diff options
Diffstat (limited to 'sys-utils/cytune.c')
-rw-r--r-- | sys-utils/cytune.c | 424 |
1 files changed, 424 insertions, 0 deletions
diff --git a/sys-utils/cytune.c b/sys-utils/cytune.c new file mode 100644 index 000000000..32a27006b --- /dev/null +++ b/sys-utils/cytune.c @@ -0,0 +1,424 @@ +/* cytune.c -- Tune Cyclades driver + * + * Copyright 1995 Nick Simicich (njs@scifi.emi.net) + * + * Modifications by Rik Faith (faith@cs.unc.edu) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Nick Simicich + * 4. Neither the name of the Nick Simicich nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY NICK SIMICICH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL NICK SIMICICH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/serial.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <linux/tty.h> +#include <termios.h> +#include <linux/tqueue.h> +#include <linux/cyclades.h> +#include <signal.h> + +#if 0 +#ifndef XMIT +# include <linux/version.h> +# if LINUX_VERSION_CODE > 66056 +# define XMIT +# endif +#endif +#endif + /* Until it gets put in the kernel, + toggle by hand. */ +#undef XMIT + +struct cyclades_control { + struct cyclades_monitor c; + int cfile; + int maxmax; + double maxtran; + double maxxmit; + unsigned long threshold_value; + unsigned long timeout_value; +}; +struct cyclades_control *cmon; +int cmon_index; + +#define mvtime(tvpto, tvpfrom) (((tvpto)->tv_sec = (tvpfrom)->tv_sec),(tvpto)->tv_usec = (tvpfrom)->tv_usec) + + +inline double dtime(struct timeval * tvpnew, struct timeval * tvpold) { + double diff; + diff = (double)tvpnew->tv_sec - (double)tvpold->tv_sec; + diff += ((double)tvpnew->tv_usec - (double)tvpold->tv_usec)/1000000; + return diff; +} + +static int global_argc, global_optind; +static char ***global_argv; + +void summary(int signal) { + struct cyclades_control *cc; + + int argc, optind; + char **argv; + + int i,j; + + argc = global_argc; + argv = *global_argv; + optind = global_optind; + + if (signal > 0) { + for(i = optind; i < argc; i ++) { + j = i - optind; + cc = &cmon[cmon_index]; + fprintf(stderr, "File %s, For threshold value %lu, Maximum characters " + "in fifo were %d,\nand the maximum transfer rate in " + "characters/second was %f\n", + argv[i], + cc->threshold_value, + cc->maxmax, + cc->maxtran); + } + + exit(0); + } + cc = &cmon[cmon_index]; + if (cc->threshold_value > 0 && signal != -1) { + fprintf(stderr, "File %s, For threshold value %lu and timrout value %lu," + " Maximum characters " + "in fifo were %d,\nand the maximum transfer rate in " + "characters/second was %f\n", + argv[cmon_index+optind], + cc->threshold_value, + cc->timeout_value, + cc->maxmax, + cc->maxtran); + } + cc->maxmax = 0; + cc->maxtran = 0.0; + cc->threshold_value = 0; + cc->timeout_value = 0; +} + +static int query = 0; +static int interval = 1; + +static int set = 0; +static int set_val = -1; +static int get = 0; + +static int set_def = 0; +static int set_def_val = -1; +static int get_def = 0; + +static int set_time = 0; +static int set_time_val = -1; + +static int set_def_time = 0; +static int set_def_time_val = -1; + + +int main(int argc, char *argv[]) { + + struct timeval lasttime, thistime; + struct timezone tz = {0,DST_NONE}; + double diff; + int errflg = 0; + int file; + int numfiles; + struct cyclades_monitor cywork; + + int i; + extern char *optarg; + extern int optind; + unsigned long threshold_value; + unsigned long timeout_value; + double xfer_rate; +#ifdef XMIT + double xmit_rate; +#endif + + global_argc = argc; /* For signal routine. */ + global_argv = &argv; /* For signal routine. */ + + while (EOF != (i = getopt(argc, argv, + "qs:S:t:T:gGi:"))) { + switch (i) { + case 'q': + query = 1; + break; + case 'i': + interval = atoi(optarg); + if(interval <= 0) { + fprintf(stderr, "Invalid interval value: %s\n",optarg); + errflg ++; + } + break; + case 's': + ++set; + set_val = atoi(optarg); + if(set_val <= 0 || set_val > 12) { + fprintf(stderr, "Invalid set value: %s\n",optarg); + errflg ++; + } + break; + case 'S': + ++set_def; + set_def_val = atoi(optarg); + if(set_def_val < 0 || set_def_val > 12) { + fprintf(stderr, "Invalid default value: %s\n",optarg); + errflg ++; + } + break; + case 't': + ++set_time; + set_time_val = atoi(optarg); + if(set_time_val <= 0 || set_time_val > 255) { + fprintf(stderr, "Invalid set time value: %s\n",optarg); + errflg ++; + } + break; + case 'T': + ++set_def_time; + set_def_time_val = atoi(optarg); + if(set_def_time_val < 0 || set_def_time_val > 255) { + fprintf(stderr, "Invalid default time value: %s\n",optarg); + errflg ++; + } + break; + case 'g': ++get; break; + case 'G': ++get_def; break; + default: + errflg ++; + } + } + numfiles = argc - optind; + if(errflg || (numfiles == 0) + || (!query && !set && !set_def && + !get && !get_def && !set_time && !set_def_time) || + (set && set_def) || (set_time && set_def_time) || + (get && get_def)) { + fprintf(stderr, + "Usage: %s [-q [-i interval]]" + " ([-s value]|[-S value]) ([-t value]|[-T value])" + " [-g|-G] file [file...]\n", + argv[0]); + exit(1); + } + + global_optind = optind; /* For signal routine. */ + + if (set || set_def) { + for(i = optind;i < argc;i ++) { + file = open(argv[i],O_RDONLY); + if(file == -1) { + fprintf(stderr, "Can't open %s: %s\n",argv[i],strerror(errno)); + exit(1); + } + if(ioctl(file, + set ? CYSETTHRESH : CYSETDEFTHRESH, + set ? set_val : set_def_val)) { + fprintf(stderr, "Can't set %s to threshold %d: %s\n", + argv[i],set?set_val:set_def_val,strerror(errno)); + exit(1); + } + } + } + if (set_time || set_def_time) { + for(i = optind;i < argc;i ++) { + file = open(argv[i],O_RDONLY); + if(file == -1) { + fprintf(stderr, "Can't open %s: %s\n",argv[i],strerror(errno)); + exit(1); + } + if(ioctl(file, + set_time ? CYSETTIMEOUT : CYSETDEFTIMEOUT, + set_time ? set_time_val : set_def_time_val)) { + fprintf(stderr, "Can't set %s to time threshold %d: %s\n", + argv[i],set_time?set_time_val:set_def_time_val,strerror(errno)); + exit(1); + } + } + } + + if (get || get_def) { + for(i = optind;i < argc;i ++) { + file = open(argv[i],O_RDONLY); + if(file == -1) { + fprintf(stderr, "Can't open %s: %s\n",argv[i],strerror(errno)); + exit(1); + } + if(ioctl(file, get ? CYGETTHRESH : CYGETDEFTHRESH, &threshold_value)) { + fprintf(stderr, "Can't get threshold for %s: %s\n", + argv[i],strerror(errno)); + exit(1); + } + if(ioctl(file, get ? CYGETTIMEOUT : CYGETDEFTIMEOUT, &timeout_value)) { + fprintf(stderr, "Can't get timeout for %s: %s\n", + argv[i],strerror(errno)); + exit(1); + } + printf("%s: %ld %s threshold and %ld %s timeout\n", + argv[i], threshold_value, + get?"current":"default", + timeout_value, + get?"current":"default"); + } + } + + if(!query) return 0; /* must have been something earlier */ + + /* query stuff after this line */ + + cmon = (struct cyclades_control *) malloc(sizeof (struct cyclades_control) + * numfiles); + if(!cmon) { + perror("malloc failed"); + exit(1); + } + if(signal(SIGINT, summary)|| + signal(SIGQUIT, summary)|| + signal(SIGTERM, summary)) { + perror("Can't set signal handler"); + exit(1); + } + if(gettimeofday(&lasttime,&tz)) { + perror("gettimeofday failed"); + exit(1); + } + for(i = optind; i < argc; i ++) { + cmon_index = i - optind; + cmon[cmon_index].cfile = open(argv[i], O_RDONLY); + if(-1 == cmon[cmon_index].cfile) { + fprintf(stderr, "Can't open %s: %s\n",argv[i],strerror(errno)); + exit(1); + } + if(ioctl(cmon[cmon_index].cfile, CYGETMON, &cmon[cmon_index].c)) { + fprintf(stderr, "Can't issue CYGETMON on %s: %s\n", + argv[i],strerror(errno)); + exit(1); + } + summary(-1); + if(ioctl(cmon[cmon_index].cfile, CYGETTHRESH, &threshold_value)) { + fprintf(stderr, "Can't get threshold for %s: %s\n", + argv[i],strerror(errno)); + exit(1); + } + if(ioctl(cmon[cmon_index].cfile, CYGETTIMEOUT, &timeout_value)) { + fprintf(stderr, "Can't get timeout for %s: %s\n", + argv[i],strerror(errno)); + exit(1); + } + } + while(1) { + sleep(interval); + + if(gettimeofday(&thistime,&tz)) { + perror("gettimeofday failed"); + exit(1); + } + diff = dtime(&thistime, &lasttime); + mvtime(&lasttime, &thistime); + + for(i = optind; i < argc; i ++) { + cmon_index = i - optind; + if(ioctl(cmon[cmon_index].cfile, CYGETMON, &cywork)) { + fprintf(stderr, "Can't issue CYGETMON on %s: %s\n", + argv[i],strerror(errno)); + exit(1); + } + if(ioctl(cmon[cmon_index].cfile, CYGETTHRESH, &threshold_value)) { + fprintf(stderr, "Can't get threshold for %s: %s\n", + argv[i],strerror(errno)); + exit(1); + } + if(ioctl(cmon[cmon_index].cfile, CYGETTIMEOUT, &timeout_value)) { + fprintf(stderr, "Can't get timeout for %s: %s\n", + argv[i],strerror(errno)); + exit(1); + } + + xfer_rate = cywork.char_count/diff; +#ifdef XMIT + xmit_rate = cywork.send_count/diff; +#endif + + if(threshold_value != cmon[cmon_index].threshold_value || + timeout_value != cmon[cmon_index].timeout_value) { + summary(-2); + /* Note that the summary must come before the setting of */ + /* threshold_value */ + cmon[cmon_index].threshold_value = threshold_value; + cmon[cmon_index].timeout_value = timeout_value; + } else { + /* Don't record this first cycle after change */ + if(xfer_rate > cmon[cmon_index].maxtran) + cmon[cmon_index].maxtran = xfer_rate; +#ifdef XMIT + if(xmit_rate > cmon[cmon_index].maxxmit) + cmon[cmon_index].maxxmit = xmit_rate; +#endif + if(cywork.char_max > cmon[cmon_index].maxmax) + cmon[cmon_index].maxmax = cywork.char_max; + } + +#ifdef XMIT + printf("%s: %lu ints, %lu/%lu chars; " + "fifo: %lu thresh, %lu tmout, " + "%lu max, %lu now\n", + argv[i], + cywork.int_count,cywork.char_count,cywork.send_count, + threshold_value,timeout_value, + cywork.char_max,cywork.char_last); + printf(" %f int/sec; %f rec, %f send (char/sec)\n", + cywork.int_count/diff, + xfer_rate, + xmit_rate); +#else + printf("%s: %lu ints, %lu chars; " + "fifo: %lu thresh, %lu tmout, " + "%lu max, %lu now\n", + argv[i], + cywork.int_count,cywork.char_count, + threshold_value,timeout_value, + cywork.char_max,cywork.char_last); + printf(" %f int/sec; %f rec (char/sec)\n", + cywork.int_count/diff, + xfer_rate); +#endif + memcpy(&cmon[cmon_index].c, &cywork, sizeof (struct cyclades_monitor)); + } + } + + return 0; +} |