Print this page
10120 smatch indenting fixes for usr/src/cmd
Reviewed by: Gergő Doma <domag02@gmail.com>
Portions contributed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/busstat/busstat.c
+++ new/usr/src/cmd/busstat/busstat.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 -#pragma ident "%Z%%M% %I% %E% SMI"
27 +/*
28 + * Copyright (c) 2018, Joyent, Inc.
29 + */
28 30
29 31 #include <stdio.h>
30 32 #include <stdlib.h>
31 33 #include <strings.h>
32 34 #include <time.h>
33 35 #include <signal.h>
34 36 #include <sys/types.h>
35 37 #include <sys/stat.h>
36 38 #include <sys/time.h>
37 39 #include <sys/modctl.h>
38 40 #include <sys/systeminfo.h>
39 41 #include <limits.h>
40 42 #include <signal.h>
41 43 #include <fcntl.h>
42 44 #include <unistd.h>
43 45 #include <stropts.h>
44 46 #include <locale.h>
45 47 #include <libintl.h>
46 48 #include <libgen.h>
47 49 #include <nl_types.h>
48 50 #include <kstat.h>
49 51 #include <ctype.h>
50 52 #include <signal.h>
51 53 #include <errno.h>
52 54 #include <time.h>
53 55
54 56 #include "busstat.h"
55 57
56 58
57 59 /* Global defines */
58 60 static int delta = TRUE;
59 61 static int banner = TRUE;
60 62 static int max_pic_num = 1;
61 63 static int initial_read = TRUE;
62 64 static char *pgmname;
63 65 static kstat_ctl_t *kc; /* libkstat cookie */
64 66 static dev_node_t *dev_list_head = NULL;
65 67 static dev_node_t *dev_list_tail = NULL;
66 68
67 69 /*
68 70 * Global flags.
69 71 */
70 72 static char curr_dev_name[KSTAT_STRLEN];
71 73 static int curr_inst_num;
72 74
73 75 static void print_evt(void);
74 76 static void print_dev(int, char *);
75 77 static void parse_cmd(int);
76 78 static void parse_dev_inst(char *);
77 79 static void parse_pic_evt(char *);
78 80 static void add_dev_node(char *, int);
79 81 static void add_all_dev_node(char *);
80 82 static void add_evt_node(dev_node_t *);
81 83 static void modify_evt_node(dev_node_t *, char *);
82 84 static void prune_evt_nodes(dev_node_t *);
83 85 static void setup_evts(void);
84 86 static void set_evt(dev_node_t *);
85 87 static void read_evts(void);
86 88 static void read_r_evt_node(dev_node_t *, int, kstat_named_t *);
87 89 static void read_w_evt_node(dev_node_t *, int, kstat_named_t *);
88 90 static void check_dr_ops(void);
89 91 static void remove_dev_node(dev_node_t *);
90 92 static dev_node_t *find_dev_node(char *, int, int);
91 93 static kstat_t *find_pic_kstat(char *, int, char *);
92 94 static int64_t is_num(char *);
93 95 static void print_banner(void);
94 96 static void print_timestamp(void);
95 97 static void usage(void);
96 98 static void *safe_malloc(size_t);
97 99 static void set_timer(int);
98 100 static void handle_sig(int);
99 101 static int strisnum(const char *);
100 102
101 103 int
102 104 main(int argc, char **argv)
103 105 {
104 106 int c, i;
105 107 int interval = 1; /* Interval between displays */
106 108 int count = 0; /* Number of times to sample */
107 109 int write_evts = FALSE;
108 110 int pos = 0;
109 111
110 112 #if !defined(TEXT_DOMAIN)
111 113 #define TEXT_DOMAIN "SYS_TEST"
112 114 #endif
113 115
114 116 /* For I18N */
115 117 (void) setlocale(LC_ALL, "");
116 118 (void) textdomain(TEXT_DOMAIN);
117 119
118 120 pgmname = basename(argv[0]);
119 121
120 122 if ((kc = kstat_open()) == NULL) {
121 123 (void) fprintf(stderr, gettext("%s: could not "
122 124 "open /dev/kstat\n"), pgmname);
123 125 exit(1);
124 126 }
125 127
126 128 while ((c = getopt(argc, argv, "e:w:r:ahln")) != EOF) {
127 129 switch (c) {
128 130 case 'a':
129 131 delta = FALSE;
130 132 break;
131 133 case 'e':
132 134 (void) print_evt();
133 135 break;
134 136 case 'h':
135 137 usage();
136 138 break;
137 139 case 'l':
138 140 (void) print_dev(argc, argv[argc-1]);
139 141 break;
140 142 case 'n':
141 143 banner = FALSE;
142 144 break;
143 145 case 'r':
144 146 (void) parse_cmd(READ_EVT);
145 147 break;
146 148 case 'w':
147 149 (void) parse_cmd(WRITE_EVT);
148 150 write_evts = TRUE;
149 151 break;
150 152 default:
151 153 (void) fprintf(stderr, gettext("%s: invalid "
152 154 "option\n"), pgmname);
153 155 usage();
154 156 break;
155 157 }
156 158 }
157 159
158 160 if ((argc == 1) || (dev_list_head == NULL))
159 161 usage();
160 162
161 163 /*
162 164 * validate remaining operands are numeric.
163 165 */
164 166 pos = optind;
165 167 while (pos < argc) {
166 168 if (strisnum(argv[pos]) == 0) {
167 169 (void) fprintf(stderr,
168 170 gettext("%s: syntax error\n"),
169 171 pgmname);
170 172 usage();
171 173 }
172 174 pos++;
173 175 }
174 176
175 177 if (optind < argc) {
176 178 if ((interval = atoi(argv[optind])) == 0) {
177 179 (void) fprintf(stderr, gettext("%s: invalid "
178 180 "interval value\n"), pgmname);
179 181 exit(1);
180 182 }
181 183
182 184 optind++;
183 185 if (optind < argc)
184 186 if ((count = atoi(argv[optind])) <= 0) {
185 187 (void) fprintf(stderr, gettext("%s: "
186 188 "invalid iteration value.\n"),
187 189 pgmname);
188 190 exit(1);
189 191 }
190 192 }
191 193
192 194 set_timer(interval);
193 195
194 196 /*
195 197 * Set events for the first time.
196 198 */
197 199 if (write_evts == TRUE)
198 200 setup_evts();
199 201
200 202
201 203 if (count > 0) {
202 204 for (i = 0; i < count; i++) {
203 205 if (banner)
204 206 print_banner();
205 207
206 208 check_dr_ops();
207 209 read_evts();
208 210 (void) fflush(stdout);
209 211 (void) pause();
210 212 }
211 213 } else {
212 214 for (;;) {
213 215 if (banner)
214 216 print_banner();
215 217
216 218 check_dr_ops();
217 219 read_evts();
218 220 (void) fflush(stdout);
219 221 (void) pause();
220 222 }
221 223 }
222 224
223 225 read_evts();
224 226 return (0);
225 227 }
226 228
227 229
228 230 /*
229 231 * Display all the events that can be set on a device.
230 232 */
231 233 void
232 234 print_evt()
233 235 {
234 236 kstat_t *cnt_ksp;
235 237 kstat_t *pic_ksp;
236 238 kstat_named_t *cnt_data;
237 239 kstat_named_t *pic_data;
238 240 char *device = NULL;
239 241 char *value;
240 242 int inst_num = -1;
241 243 int i = 0;
242 244 int j;
243 245
244 246 value = optarg;
245 247
246 248 /*
247 249 * Search through the value string for a numeric char which will
248 250 * be the device instance number, if the user specified one. If
249 251 * the user did not specify an instance then the return value from
250 252 * strscpn will be equal to the string length. In this case we
251 253 * use a default value of -1 for the kstat_lookup which causes
252 254 * the device number to be ignored during the search.
253 255 */
254 256 if (((i = strcspn(value, "0123456789")) > 0) && (i != strlen(value))) {
255 257
256 258 device = safe_malloc(sizeof (char) * i+1);
257 259 device[i] = '\0';
258 260 (void) strncpy(device, value, i);
259 261
260 262 value = value + i;
261 263 inst_num = atoi(value);
262 264 }
263 265
264 266 /*
265 267 * No instance specified.
266 268 */
267 269 if (device == NULL)
268 270 device = value;
269 271
270 272 /*
271 273 * Get the "counters" kstat, so that we can get
272 274 * the names of the "picN" kstats, which hold the
273 275 * event names.
274 276 */
275 277 if ((cnt_ksp = kstat_lookup(kc, device, inst_num, "counters"))
276 278 == NULL) {
277 279 (void) fprintf(stderr, gettext("%s: invalid device "
278 280 "name or instance (%s)\n"), pgmname, device);
279 281 exit(1);
280 282 }
281 283
282 284 if (kstat_read(kc, cnt_ksp, NULL) == FAIL) {
283 285 (void) fprintf(stderr, gettext("%s: could not read "
284 286 "kstat.\n"), pgmname);
285 287 exit(1);
286 288 }
287 289
288 290 cnt_data = (kstat_named_t *)cnt_ksp->ks_data;
289 291
290 292 /*
291 293 * Start at 1 as the first entry in the "counters"
292 294 * kstat is the pcr value/name. We are looking for the
293 295 * name of the "picN" kstats. For each one found store
294 296 * a pointer to it in pic_data[].
295 297 */
296 298 if (cnt_ksp->ks_ndata <= 1) {
297 299 (void) fprintf(stderr, gettext("%s: invalid kstat "
298 300 "structure.\n"), pgmname);
299 301 exit(1);
300 302 }
301 303
302 304 for (i = 1; i < cnt_ksp->ks_ndata; i++) {
303 305 if ((pic_ksp = find_pic_kstat(device, inst_num,
304 306 cnt_data[i].name)) == NULL) {
305 307
306 308 (void) fprintf(stderr, gettext("%s: could not read "
307 309 "pic kstat data structure for %s\n"),
308 310 pgmname, cnt_ksp->ks_module);
309 311
310 312 exit(1);
311 313 }
312 314
313 315 if (kstat_read(kc, pic_ksp, NULL) == FAIL) {
314 316 (void) fprintf(stderr, gettext("%s: could not read "
315 317 "pic kstat.\n"), pgmname);
316 318
317 319 exit(1);
318 320 }
319 321
320 322 pic_data = (kstat_named_t *)pic_ksp->ks_data;
321 323
322 324 (void) printf(gettext("pic%-8d\n"), i-1);
323 325
324 326 for (j = 0; j < pic_ksp->ks_ndata-1; j++) {
325 327 (void) printf("%-30s\n", pic_data[j].name);
326 328 }
327 329
328 330 (void) printf("\n");
329 331 }
330 332
331 333 exit(0);
332 334 }
333 335
334 336
335 337 /*
336 338 * Display the names and instances of the devices on the system
337 339 * which can support performance monitoring.
338 340 */
339 341 void
340 342 print_dev(int argc, char *str)
341 343 {
342 344 kstat_t *ksp;
343 345 static int first_time = 1;
344 346
345 347 if ((argc > 2) || (strcmp(str, "-l") != 0)) {
346 348 (void) fprintf(stderr, gettext("%s: no arguments "
347 349 "permitted with -l option.\n"),
348 350 pgmname);
349 351 usage();
350 352 exit(1);
351 353 }
352 354
353 355 /*
354 356 * For each device node, print the node name (device
355 357 * name) and the instance numbers.
356 358 */
357 359 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
358 360 if ((strcmp(ksp->ks_class, "bus") == 0) &&
359 361 (strcmp(ksp->ks_name, "counters") == 0)) {
360 362 if (first_time) {
361 363 (void) printf(gettext("Busstat "
362 364 "Device(s):\n"));
363 365 first_time = 0;
364 366 }
365 367 (void) printf("%s%d ", ksp->ks_module,
366 368 ksp->ks_instance);
367 369 }
368 370 }
369 371
370 372 if (first_time)
371 373 (void) fprintf(stderr, gettext("%s: No devices available "
372 374 "in system."), pgmname);
373 375
374 376 (void) printf("\n");
375 377
376 378 exit(0);
377 379 }
378 380
379 381 /*
380 382 * Parses the cmd line, checks all the values and
381 383 * creates the appropiate data structures.
382 384 */
383 385 void
384 386 parse_cmd(int mode)
385 387 {
386 388 char *options = optarg, *value;
387 389 int arg_num = 0;
388 390
389 391 while ((value = (char *)strtok(options, ",=")) != NULL) {
390 392 /*
↓ open down ↓ |
353 lines elided |
↑ open up ↑ |
391 393 * First arg must be device name.
392 394 */
393 395 if (!arg_num) {
394 396 parse_dev_inst(value);
395 397 } else {
396 398 if (mode == READ_EVT) {
397 399 (void) fprintf(stderr, gettext("%s: "
398 400 "event names or pic values not "
399 401 "permitted with -r option.\n"),
400 402 pgmname);
401 - usage();
403 + usage();
402 404 exit(1);
403 405 }
404 406 /*
405 407 * Now dealing with pic values.
406 408 */
407 409 parse_pic_evt(value);
408 410 }
409 411 /*
410 412 * After first strtok call, must set first arg
411 413 * to null if wish to parse rest of string.
412 414 * See strtok man page.
413 415 */
414 416 if (options != NULL)
415 417 options = NULL;
416 418 arg_num++;
417 419 }
418 420 }
419 421
420 422
421 423 /*
422 424 * Parse the device name/instance section of the
423 425 * command line.
424 426 */
425 427 void
426 428 parse_dev_inst(char *value)
427 429 {
428 430 int i;
429 431 char *device = NULL;
430 432 int malloc_flag = FALSE;
431 433
432 434 if (strlen(value) == 0) {
433 435 (void) fprintf(stderr, gettext("%s: No device name given.\n"),
434 436 pgmname);
435 437 exit(1);
436 438 }
437 439
438 440 /*
439 441 * Break string into device name and
440 442 * instance number (if given).
441 443 */
442 444 if ((i = strcspn(value, "0123456789")) > 0) {
443 445 if (i != strlen(value)) {
444 446 device = safe_malloc(sizeof (char) * i+1);
445 447 device[i] = '\0';
446 448
447 449 (void) strncpy(device, value, i);
448 450 malloc_flag = TRUE;
449 451
450 452 value = value + i;
451 453 }
452 454 }
453 455
454 456 /*
455 457 * No instance was specified so we assume
456 458 * the user wants to use ALL instances.
457 459 */
458 460 if (device == NULL) {
459 461 if ((device = value) == NULL) {
460 462 (void) fprintf(stderr, gettext("%s: no device "
461 463 "specified\n"), pgmname);
462 464 exit(1);
463 465 }
464 466
465 467 /*
466 468 * Set global flags.
467 469 */
468 470 (void) strcpy(curr_dev_name, device);
469 471 curr_inst_num = -1;
470 472
471 473 add_all_dev_node(device);
472 474 goto clean_up;
473 475 }
474 476
475 477 /*
476 478 * Set global flags.
477 479 */
478 480 (void) strcpy(curr_dev_name, device);
479 481 curr_inst_num = atoi(value);
480 482
481 483 add_dev_node(device, curr_inst_num);
482 484
483 485 clean_up:
484 486 if (malloc_flag) {
485 487 free(device);
486 488 }
487 489 }
488 490
489 491
490 492 /*
491 493 * Adds new event nodes to existing ones, modifies existing ones, or
492 494 * prunes existing ones.
493 495 *
494 496 * A specific instance call will overwrite an earlier all
495 497 * instances call, but *not* vice-versa.
496 498 *
497 499 * All the state transitions are given below.
498 500 *
499 501 *
500 502 * Call Type
501 503 * STATE | Specific Instance All Instances.
502 504 * ======================================================
503 505 * INIT | Change state to | Change state to ALL,
504 506 * | INST, add events | add events.
505 507 * | |
506 508 * INST | State unchanged, | No change.
507 509 * | Add events. |
508 510 * | |
509 511 * ALL | Change state to | State unchanged,
510 512 * | INST, replace events. | add events.
511 513 */
512 514 void
513 515 parse_pic_evt(char *value)
514 516 {
515 517 dev_node_t *dev_node;
516 518 char *evt_name;
517 519 int pic_num;
518 520
519 521 if (strlen(value) <= PIC_STR_LEN) {
520 522 (void) fprintf(stderr, gettext("%s: no pic number "
521 523 "specified.\n"), pgmname);
522 524 exit(1);
523 525 }
524 526
525 527 if (strncmp(value, "pic", PIC_STR_LEN) != 0) {
526 528 (void) fprintf(stderr, gettext("%s: missing pic "
527 529 "specifier\n"), pgmname);
528 530 usage();
529 531 }
530 532
531 533 /*
532 534 * Step over the 'pic' part of the string to
533 535 * get the pic number.
534 536 */
535 537 value = value + PIC_STR_LEN;
536 538 pic_num = atoi(value);
537 539
538 540 if ((pic_num == -1) || (pic_num > max_pic_num -1)) {
539 541 (void) fprintf(stderr, gettext("%s: invalid pic "
540 542 "number.\n"), pgmname);
541 543 exit(1);
542 544 }
543 545
544 546 if ((evt_name = (char *)strtok(NULL, "=,")) == NULL) {
545 547 (void) fprintf(stderr, gettext("%s: no event "
546 548 "specified.\n"), pgmname);
547 549 exit(1);
548 550 }
549 551
550 552 /*
551 553 * Dealing with a specific instance.
552 554 */
553 555 if (curr_inst_num >= 0) {
554 556 if ((dev_node = find_dev_node(curr_dev_name,
555 557 curr_inst_num, pic_num)) == NULL) {
556 558 (void) fprintf(stderr, gettext("%s: could not find "
557 559 "data structures for %s\n"),
558 560 pgmname, curr_dev_name);
559 561 exit(1);
560 562 }
561 563
562 564 if (dev_node->r_w == EVT_READ) {
563 565 modify_evt_node(dev_node, evt_name);
564 566 dev_node->r_w = EVT_WRITE;
565 567 dev_node->state = STATE_INST;
566 568
567 569 } else if ((dev_node->r_w == EVT_WRITE) &&
568 570 (dev_node->state == STATE_ALL)) {
569 571
570 572 prune_evt_nodes(dev_node);
571 573 modify_evt_node(dev_node, evt_name);
572 574 dev_node->state = STATE_INST;
573 575
574 576 } else if ((dev_node->r_w == EVT_WRITE) &&
575 577 (dev_node->state == STATE_INST)) {
576 578
577 579 add_evt_node(dev_node);
578 580 modify_evt_node(dev_node, evt_name);
579 581 }
580 582
581 583 return;
582 584 }
583 585
584 586 /*
585 587 * Dealing with all instances of a specific device.
586 588 */
587 589 dev_node = dev_list_head;
588 590 while (dev_node != NULL) {
589 591 if ((strcmp(dev_node->name, curr_dev_name) == 0) &&
590 592 (dev_node->pic_num == pic_num)) {
591 593
592 594 if (dev_node->r_w == EVT_READ) {
593 595 modify_evt_node(dev_node,
594 596 evt_name);
595 597
596 598 dev_node->r_w = EVT_WRITE;
597 599 dev_node->state = STATE_ALL;
598 600
599 601 } else if ((dev_node->r_w == EVT_WRITE) &&
600 602 (dev_node->state == STATE_ALL)) {
601 603
602 604 add_evt_node(dev_node);
603 605 modify_evt_node(dev_node, evt_name);
604 606
605 607 }
606 608 }
607 609 dev_node = dev_node->next;
608 610 }
609 611 }
610 612
611 613
612 614 /*
613 615 * Create a dev_node structure for this device if one does not
614 616 * already exist.
615 617 */
616 618 void
617 619 add_dev_node(char *dev_name, int inst_num)
618 620 {
619 621 dev_node_t *new_dev_node;
620 622 kstat_named_t *cnt_data;
621 623 kstat_t *cnt_ksp;
622 624 kstat_t *pic_ksp;
623 625 int pic_num;
624 626
625 627
626 628 if ((cnt_ksp = kstat_lookup(kc, dev_name,
627 629 inst_num, "counters")) == NULL) {
628 630 (void) fprintf(stderr, gettext("%s: invalid device "
629 631 "name or instance (%s%d)\n"), pgmname,
630 632 dev_name, inst_num);
631 633 exit(1);
632 634 }
633 635
634 636 if (kstat_read(kc, cnt_ksp, NULL) == FAIL) {
635 637 (void) fprintf(stderr, gettext("%s : could not read counters "
636 638 "kstat for device %s.\n"), pgmname, dev_name);
637 639 exit(1);
638 640 }
639 641
640 642 cnt_data = (kstat_named_t *)cnt_ksp->ks_data;
641 643
642 644 if (cnt_ksp->ks_ndata <= 1) {
643 645 (void) fprintf(stderr, gettext("%s : invalid "
644 646 "kstat structure.\n"), pgmname);
645 647 exit(1);
646 648 }
647 649
648 650 /*
649 651 * max_pic_num used to format headers correctly
650 652 * for printing.
651 653 */
652 654 if (cnt_ksp->ks_ndata-1 > max_pic_num)
653 655 max_pic_num = cnt_ksp->ks_ndata-1;
654 656
655 657 /* for each pic... */
656 658 for (pic_num = 0; pic_num < cnt_ksp->ks_ndata-1; pic_num++) {
657 659 if (find_dev_node(dev_name, inst_num, pic_num) != NULL) {
658 660 /* Node already exists */
659 661 continue;
660 662 }
661 663
662 664 new_dev_node = safe_malloc(sizeof (dev_node_t));
663 665 bzero(new_dev_node, sizeof (dev_node_t));
664 666
665 667 (void) strcpy(new_dev_node->name, dev_name);
666 668 new_dev_node->dev_inst = inst_num;
667 669 new_dev_node->pic_num = pic_num;
668 670
669 671 new_dev_node->cnt_ksp = cnt_ksp;
670 672
671 673 if ((pic_ksp = find_pic_kstat(dev_name, inst_num,
672 674 cnt_data[pic_num+1].name)) == NULL) {
673 675
674 676 (void) fprintf(stderr, gettext("%s: could not find "
675 677 "pic kstat structure for %s.\n"),
676 678 pgmname, cnt_ksp->ks_module);
677 679 exit(1);
678 680 }
679 681
680 682 new_dev_node->pic_ksp = pic_ksp;
681 683
682 684 add_evt_node(new_dev_node);
683 685
684 686 new_dev_node->state = STATE_INIT;
685 687 new_dev_node->r_w = EVT_READ;
686 688
687 689 if (dev_list_head == NULL) {
688 690 dev_list_head = new_dev_node;
689 691 dev_list_tail = new_dev_node;
690 692
691 693 } else if (find_dev_node(dev_name, inst_num, pic_num) == NULL) {
692 694 dev_list_tail->next = new_dev_node;
693 695 dev_list_tail = new_dev_node;
694 696 }
695 697 }
696 698 }
697 699
698 700
699 701 /*
700 702 * Add all possible instances of a device.
701 703 */
702 704 void
703 705 add_all_dev_node(char *dev_name)
704 706 {
705 707 kstat_t *ksp;
706 708 int match = 0;
707 709
708 710 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
709 711 if ((strcmp(ksp->ks_class, "bus") == 0) &&
710 712 (strcmp(ksp->ks_name, "counters") == 0) &&
711 713 (strcmp(ksp->ks_module, dev_name) == 0)) {
712 714 match = 1;
713 715 add_dev_node(dev_name, ksp->ks_instance);
714 716 }
715 717 }
716 718
717 719 if (match == 0) {
718 720 (void) fprintf(stderr,
719 721 gettext("%s: invalid device name (%s)\n"),
720 722 pgmname, dev_name);
721 723 exit(1);
722 724 }
723 725 }
724 726
725 727
726 728 /*
727 729 * Add an event node to a specified device node.
728 730 */
729 731 void
730 732 add_evt_node(dev_node_t *dev_node)
731 733 {
732 734 evt_node_t *new_evt_node;
733 735 evt_node_t *curr_evt_node;
734 736
735 737 new_evt_node = safe_malloc(sizeof (evt_node_t));
736 738 bzero(new_evt_node, sizeof (evt_node_t));
737 739
738 740 (void) strcpy(new_evt_node->evt_name, "");
739 741
740 742 if (dev_node->evt_node == NULL) {
741 743 dev_node->evt_node = new_evt_node;
742 744 new_evt_node->next = new_evt_node;
743 745 return;
744 746 } else {
745 747 curr_evt_node = dev_node->evt_node;
746 748 while (curr_evt_node->next != dev_node->evt_node)
747 749 curr_evt_node = curr_evt_node->next;
748 750
749 751 curr_evt_node->next = new_evt_node;
750 752 new_evt_node->next = dev_node->evt_node;
751 753 }
752 754 }
753 755
754 756
755 757 /*
756 758 * Fill in or change the fields of an evt node.
757 759 */
758 760 void
759 761 modify_evt_node(dev_node_t *dev_node, char *evt_name)
760 762 {
761 763 evt_node_t *evt_node;
762 764 kstat_t *pic_ksp;
763 765 kstat_named_t *pic_data;
764 766 int64_t evt_num = 0;
765 767 int evt_match = 0;
766 768 int i;
767 769
768 770 evt_node = dev_node->evt_node;
769 771
770 772 /*
771 773 * Find the last event node.
772 774 */
773 775 if (evt_node->next != evt_node) {
774 776 while (evt_node->next != dev_node->evt_node) {
775 777 evt_node = evt_node->next;
776 778 }
777 779 }
778 780
779 781 evt_node->prev_count = 0;
780 782 evt_node->total = 0;
781 783
782 784 pic_ksp = dev_node->pic_ksp;
783 785
784 786 if (kstat_read(kc, pic_ksp, NULL) == FAIL) {
785 787 (void) fprintf(stderr, gettext("%s: could not read "
786 788 "pic kstat.\n"), pgmname);
787 789 exit(1);
788 790 }
789 791
790 792 pic_data = (kstat_named_t *)dev_node->pic_ksp->ks_data;
791 793
792 794 /*
793 795 * The event can either be given as a event name (string) or
794 796 * as a pcr mask. If given as pcr mask, we try to match it
795 797 * to an event name, and use that name. Otherwise we just use
796 798 * the pcr mask value.
797 799 */
798 800 if ((evt_num = is_num(evt_name)) == EVT_STR) {
799 801 (void) strcpy(evt_node->evt_name, evt_name);
800 802
801 803 for (i = 0; i < dev_node->pic_ksp->ks_ndata; i++) {
802 804 if (strcmp(evt_name, pic_data[i].name) == 0) {
803 805 evt_node->evt_pcr_mask = pic_data[i].value.ui64;
804 806 return;
805 807 }
806 808 }
807 809
808 810 (void) fprintf(stderr,
809 811 gettext("%s: %s is not a valid event name.\n"),
810 812 pgmname, evt_name);
811 813 exit(1);
812 814
813 815 } else {
814 816 /*
815 817 * See if the pcr mask given by the user matches that for any
816 818 * existing event.
817 819 */
818 820 for (i = 0; i < dev_node->pic_ksp->ks_ndata; i++) {
819 821 if (evt_num == pic_data[i].value.ui64) {
820 822 (void) strcpy(evt_node->evt_name,
821 823 pic_data[i].name);
822 824 evt_match = 1;
823 825 break;
824 826 }
825 827 }
826 828
827 829 if (evt_match == 0)
828 830 (void) sprintf(evt_node->evt_name, "%llx", evt_num);
829 831
830 832 evt_node->evt_pcr_mask = evt_num;
831 833 }
832 834 }
833 835
834 836
835 837 /*
836 838 * Removes all bar one of the evt_nodes that are hanging off the
837 839 * specified dev_node.
838 840 */
839 841 void
840 842 prune_evt_nodes(dev_node_t *dev_node)
841 843 {
842 844 evt_node_t *next_evt_node;
843 845 evt_node_t *curr_evt_node;
844 846
845 847 /*
846 848 * Only one evt node, nothing for us to do.
847 849 */
848 850 if (dev_node->evt_node->next == dev_node->evt_node) {
849 851 return;
850 852 }
851 853
852 854 curr_evt_node = dev_node->evt_node->next;
853 855 dev_node->evt_node->next = dev_node->evt_node;
854 856
855 857 while (curr_evt_node != dev_node->evt_node) {
856 858 next_evt_node = curr_evt_node->next;
857 859 free(curr_evt_node);
858 860 curr_evt_node = next_evt_node;
859 861 }
860 862 }
861 863
862 864
863 865 /*
864 866 * Set the events for each pic on each device instance.
865 867 */
866 868 void
867 869 setup_evts()
868 870 {
869 871 dev_node_t *dev_node;
870 872
871 873 dev_node = dev_list_head;
872 874
873 875 while (dev_node != NULL) {
874 876 if (dev_node->r_w == EVT_WRITE)
875 877 set_evt(dev_node);
876 878
877 879 dev_node = dev_node->next;
878 880 }
879 881 }
880 882
881 883
882 884 /*
883 885 * Set the appropiate events. Only called for event nodes
884 886 * that are marked EVT_WRITE.
885 887 */
886 888 void
887 889 set_evt(dev_node_t *dev_node)
888 890 {
889 891 kstat_named_t *cnt_data;
890 892 kstat_named_t *pic_data;
891 893 kstat_t *cnt_ksp;
892 894 kstat_t *pic_ksp;
893 895 evt_node_t *evt_node;
894 896 uint64_t clear_pcr_mask;
895 897 uint64_t pcr;
896 898 int pic_num;
897 899
898 900 cnt_ksp = dev_node->cnt_ksp;
899 901 pic_ksp = dev_node->pic_ksp;
900 902 pic_num = dev_node->pic_num;
901 903 evt_node = dev_node->evt_node;
902 904
903 905 /* Read the "counters" kstat */
904 906 if (kstat_read(kc, cnt_ksp, NULL) == FAIL) {
905 907 (void) fprintf(stderr, gettext("%s: could "
906 908 "not set event's.\n"), pgmname);
907 909 exit(1);
908 910 }
909 911
910 912 cnt_data = (kstat_named_t *)cnt_ksp->ks_data;
911 913
912 914 if (kstat_read(kc, pic_ksp, NULL) == FAIL) {
913 915 (void) fprintf(stderr, gettext("%s: could "
914 916 "not set event's.\n"), pgmname);
915 917 exit(1);
916 918 }
917 919
918 920 pic_data = (kstat_named_t *)pic_ksp->ks_data;
919 921 clear_pcr_mask = pic_data[pic_ksp->ks_ndata-1].value.ui64;
920 922
921 923 if ((pic_num < 0) || (pic_num > cnt_ksp->ks_ndata-1)) {
922 924 (void) fprintf(stderr,
923 925 gettext("%s: invalid pic #%d.\n"),
924 926 pgmname, pic_num);
925 927 exit(1);
926 928 }
927 929
928 930 /*
929 931 * Store the previous value that is on the pic
930 932 * so that we can calculate the delta value
931 933 * later.
932 934 */
933 935 evt_node->prev_count = cnt_data[pic_num+1].value.ui64;
934 936
935 937
936 938 /*
937 939 * Read the current pcr value from device.
938 940 */
939 941 pcr = cnt_data[0].value.ui64;
940 942
941 943 /*
942 944 * Clear the section of the pcr which corresponds to the
943 945 * pic we are setting events on. Also clear the pcr value
944 946 * which is stored in the instance node.
945 947 *
946 948 */
947 949 pcr = pcr & clear_pcr_mask;
948 950
949 951 /*
950 952 * Set the event.
951 953 */
952 954 pcr = pcr | evt_node->evt_pcr_mask;
953 955 cnt_data[0].value.ui64 = pcr;
954 956
955 957 /*
956 958 * Write the value back to the kstat, to make it
957 959 * visible to the underlying driver.
958 960 */
959 961 if (kstat_write(kc, cnt_ksp, NULL) == FAIL) {
960 962 (void) fprintf(stderr, gettext("%s: could not set events "
961 963 "(setting events requires root "
962 964 "permission).\n"), pgmname);
963 965 exit(1);
964 966 }
965 967 }
966 968
967 969
968 970 /*
969 971 * Works through the list of device nodes, reading events
970 972 * and where appropiate setting new events (multiplexing).
971 973 */
972 974 void
973 975 read_evts()
974 976 {
975 977 dev_node_t *dev_node;
976 978 kstat_t *cnt_ksp;
977 979 kstat_named_t *cnt_data;
978 980 char tmp_str[30];
979 981 int iter = 0;
980 982
981 983 dev_node = dev_list_head;
982 984
983 985 while (dev_node != NULL) {
984 986 if (iter == 0)
985 987 print_timestamp();
986 988 /*
987 989 * First read of all the counters is done
988 990 * to establish a baseline for the counts.
989 991 * This data is not printed.
990 992 */
991 993 if ((!initial_read) && (iter == 0)) {
992 994 (void) snprintf(tmp_str, sizeof (tmp_str), "%s%d",
993 995 dev_node->name, dev_node->dev_inst);
994 996 (void) printf("%-7s", tmp_str);
995 997 }
996 998
997 999 cnt_ksp = (kstat_t *)dev_node->cnt_ksp;
998 1000
999 1001 if (kstat_read(kc, cnt_ksp, NULL) == FAIL) {
1000 1002 (void) fprintf(stderr, gettext("%s: device %s%d "
1001 1003 "(pic %d) no longer valid.\n"),
1002 1004 pgmname, dev_node->name,
1003 1005 dev_node->dev_inst,
1004 1006 dev_node->pic_num);
1005 1007 remove_dev_node(dev_node);
1006 1008 dev_node = dev_list_head;
1007 1009 continue;
1008 1010 }
1009 1011
1010 1012 cnt_data = (kstat_named_t *)cnt_ksp->ks_data;
1011 1013
1012 1014 if (dev_node->r_w == EVT_READ) {
1013 1015 read_r_evt_node(dev_node, dev_node->pic_num, cnt_data);
1014 1016 iter++;
1015 1017 } else {
1016 1018 read_w_evt_node(dev_node, dev_node->pic_num, cnt_data);
1017 1019 iter++;
1018 1020 }
1019 1021
1020 1022 if ((!initial_read) && (iter == max_pic_num)) {
1021 1023 iter = 0;
1022 1024 (void) printf("\n");
1023 1025 }
1024 1026
1025 1027 /*
1026 1028 * If there is more than one event node
1027 1029 * per-pic then we are multiplexing.
1028 1030 */
1029 1031 if ((dev_node->evt_node->next != dev_node->evt_node) &&
1030 1032 (!initial_read)) {
1031 1033 dev_node->evt_node = dev_node->evt_node->next;
1032 1034 set_evt(dev_node);
1033 1035 }
1034 1036 dev_node = dev_node->next;
1035 1037 }
1036 1038 initial_read = FALSE;
1037 1039 }
1038 1040
1039 1041
1040 1042 /*
1041 1043 * Read a node that is marked as EVT_READ
1042 1044 */
1043 1045 void
1044 1046 read_r_evt_node(dev_node_t *dev_node, int pic_num, kstat_named_t *cnt_data)
1045 1047 {
1046 1048 evt_node_t *evt_node;
1047 1049 kstat_t *pic_ksp;
1048 1050 kstat_named_t *pic_data;
1049 1051 uint64_t pcr_read;
1050 1052 uint64_t clear_pcr_mask;
1051 1053 uint64_t delta_count;
1052 1054 int i;
1053 1055 int match = 0;
1054 1056 int evt_blank = 1;
1055 1057
1056 1058 evt_node = dev_node->evt_node;
1057 1059
1058 1060 pic_ksp = (kstat_t *)dev_node->pic_ksp;
1059 1061
1060 1062 if (kstat_read(kc, pic_ksp, NULL) == FAIL) {
1061 1063 (void) fprintf(stderr, gettext("%s: device %s%d "
1062 1064 "(pic %d) no longer valid.\n"), pgmname,
1063 1065 dev_node->name, dev_node->dev_inst,
1064 1066 dev_node->pic_num);
1065 1067 remove_dev_node(dev_node);
1066 1068 return;
1067 1069 }
1068 1070
1069 1071 pic_data = (kstat_named_t *)pic_ksp->ks_data;
1070 1072 clear_pcr_mask = pic_data[pic_ksp->ks_ndata-1].value.ui64;
1071 1073
1072 1074 /*
1073 1075 * Get PCR value from device. We extract the portion
1074 1076 * of the PCR relating to the pic we are interested by
1075 1077 * AND'ing the inverse of the clear mask for this pic.
1076 1078 *
1077 1079 * The clear mask is usually used to clear the appropiate
1078 1080 * section of the PCR before we write events into it. So
1079 1081 * by using the inverse of the mask, we zero everything
1080 1082 * *but* the section we are interested in.
1081 1083 */
1082 1084 pcr_read = cnt_data[0].value.ui64;
1083 1085 pcr_read = pcr_read & ~(clear_pcr_mask);
1084 1086
1085 1087 /*
1086 1088 * If the event name is blank this is the first time that
1087 1089 * this node has been accessed, so we read the pcr and
1088 1090 * from that we get the event name if it exists.
1089 1091 *
1090 1092 * If the pcr read from the device does not match that
1091 1093 * stored in the node, then it means that the event has
1092 1094 * changed from its previous value, so we need to re-read
1093 1095 * all the values.
1094 1096 */
1095 1097 if ((strcmp(evt_node->evt_name, "") == 0) ||
1096 1098 (pcr_read != evt_node->evt_pcr_mask)) {
1097 1099
1098 1100 for (i = 0; i < pic_ksp->ks_ndata-1; i++) {
1099 1101 if (pcr_read == pic_data[i].value.ui64) {
1100 1102 match = TRUE;
1101 1103 break;
1102 1104 }
1103 1105 }
1104 1106
1105 1107 /*
1106 1108 * Able to resolve pcr value to a event name.
1107 1109 */
1108 1110 if (match) {
1109 1111 (void) strcpy(evt_node->evt_name, pic_data[i].name);
1110 1112 evt_node->evt_pcr_mask = pcr_read;
1111 1113 evt_node->total = 0;
1112 1114 evt_node->prev_count =
1113 1115 cnt_data[pic_num+1].value.ui64;
1114 1116
1115 1117 if ((evt_blank) && (!initial_read)) {
1116 1118 (void) printf("%s\t%-8d\t",
1117 1119 evt_node->evt_name, 0);
1118 1120 evt_blank = 0;
1119 1121 }
1120 1122
1121 1123 } else {
1122 1124 (void) sprintf(evt_node->evt_name, "0x%llx", pcr_read);
1123 1125 evt_node->evt_pcr_mask = pcr_read;
1124 1126 evt_node->total = 0;
1125 1127 evt_node->prev_count =
1126 1128 cnt_data[pic_num+1].value.ui64;
1127 1129
1128 1130 if ((evt_blank) && (!initial_read)) {
1129 1131 (void) printf("%s\t%-8d\t",
1130 1132 evt_node->evt_name, 0);
1131 1133 evt_blank = 0;
1132 1134 }
1133 1135
1134 1136 }
1135 1137 } else {
1136 1138 /* Deal with wraparound of the counters */
1137 1139 if (cnt_data[pic_num+1].value.ui64 < evt_node->prev_count) {
1138 1140
1139 1141 delta_count = (UINT32_MAX-evt_node->prev_count) +
1140 1142 cnt_data[pic_num+1].value.ui64;
1141 1143 } else {
1142 1144 /* Calcalate delta value */
1143 1145 delta_count = cnt_data[pic_num+1].value.ui64
1144 1146 - evt_node->prev_count;
1145 1147 }
1146 1148
1147 1149
1148 1150 /*
1149 1151 * Store value so that we can calculate delta next
1150 1152 * time through.
1151 1153 */
1152 1154 evt_node->prev_count = cnt_data[pic_num+1].value.ui64;
1153 1155
1154 1156 /* Update count total */
1155 1157 evt_node->total += delta_count;
1156 1158
1157 1159 if (delta) {
1158 1160 (void) printf("%-20s %-9lld ",
1159 1161 evt_node->evt_name, delta_count);
1160 1162 } else {
1161 1163
1162 1164 (void) printf("%-20s %-9lld ",
1163 1165 evt_node->evt_name, evt_node->total);
1164 1166 }
1165 1167 }
1166 1168 }
1167 1169
1168 1170
1169 1171 /*
1170 1172 * Read event nodes marked as EVT_WRITE
1171 1173 */
1172 1174 void
1173 1175 read_w_evt_node(dev_node_t *dev_node, int pic_num, kstat_named_t *cnt_data)
1174 1176 {
1175 1177 kstat_t *pic_ksp;
1176 1178 kstat_named_t *pic_data;
1177 1179 evt_node_t *evt_node;
1178 1180 uint64_t delta_count;
1179 1181 uint64_t pcr_read;
1180 1182 uint64_t clear_pcr_mask;
1181 1183
1182 1184 evt_node = dev_node->evt_node;
1183 1185
1184 1186 pic_ksp = (kstat_t *)dev_node->pic_ksp;
1185 1187
1186 1188 if (kstat_read(kc, pic_ksp, NULL) == FAIL) {
1187 1189 (void) fprintf(stderr, gettext("%s: could not read "
1188 1190 "%s%d\n"), pgmname, dev_node->name,
1189 1191 dev_node->dev_inst);
1190 1192 remove_dev_node(dev_node);
1191 1193 return;
1192 1194 }
1193 1195
1194 1196 pic_data = (kstat_named_t *)pic_ksp->ks_data;
1195 1197 clear_pcr_mask = pic_data[pic_ksp->ks_ndata-1].value.ui64;
1196 1198
1197 1199 /*
1198 1200 * Get PCR value from device. We extract the portion
1199 1201 * of the PCR relating to the pic we are interested by
1200 1202 * AND'ing the inverse of the clear mask for this pic.
1201 1203 *
1202 1204 * The clear mask is usually used to clear the appropiate
1203 1205 * section of the PCR before we write events into it. So
1204 1206 * by using the inverse of the mask, we zero everything
1205 1207 * *but* the section we are interested in.
1206 1208 */
1207 1209 pcr_read = cnt_data[0].value.ui64;
1208 1210 pcr_read = pcr_read & ~(clear_pcr_mask);
1209 1211
1210 1212 /*
1211 1213 * If the pcr value from the device does not match the
1212 1214 * stored value, then the events on at least one of the
1213 1215 * pics must have been change by another busstat instance.
1214 1216 *
1215 1217 * Regard this as a fatal error.
1216 1218 */
1217 1219 if (pcr_read != evt_node->evt_pcr_mask) {
1218 1220 (void) fprintf(stderr, gettext("%s: events changed (possibly "
1219 1221 "by another busstat).\n"), pgmname);
1220 1222 exit(2);
1221 1223 }
1222 1224
1223 1225 /*
1224 1226 * Calculate delta, and then store value just read to allow us to
1225 1227 * calculate delta next time around.
1226 1228 */
1227 1229 /* Deal with wraparound of the counters */
1228 1230 if (cnt_data[pic_num+1].value.ui64 < evt_node->prev_count) {
1229 1231
1230 1232 delta_count = (UINT32_MAX-evt_node->prev_count) +
1231 1233 cnt_data[pic_num+1].value.ui64;
1232 1234 } else {
1233 1235 /* Calcalate delta value */
1234 1236 delta_count = cnt_data[pic_num+1].value.ui64
1235 1237 - evt_node->prev_count;
1236 1238 }
1237 1239
1238 1240 evt_node->prev_count = cnt_data[pic_num+1].value.ui64;
1239 1241
1240 1242 if (initial_read) {
1241 1243 evt_node->total = 0;
1242 1244
1243 1245 } else {
1244 1246 /* Update count total */
1245 1247 evt_node->total += delta_count;
1246 1248
1247 1249 if (delta) {
1248 1250 (void) printf("%-20s %-9lld ",
1249 1251 evt_node->evt_name, delta_count);
1250 1252 } else {
1251 1253 (void) printf("%-20s %-9lld ",
1252 1254 evt_node->evt_name, evt_node->total);
1253 1255 }
1254 1256 }
1255 1257 }
1256 1258
1257 1259
1258 1260 /*
1259 1261 * Check to see if any DR operations have occured, and deal with the
1260 1262 * consequences.
1261 1263 *
1262 1264 * Use the Kstat chain ID to check for DR operations. If the ID has
1263 1265 * changed then some kstats on system have been modified, we check
1264 1266 * all the data structures to see are they still valid. If they are
1265 1267 * not we remove them.
1266 1268 */
1267 1269 void
1268 1270 check_dr_ops()
1269 1271 {
1270 1272 dev_node_t *dev_node;
1271 1273 kid_t new_id;
1272 1274 kstat_t *ksp;
1273 1275 int match = 0;
1274 1276
1275 1277 if ((new_id = kstat_chain_update(kc)) < 0) {
1276 1278 (void) fprintf(stderr, gettext("%s: could not get "
1277 1279 "kstat chain id\n"), pgmname);
1278 1280 exit(1);
1279 1281 }
1280 1282
1281 1283 if (new_id == 0) {
1282 1284 /* Kstat chain has not changed. */
1283 1285 return;
1284 1286 }
1285 1287
1286 1288 /*
1287 1289 * Scan the chain of device nodes, making sure that their associated
1288 1290 * kstats are still present. If not we remove the appropiate node.
1289 1291 */
1290 1292 dev_node = dev_list_head;
1291 1293
1292 1294 while (dev_node != NULL) {
1293 1295 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
1294 1296 if ((strcmp("bus", ksp->ks_class) == 0) &&
1295 1297 (strcmp("counters", ksp->ks_name) == 0) &&
1296 1298 (strcmp(dev_node->name, ksp->ks_module) == 0) &&
1297 1299 (ksp->ks_instance == dev_node->dev_inst)) {
1298 1300 match = 1;
1299 1301 break;
1300 1302 }
1301 1303 }
1302 1304 if (match == 0) {
1303 1305 (void) fprintf(stderr, gettext("%s: device %s%d"
1304 1306 " (pic %d) no longer valid.\n"), pgmname,
1305 1307 dev_node->name, dev_node->dev_inst,
1306 1308 dev_node->pic_num);
1307 1309
1308 1310 remove_dev_node(dev_node);
1309 1311 }
1310 1312 dev_node = dev_node->next;
1311 1313 }
1312 1314 }
1313 1315
1314 1316
1315 1317
1316 1318 /*
1317 1319 * Remove a device node and its associated event nodes.
1318 1320 */
1319 1321 void
1320 1322 remove_dev_node(dev_node_t *dev_node)
1321 1323 {
1322 1324 dev_node_t *curr_node;
1323 1325 dev_node_t *prev_node;
1324 1326 evt_node_t *curr_evt_node;
1325 1327 evt_node_t *next_evt_node;
1326 1328 evt_node_t *start_pos;
1327 1329
1328 1330 curr_node = dev_list_head;
1329 1331
1330 1332 if (curr_node == dev_node) {
1331 1333 dev_list_head = dev_node->next;
1332 1334
1333 1335 if (dev_list_head == NULL) {
1334 1336 (void) fprintf(stderr, gettext("%s: no "
1335 1337 "devices left to monitor.\n"),
1336 1338 pgmname);
1337 1339 exit(1);
1338 1340 }
1339 1341
1340 1342 /* Remove each event node first */
1341 1343 start_pos = dev_node->evt_node;
1342 1344 curr_evt_node = start_pos->next;
1343 1345
1344 1346 while (curr_evt_node != start_pos) {
1345 1347 next_evt_node = curr_evt_node->next;
1346 1348
1347 1349 free(curr_evt_node);
1348 1350 curr_evt_node = next_evt_node;
1349 1351 }
1350 1352
1351 1353 free(start_pos);
1352 1354 free(dev_node);
1353 1355 return;
1354 1356 }
1355 1357
1356 1358 /* Find the device node */
1357 1359 prev_node = dev_list_head;
1358 1360 curr_node = prev_node->next;
1359 1361
1360 1362 while (curr_node != NULL) {
1361 1363 if (curr_node == dev_node) {
1362 1364 prev_node->next = curr_node->next;
1363 1365
1364 1366 /* Remove each event node first */
1365 1367 start_pos = dev_node->evt_node;
1366 1368 curr_evt_node = start_pos->next;
1367 1369
1368 1370 while (curr_evt_node != start_pos) {
1369 1371 next_evt_node = curr_evt_node->next;
1370 1372
1371 1373 free(curr_evt_node);
1372 1374 curr_evt_node = next_evt_node;
1373 1375 }
1374 1376 free(start_pos);
1375 1377
1376 1378 free(dev_node);
1377 1379 return;
1378 1380 }
1379 1381 prev_node = curr_node;
1380 1382 curr_node = curr_node->next;
1381 1383 }
1382 1384 }
1383 1385
1384 1386
1385 1387 /*
1386 1388 * Find a device node in the linked list of dev_nodes. Match
1387 1389 * is done on device name, and instance number.
1388 1390 */
1389 1391 dev_node_t *
1390 1392 find_dev_node(char *name, int inst_num, int pic_num)
1391 1393 {
1392 1394 dev_node_t *curr_node;
1393 1395
1394 1396 curr_node = dev_list_head;
1395 1397
1396 1398 while (curr_node != NULL) {
1397 1399 if ((strcmp(curr_node->name, name) == 0) &&
1398 1400 (curr_node->dev_inst == inst_num) &&
1399 1401 (curr_node->pic_num == pic_num)) {
1400 1402 return (curr_node);
1401 1403 }
1402 1404
1403 1405 curr_node = curr_node->next;
1404 1406 }
1405 1407
1406 1408 return (NULL);
1407 1409 }
1408 1410
1409 1411
1410 1412 /*
1411 1413 * Determines whether the string represents a event name
1412 1414 * or a numeric value. Numeric value can be dec, hex
1413 1415 * or octal. All are converted to long int.
1414 1416 */
1415 1417 int64_t
1416 1418 is_num(char *name)
1417 1419 {
1418 1420 char *remainder = NULL;
1419 1421 int64_t num;
1420 1422
1421 1423 num = (int64_t)strtol(name, &remainder, 0);
1422 1424
1423 1425 if (name == remainder) {
1424 1426 return (EVT_STR);
1425 1427 } else {
1426 1428 return (num);
1427 1429 }
1428 1430 }
1429 1431
1430 1432
1431 1433 /*
1432 1434 * Find a pointer to the specified picN kstat. First
1433 1435 * search for the specific kstat, and if that can't
1434 1436 * be found search for any picN kstat belonging to this device.
1435 1437 */
1436 1438 kstat_t *
1437 1439 find_pic_kstat(char *dev_name, int inst_num, char *pic)
1438 1440 {
1439 1441 kstat_t *ksp;
1440 1442 kstat_t *p_ksp;
1441 1443
1442 1444 /* Look for specific picN kstat */
1443 1445 if ((p_ksp = kstat_lookup(kc, dev_name, inst_num, pic)) == NULL) {
1444 1446
1445 1447 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
1446 1448 if ((strcmp(ksp->ks_class, "bus") == 0) &&
1447 1449 (strcmp(ksp->ks_name, pic) == 0) &&
1448 1450 (strcmp(ksp->ks_module, dev_name) == 0)) {
1449 1451
1450 1452 return (ksp);
1451 1453 }
1452 1454 }
1453 1455 }
1454 1456 return (p_ksp);
1455 1457 }
1456 1458
1457 1459
1458 1460 /*
1459 1461 * Print column titles.
1460 1462 * Can be turned off by -n option.
1461 1463 */
1462 1464 void
1463 1465 print_banner()
1464 1466 {
1465 1467 int i;
1466 1468
1467 1469 (void) printf("time dev ");
1468 1470
1469 1471 for (i = 0; i < max_pic_num; i++)
1470 1472 (void) printf("event%d "
1471 1473 "pic%d ", i, i);
1472 1474
1473 1475 (void) printf("\n");
1474 1476
1475 1477 banner = FALSE;
1476 1478 }
1477 1479
1478 1480
1479 1481 /*
1480 1482 * Print the elapsed time in seconds, since the last call.
1481 1483 */
1482 1484 void
1483 1485 print_timestamp()
1484 1486 {
1485 1487 static hrtime_t curr_time = 0;
1486 1488 static hrtime_t total_elapsed = 0;
1487 1489 hrtime_t new_time = 0;
1488 1490 hrtime_t elapsed = 0;
1489 1491 hrtime_t rem = 0;
1490 1492
1491 1493 if (initial_read) {
1492 1494 curr_time = (uint64_t)gethrtime();
1493 1495 return;
1494 1496 }
1495 1497
1496 1498 new_time = gethrtime();
1497 1499
1498 1500 elapsed = (new_time - curr_time)/NANO;
1499 1501
1500 1502 /* Round up time value if necessary */
1501 1503 rem = (new_time - curr_time)%NANO;
1502 1504 if (rem >= NANO/2)
1503 1505 elapsed += 1;
1504 1506
1505 1507 total_elapsed += elapsed;
1506 1508
1507 1509 (void) printf("%-4llu ", total_elapsed);
1508 1510
1509 1511 curr_time = new_time;
1510 1512 }
1511 1513
1512 1514
1513 1515 void
1514 1516 usage()
1515 1517 {
1516 1518 (void) printf(gettext("Usage : busstat [-a] [-h] [-l] [-n]\n"
1517 1519 " [-e device-inst]\n"
1518 1520 " [-w device-inst "
1519 1521 "[,pic0=<event>] [,picN=<event>] ]\n"
1520 1522 " [-r device-inst]\n"
1521 1523 " [ interval [count] ]\n"));
1522 1524
1523 1525 exit(2);
1524 1526 }
1525 1527
1526 1528
1527 1529 void *
1528 1530 safe_malloc(size_t size)
1529 1531 {
1530 1532 void *a;
1531 1533
1532 1534 if ((a = malloc(size)) == NULL) {
1533 1535 (void) fprintf(stderr,
1534 1536 gettext("%s: out of memory.\n"), pgmname);
1535 1537 exit(1);
1536 1538 }
1537 1539
1538 1540 return (a);
1539 1541 }
1540 1542
1541 1543 /*
1542 1544 * Create and arm the timer.
1543 1545 */
1544 1546 void
1545 1547 set_timer(int interval)
1546 1548 {
1547 1549 timer_t t_id; /* Timer id */
1548 1550 itimerspec_t time_struct;
1549 1551 struct sigevent sig_struct;
1550 1552 struct sigaction act;
1551 1553
1552 1554 bzero(&sig_struct, sizeof (struct sigevent));
1553 1555 bzero(&act, sizeof (struct sigaction));
1554 1556
1555 1557 /* Create timer */
1556 1558 sig_struct.sigev_notify = SIGEV_SIGNAL;
1557 1559 sig_struct.sigev_signo = SIGUSR1;
1558 1560 sig_struct.sigev_value.sival_int = 0;
1559 1561
1560 1562 if (timer_create(CLOCK_REALTIME, &sig_struct, &t_id) != 0) {
1561 1563 (void) fprintf(stderr, gettext("%s: Timer creation failed.\n"),
1562 1564 pgmname);
1563 1565 exit(1);
1564 1566 }
1565 1567
1566 1568 act.sa_handler = handle_sig;
1567 1569
1568 1570 if (sigaction(SIGUSR1, &act, NULL) != 0) {
1569 1571 (void) fprintf(stderr, gettext("%s: could not setup signal "
1570 1572 "handler"), pgmname);
1571 1573 exit(1);
1572 1574 }
1573 1575
1574 1576 time_struct.it_value.tv_sec = interval;
1575 1577 time_struct.it_value.tv_nsec = 0;
1576 1578 time_struct.it_interval.tv_sec = interval;
1577 1579 time_struct.it_interval.tv_nsec = 0;
1578 1580
1579 1581 /* Arm timer */
1580 1582 if ((timer_settime(t_id, 0, &time_struct, NULL)) != 0) {
1581 1583 (void) fprintf(stderr, gettext("%s: Setting timer failed.\n"),
1582 1584 pgmname);
1583 1585 exit(1);
1584 1586 }
1585 1587 }
1586 1588
1587 1589
1588 1590 /* ARGSUSED */
1589 1591 void
1590 1592 handle_sig(int x)
1591 1593 {
1592 1594 }
1593 1595
1594 1596 /*
1595 1597 * return a boolean value indicating whether or not
1596 1598 * a string consists solely of characters which are
1597 1599 * digits 0..9
1598 1600 */
1599 1601 int
1600 1602 strisnum(const char *s)
1601 1603 {
1602 1604 for (; *s != '\0'; s++) {
1603 1605 if (*s < '0' || *s > '9')
1604 1606 return (0);
1605 1607 }
1606 1608 return (1);
1607 1609 }
↓ open down ↓ |
1196 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX