]> git.ipfire.org Git - thirdparty/util-linux.git/blame - sys-utils/cytune.c
Imported from util-linux-2.8 tarball.
[thirdparty/util-linux.git] / sys-utils / cytune.c
CommitLineData
726f69e2
KZ
1/* cytune.c -- Tune Cyclades driver
2 *
3 * Copyright 1995 Nick Simicich (njs@scifi.emi.net)
4 *
5 * Modifications by Rik Faith (faith@cs.unc.edu)
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the Nick Simicich
18 * 4. Neither the name of the Nick Simicich nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY NICK SIMICICH AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL NICK SIMICICH OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 */
35
36#include <stdio.h>
37#include <stdlib.h>
726f69e2
KZ
38#include <sys/types.h>
39#include <sys/time.h>
40#include <sys/ioctl.h>
41#include <unistd.h>
fd6b7a7f 42#include <string.h>
726f69e2
KZ
43#include <fcntl.h>
44#include <errno.h>
45#include <linux/tty.h>
46#include <termios.h>
2b6fc908
KZ
47#if 0
48#include <linux/tqueue.h> /* required for old kernels */
49 /* compilation errors on other kernels */
50#endif
726f69e2
KZ
51#include <linux/cyclades.h>
52#include <signal.h>
53
54#if 0
55#ifndef XMIT
56# include <linux/version.h>
57# if LINUX_VERSION_CODE > 66056
58# define XMIT
59# endif
60#endif
61#endif
62 /* Until it gets put in the kernel,
63 toggle by hand. */
64#undef XMIT
65
66struct cyclades_control {
67 struct cyclades_monitor c;
68 int cfile;
69 int maxmax;
70 double maxtran;
71 double maxxmit;
72 unsigned long threshold_value;
73 unsigned long timeout_value;
74};
75struct cyclades_control *cmon;
76int cmon_index;
77
78#define mvtime(tvpto, tvpfrom) (((tvpto)->tv_sec = (tvpfrom)->tv_sec),(tvpto)->tv_usec = (tvpfrom)->tv_usec)
79
80
81inline double dtime(struct timeval * tvpnew, struct timeval * tvpold) {
82 double diff;
83 diff = (double)tvpnew->tv_sec - (double)tvpold->tv_sec;
84 diff += ((double)tvpnew->tv_usec - (double)tvpold->tv_usec)/1000000;
85 return diff;
86}
87
88static int global_argc, global_optind;
89static char ***global_argv;
90
91void summary(int signal) {
92 struct cyclades_control *cc;
93
94 int argc, optind;
95 char **argv;
96
97 int i,j;
98
99 argc = global_argc;
100 argv = *global_argv;
101 optind = global_optind;
102
103 if (signal > 0) {
104 for(i = optind; i < argc; i ++) {
105 j = i - optind;
106 cc = &cmon[cmon_index];
107 fprintf(stderr, "File %s, For threshold value %lu, Maximum characters "
108 "in fifo were %d,\nand the maximum transfer rate in "
109 "characters/second was %f\n",
110 argv[i],
111 cc->threshold_value,
112 cc->maxmax,
113 cc->maxtran);
114 }
115
116 exit(0);
117 }
118 cc = &cmon[cmon_index];
119 if (cc->threshold_value > 0 && signal != -1) {
120 fprintf(stderr, "File %s, For threshold value %lu and timrout value %lu,"
121 " Maximum characters "
122 "in fifo were %d,\nand the maximum transfer rate in "
123 "characters/second was %f\n",
124 argv[cmon_index+optind],
125 cc->threshold_value,
126 cc->timeout_value,
127 cc->maxmax,
128 cc->maxtran);
129 }
130 cc->maxmax = 0;
131 cc->maxtran = 0.0;
132 cc->threshold_value = 0;
133 cc->timeout_value = 0;
134}
135
136static int query = 0;
137static int interval = 1;
138
139static int set = 0;
140static int set_val = -1;
141static int get = 0;
142
143static int set_def = 0;
144static int set_def_val = -1;
145static int get_def = 0;
146
147static int set_time = 0;
148static int set_time_val = -1;
149
150static int set_def_time = 0;
151static int set_def_time_val = -1;
152
153
154int main(int argc, char *argv[]) {
155
156 struct timeval lasttime, thistime;
fd6b7a7f 157 struct timezone tz = {0,0};
726f69e2
KZ
158 double diff;
159 int errflg = 0;
160 int file;
161 int numfiles;
162 struct cyclades_monitor cywork;
163
164 int i;
165 extern char *optarg;
166 extern int optind;
167 unsigned long threshold_value;
168 unsigned long timeout_value;
169 double xfer_rate;
170#ifdef XMIT
171 double xmit_rate;
172#endif
173
174 global_argc = argc; /* For signal routine. */
175 global_argv = &argv; /* For signal routine. */
176
177 while (EOF != (i = getopt(argc, argv,
178 "qs:S:t:T:gGi:"))) {
179 switch (i) {
180 case 'q':
181 query = 1;
182 break;
183 case 'i':
184 interval = atoi(optarg);
185 if(interval <= 0) {
186 fprintf(stderr, "Invalid interval value: %s\n",optarg);
187 errflg ++;
188 }
189 break;
190 case 's':
191 ++set;
192 set_val = atoi(optarg);
193 if(set_val <= 0 || set_val > 12) {
194 fprintf(stderr, "Invalid set value: %s\n",optarg);
195 errflg ++;
196 }
197 break;
198 case 'S':
199 ++set_def;
200 set_def_val = atoi(optarg);
201 if(set_def_val < 0 || set_def_val > 12) {
202 fprintf(stderr, "Invalid default value: %s\n",optarg);
203 errflg ++;
204 }
205 break;
206 case 't':
207 ++set_time;
208 set_time_val = atoi(optarg);
209 if(set_time_val <= 0 || set_time_val > 255) {
210 fprintf(stderr, "Invalid set time value: %s\n",optarg);
211 errflg ++;
212 }
213 break;
214 case 'T':
215 ++set_def_time;
216 set_def_time_val = atoi(optarg);
217 if(set_def_time_val < 0 || set_def_time_val > 255) {
218 fprintf(stderr, "Invalid default time value: %s\n",optarg);
219 errflg ++;
220 }
221 break;
222 case 'g': ++get; break;
223 case 'G': ++get_def; break;
224 default:
225 errflg ++;
226 }
227 }
228 numfiles = argc - optind;
229 if(errflg || (numfiles == 0)
230 || (!query && !set && !set_def &&
231 !get && !get_def && !set_time && !set_def_time) ||
232 (set && set_def) || (set_time && set_def_time) ||
233 (get && get_def)) {
234 fprintf(stderr,
235 "Usage: %s [-q [-i interval]]"
236 " ([-s value]|[-S value]) ([-t value]|[-T value])"
237 " [-g|-G] file [file...]\n",
238 argv[0]);
239 exit(1);
240 }
241
242 global_optind = optind; /* For signal routine. */
243
244 if (set || set_def) {
245 for(i = optind;i < argc;i ++) {
246 file = open(argv[i],O_RDONLY);
247 if(file == -1) {
248 fprintf(stderr, "Can't open %s: %s\n",argv[i],strerror(errno));
249 exit(1);
250 }
251 if(ioctl(file,
252 set ? CYSETTHRESH : CYSETDEFTHRESH,
253 set ? set_val : set_def_val)) {
254 fprintf(stderr, "Can't set %s to threshold %d: %s\n",
255 argv[i],set?set_val:set_def_val,strerror(errno));
256 exit(1);
257 }
258 }
259 }
260 if (set_time || set_def_time) {
261 for(i = optind;i < argc;i ++) {
262 file = open(argv[i],O_RDONLY);
263 if(file == -1) {
264 fprintf(stderr, "Can't open %s: %s\n",argv[i],strerror(errno));
265 exit(1);
266 }
267 if(ioctl(file,
268 set_time ? CYSETTIMEOUT : CYSETDEFTIMEOUT,
269 set_time ? set_time_val : set_def_time_val)) {
270 fprintf(stderr, "Can't set %s to time threshold %d: %s\n",
271 argv[i],set_time?set_time_val:set_def_time_val,strerror(errno));
272 exit(1);
273 }
274 }
275 }
276
277 if (get || get_def) {
278 for(i = optind;i < argc;i ++) {
279 file = open(argv[i],O_RDONLY);
280 if(file == -1) {
281 fprintf(stderr, "Can't open %s: %s\n",argv[i],strerror(errno));
282 exit(1);
283 }
284 if(ioctl(file, get ? CYGETTHRESH : CYGETDEFTHRESH, &threshold_value)) {
285 fprintf(stderr, "Can't get threshold for %s: %s\n",
286 argv[i],strerror(errno));
287 exit(1);
288 }
289 if(ioctl(file, get ? CYGETTIMEOUT : CYGETDEFTIMEOUT, &timeout_value)) {
290 fprintf(stderr, "Can't get timeout for %s: %s\n",
291 argv[i],strerror(errno));
292 exit(1);
293 }
294 printf("%s: %ld %s threshold and %ld %s timeout\n",
295 argv[i], threshold_value,
296 get?"current":"default",
297 timeout_value,
298 get?"current":"default");
299 }
300 }
301
302 if(!query) return 0; /* must have been something earlier */
303
304 /* query stuff after this line */
305
306 cmon = (struct cyclades_control *) malloc(sizeof (struct cyclades_control)
307 * numfiles);
308 if(!cmon) {
309 perror("malloc failed");
310 exit(1);
311 }
312 if(signal(SIGINT, summary)||
313 signal(SIGQUIT, summary)||
314 signal(SIGTERM, summary)) {
315 perror("Can't set signal handler");
316 exit(1);
317 }
318 if(gettimeofday(&lasttime,&tz)) {
319 perror("gettimeofday failed");
320 exit(1);
321 }
322 for(i = optind; i < argc; i ++) {
323 cmon_index = i - optind;
324 cmon[cmon_index].cfile = open(argv[i], O_RDONLY);
325 if(-1 == cmon[cmon_index].cfile) {
326 fprintf(stderr, "Can't open %s: %s\n",argv[i],strerror(errno));
327 exit(1);
328 }
329 if(ioctl(cmon[cmon_index].cfile, CYGETMON, &cmon[cmon_index].c)) {
330 fprintf(stderr, "Can't issue CYGETMON on %s: %s\n",
331 argv[i],strerror(errno));
332 exit(1);
333 }
334 summary(-1);
335 if(ioctl(cmon[cmon_index].cfile, CYGETTHRESH, &threshold_value)) {
336 fprintf(stderr, "Can't get threshold for %s: %s\n",
337 argv[i],strerror(errno));
338 exit(1);
339 }
340 if(ioctl(cmon[cmon_index].cfile, CYGETTIMEOUT, &timeout_value)) {
341 fprintf(stderr, "Can't get timeout for %s: %s\n",
342 argv[i],strerror(errno));
343 exit(1);
344 }
345 }
346 while(1) {
347 sleep(interval);
348
349 if(gettimeofday(&thistime,&tz)) {
350 perror("gettimeofday failed");
351 exit(1);
352 }
353 diff = dtime(&thistime, &lasttime);
354 mvtime(&lasttime, &thistime);
355
356 for(i = optind; i < argc; i ++) {
357 cmon_index = i - optind;
358 if(ioctl(cmon[cmon_index].cfile, CYGETMON, &cywork)) {
359 fprintf(stderr, "Can't issue CYGETMON on %s: %s\n",
360 argv[i],strerror(errno));
361 exit(1);
362 }
363 if(ioctl(cmon[cmon_index].cfile, CYGETTHRESH, &threshold_value)) {
364 fprintf(stderr, "Can't get threshold for %s: %s\n",
365 argv[i],strerror(errno));
366 exit(1);
367 }
368 if(ioctl(cmon[cmon_index].cfile, CYGETTIMEOUT, &timeout_value)) {
369 fprintf(stderr, "Can't get timeout for %s: %s\n",
370 argv[i],strerror(errno));
371 exit(1);
372 }
373
374 xfer_rate = cywork.char_count/diff;
375#ifdef XMIT
376 xmit_rate = cywork.send_count/diff;
377#endif
378
379 if(threshold_value != cmon[cmon_index].threshold_value ||
380 timeout_value != cmon[cmon_index].timeout_value) {
381 summary(-2);
382 /* Note that the summary must come before the setting of */
383 /* threshold_value */
384 cmon[cmon_index].threshold_value = threshold_value;
385 cmon[cmon_index].timeout_value = timeout_value;
386 } else {
387 /* Don't record this first cycle after change */
388 if(xfer_rate > cmon[cmon_index].maxtran)
389 cmon[cmon_index].maxtran = xfer_rate;
390#ifdef XMIT
391 if(xmit_rate > cmon[cmon_index].maxxmit)
392 cmon[cmon_index].maxxmit = xmit_rate;
393#endif
394 if(cywork.char_max > cmon[cmon_index].maxmax)
395 cmon[cmon_index].maxmax = cywork.char_max;
396 }
397
398#ifdef XMIT
399 printf("%s: %lu ints, %lu/%lu chars; "
400 "fifo: %lu thresh, %lu tmout, "
401 "%lu max, %lu now\n",
402 argv[i],
403 cywork.int_count,cywork.char_count,cywork.send_count,
404 threshold_value,timeout_value,
405 cywork.char_max,cywork.char_last);
406 printf(" %f int/sec; %f rec, %f send (char/sec)\n",
407 cywork.int_count/diff,
408 xfer_rate,
409 xmit_rate);
410#else
411 printf("%s: %lu ints, %lu chars; "
412 "fifo: %lu thresh, %lu tmout, "
413 "%lu max, %lu now\n",
414 argv[i],
415 cywork.int_count,cywork.char_count,
416 threshold_value,timeout_value,
417 cywork.char_max,cywork.char_last);
418 printf(" %f int/sec; %f rec (char/sec)\n",
419 cywork.int_count/diff,
420 xfer_rate);
421#endif
422 memcpy(&cmon[cmon_index].c, &cywork, sizeof (struct cyclades_monitor));
423 }
424 }
425
426 return 0;
427}