Print this page
3396 new psrinfo does not print socket type
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/psrinfo/psrinfo.c
+++ new/usr/src/cmd/psrinfo/psrinfo.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 13 * Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
14 + * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
14 15 */
15 16
16 17 /*
17 18 * This implements psrinfo(1M), a utility to report various information
18 19 * about processors, cores, and threads (virtual cpus). This is mostly
19 20 * intended for human consumption - this utility doesn't do much more than
20 21 * simply process kstats for human readability.
21 22 *
22 23 * All the relevant kstats are in the cpu_info kstat module.
23 24 */
24 25
25 26 #include <stdio.h>
26 27 #include <stdlib.h>
27 28 #include <unistd.h>
28 29 #include <string.h>
29 30 #include <kstat.h>
30 31 #include <libintl.h>
31 32 #include <locale.h>
32 33 #include <libgen.h>
33 34 #include <ctype.h>
34 35 #include <errno.h>
35 36
36 37 #define _(x) gettext(x)
37 38 #if XGETTEXT
38 39 /* These CPU states are here for benefit of xgettext */
39 40 _("on-line")
40 41 _("off-line")
41 42 _("faulted")
42 43 _("powered-off")
43 44 _("no-intr")
44 45 _("spare")
45 46 _("unknown")
46 47 #endif
47 48
48 49 /*
49 50 * We deal with sorted linked lists, where the sort key is usually the
50 51 * cpu id, core id, or chip id. We generalize this with simple node.
51 52 */
52 53 struct link {
53 54 long l_id;
54 55 struct link *l_next;
55 56 void *l_ptr;
56 57 };
57 58
58 59 /*
59 60 * A physical chip. A chip can contain multiple cores and virtual cpus.
60 61 */
61 62 struct pchip {
62 63 struct link p_link;
63 64 int p_ncore;
64 65 int p_nvcpu;
65 66 struct link *p_cores;
66 67 struct link *p_vcpus;
67 68 int p_doit;
68 69 };
69 70
70 71 struct core {
71 72 struct link c_link;
72 73 struct link c_link_pchip;
73 74
74 75 int c_nvcpu;
75 76 int c_doit;
76 77
77 78 struct pchip *c_pchip;
78 79 struct link *c_vcpus;
79 80 };
80 81
81 82 struct vcpu {
82 83 struct link v_link;
83 84
84 85 struct link v_link_core;
85 86 struct link v_link_pchip;
86 87
87 88 int v_doit;
88 89
89 90 struct pchip *v_pchip;
↓ open down ↓ |
66 lines elided |
↑ open up ↑ |
90 91 struct core *v_core;
91 92
92 93 char *v_state;
93 94 long v_state_begin;
94 95 char *v_cpu_type;
95 96 char *v_fpu_type;
96 97 long v_clock_mhz;
97 98 long v_pchip_id; /* 1 per socket */
98 99 char *v_impl;
99 100 char *v_brand;
101 + char *v_socket;
100 102 long v_core_id; /* n per chip_id */
101 103 };
102 104
103 105 static struct link *pchips = NULL;
104 106 static struct link *cores = NULL;
105 107 static struct link *vcpus = NULL;
106 108
107 109 static const char *cmdname;
108 110
109 111 static void
110 112 usage(char *msg)
111 113 {
112 114 if (msg != NULL)
113 115 (void) fprintf(stderr, "%s: %s\n", cmdname, msg);
114 116 (void) fprintf(stderr, _("usage: \n" \
115 117 "\t%s [-v] [-p] [processor_id ...]\n" \
116 118 "\t%s -s [-p] processor_id\n"), cmdname, cmdname);
117 119 exit(2);
118 120 }
119 121
120 122 /* like perror, but includes the command name */
121 123 static void
122 124 die(const char *msg)
123 125 {
124 126 (void) fprintf(stderr, "%s: %s: %s\n", cmdname, msg, strerror(errno));
125 127 exit(2);
126 128 }
127 129
128 130 static char *
129 131 mystrdup(const char *src)
130 132 {
131 133 char *dst;
132 134
133 135 if ((dst = strdup(src)) == NULL)
134 136 die(_("strdup() failed"));
135 137 return (dst);
136 138 }
137 139
138 140 static void *
139 141 zalloc(size_t size)
140 142 {
141 143 void *ptr;
142 144
143 145 if ((ptr = calloc(1, size)) == NULL)
144 146 die(_("calloc() failed"));
145 147 return (ptr);
146 148 }
147 149
148 150 /*
149 151 * Insert a new node on a list, at the insertion point given.
150 152 */
151 153 static void
152 154 ins_link(struct link **ins, struct link *item)
153 155 {
154 156 item->l_next = *ins;
155 157 *ins = item;
156 158 }
157 159
158 160 /*
159 161 * Find an id on a sorted list. If the requested id is not found,
160 162 * then the insertpt will be set (if not null) to the location where
161 163 * a new node should be inserted with ins_link (see above).
162 164 */
163 165 static void *
164 166 find_link(void *list, int id, struct link ***insertpt)
165 167 {
166 168 struct link **ins = list;
167 169 struct link *l;
168 170
169 171 while ((l = *ins) != NULL) {
170 172 if (l->l_id == id)
171 173 return (l->l_ptr);
172 174 if (l->l_id > id)
173 175 break;
174 176 ins = &l->l_next;
175 177 }
176 178 if (insertpt != NULL)
177 179 *insertpt = ins;
178 180 return (NULL);
179 181 }
180 182
181 183 /*
182 184 * Print the linked list of ids in parens, taking care to collapse
183 185 * ranges, so instead of (0 1 2 3) it should print (0-3).
184 186 */
185 187 static void
186 188 print_links(struct link *l)
187 189 {
188 190 int start = -1;
189 191 int end = 0;
190 192
191 193 (void) printf(" (");
192 194 while (l != NULL) {
193 195 if (start < 0) {
194 196 start = l->l_id;
195 197 }
196 198 end = l->l_id;
197 199 if ((l->l_next == NULL) ||
198 200 (l->l_next->l_id > (l->l_id + 1))) {
199 201 /* end of the contiguous group */
200 202 if (start == end) {
201 203 (void) printf("%d", start);
202 204 } else {
203 205 (void) printf("%d-%d", start, end);
204 206 }
205 207 if (l->l_next)
206 208 (void) printf(" ");
207 209 start = -1;
208 210 }
209 211 l = l->l_next;
210 212 }
211 213 (void) printf(")");
212 214 }
213 215
214 216 static const char *
215 217 timestr(long t)
216 218 {
217 219 static char buffer[256];
218 220 (void) strftime(buffer, sizeof (buffer), _("%m/%d/%Y %T"),
219 221 localtime(&t));
220 222 return (buffer);
221 223 }
222 224
223 225 static void
224 226 print_vp(int nspec)
225 227 {
226 228 struct pchip *chip;
227 229 struct core *core;
228 230 struct vcpu *vcpu;
229 231 struct link *l1, *l2;
230 232 int len;
231 233 for (l1 = pchips; l1; l1 = l1->l_next) {
232 234
233 235 chip = l1->l_ptr;
234 236
235 237 if ((nspec != 0) && (chip->p_doit == 0))
236 238 continue;
237 239
238 240 vcpu = chip->p_vcpus->l_ptr;
239 241
240 242 /*
241 243 * Note that some of the way these strings are broken up are
242 244 * to accommodate the legacy translations so that we won't
243 245 * have to retranslate for this utility.
244 246 */
245 247 if ((chip->p_ncore == 1) || (chip->p_ncore == chip->p_nvcpu)) {
246 248 (void) printf(_("%s has %d virtual %s"),
247 249 _("The physical processor"),
248 250 chip->p_nvcpu,
249 251 chip->p_nvcpu > 1 ?
250 252 _("processors") :
251 253 _("processor"));
252 254 } else {
253 255 (void) printf(_("%s has %d %s and %d virtual %s"),
254 256 _("The physical processor"),
255 257 chip->p_ncore, _("cores"),
256 258 chip->p_nvcpu,
257 259 chip->p_nvcpu > 1 ?
258 260 _("processors") : _("processor"));
259 261 }
260 262
↓ open down ↓ |
151 lines elided |
↑ open up ↑ |
261 263 print_links(chip->p_vcpus);
262 264 (void) putchar('\n');
263 265
264 266 if ((chip->p_ncore == 1) || (chip->p_ncore == chip->p_nvcpu)) {
265 267 if (strlen(vcpu->v_impl)) {
266 268 (void) printf(" %s\n", vcpu->v_impl);
267 269 }
268 270 if (((len = strlen(vcpu->v_brand)) != 0) &&
269 271 (strncmp(vcpu->v_brand, vcpu->v_impl, len) != 0))
270 272 (void) printf("\t%s", vcpu->v_brand);
273 + if (strcmp(vcpu->v_socket, "Unknown") != 0)
274 + (void) printf("\t[ %s: %s ]", _("Socket"),
275 + vcpu->v_socket);
271 276 (void) putchar('\n');
272 277 } else {
273 278 for (l2 = chip->p_cores; l2; l2 = l2->l_next) {
274 279 core = l2->l_ptr;
275 280 (void) printf(_(" %s has %d virtual %s"),
276 281 _("The core"),
277 282 core->c_nvcpu,
278 283 chip->p_nvcpu > 1 ?
279 284 _("processors") : _("processor"));
280 285 print_links(core->c_vcpus);
281 286 (void) putchar('\n');
282 287 }
283 288 if (strlen(vcpu->v_impl)) {
284 289 (void) printf(" %s\n", vcpu->v_impl);
285 290 }
286 291 if (((len = strlen(vcpu->v_brand)) != 0) &&
287 292 (strncmp(vcpu->v_brand, vcpu->v_impl, len) != 0))
288 293 (void) printf(" %s\n", vcpu->v_brand);
289 294 }
290 295 }
291 296 }
292 297
293 298 static void
294 299 print_ps(void)
295 300 {
296 301 int online = 1;
297 302 struct pchip *p;
298 303 struct vcpu *v;
299 304 struct link *l;
300 305
301 306 /*
302 307 * Report "1" if all cpus colocated on the same chip are online.
303 308 */
304 309 for (l = pchips; l != NULL; l = l->l_next) {
305 310 p = l->l_ptr;
306 311 if (p->p_doit)
307 312 break;
308 313 }
309 314 if (p == NULL)
310 315 return; /* should never happen! */
311 316 for (l = p->p_vcpus; l != NULL; l = l->l_next) {
312 317 v = l->l_ptr;
313 318 if (strcmp(v->v_state, "on-line") != 0) {
314 319 online = 0;
315 320 break;
316 321 }
317 322 }
318 323
319 324 (void) printf("%d\n", online);
320 325 }
321 326
322 327 static void
323 328 print_s(void)
324 329 {
325 330 struct link *l;
326 331
327 332 /*
328 333 * Find the processor (there will be only one) that we selected,
329 334 * and report whether or not it is online.
330 335 */
331 336 for (l = vcpus; l != NULL; l = l->l_next) {
332 337 struct vcpu *v = l->l_ptr;
333 338 if (v->v_doit) {
334 339 (void) printf("%d\n",
335 340 strcmp(v->v_state, "on-line") == 0 ? 1 : 0);
336 341 return;
337 342 }
338 343 }
339 344 }
340 345
341 346 static void
342 347 print_p(int nspec)
343 348 {
344 349 struct link *l1, *l2;
345 350 int online = 0;
346 351
347 352 /*
348 353 * Print the number of physical packages with at least one processor
349 354 * online.
350 355 */
351 356 for (l1 = pchips; l1 != NULL; l1 = l1->l_next) {
352 357 struct pchip *p = l1->l_ptr;
353 358 if ((nspec == 0) || (p->p_doit)) {
354 359
355 360 for (l2 = p->p_vcpus; l2 != NULL; l2 = l2->l_next) {
356 361 struct vcpu *v = l2->l_ptr;
357 362 if (strcmp(v->v_state, "on-line") == 0) {
358 363 online++;
359 364 break;
360 365 }
361 366 }
362 367 }
363 368 }
364 369 (void) printf("%d\n", online);
365 370 }
366 371
367 372 static void
368 373 print_v(int nspec)
369 374 {
370 375 struct link *l;
371 376
372 377 for (l = vcpus; l != NULL; l = l->l_next) {
373 378 struct vcpu *v = l->l_ptr;
374 379
375 380 if ((nspec != 0) && (!v->v_doit))
376 381 continue;
377 382 (void) printf(_("Status of virtual processor %d as of: "),
378 383 l->l_id);
379 384 (void) printf("%s\n", timestr(time(NULL)));
380 385 (void) printf(_(" %s since %s.\n"),
381 386 _(v->v_state), timestr(v->v_state_begin));
382 387 if (v->v_clock_mhz) {
383 388 (void) printf(
384 389 _(" The %s processor operates at %llu MHz,\n"),
385 390 v->v_cpu_type, (unsigned long long)v->v_clock_mhz);
386 391 } else {
387 392 (void) printf(
388 393 _(" The %s processor operates at " \
389 394 "an unknown frequency,\n"), v->v_cpu_type);
390 395 }
391 396 switch (*v->v_fpu_type) {
392 397 case '\0':
393 398 (void) printf(
394 399 _("\tand has no floating point processor.\n"));
395 400 break;
396 401 case 'a': case 'A':
397 402 case 'e': case 'E':
398 403 case 'i': case 'I':
399 404 case 'o': case 'O':
400 405 case 'u': case 'U':
401 406 case 'y': case 'Y':
402 407 (void) printf(
403 408 _("\tand has an %s floating point processor.\n"),
404 409 v->v_fpu_type);
405 410 break;
406 411 default:
407 412 (void) printf(
408 413 _("\tand has a %s floating point processor.\n"),
409 414 v->v_fpu_type);
410 415 break;
411 416 }
412 417 }
413 418 }
414 419
415 420 static void
416 421 print_normal(int nspec)
417 422 {
418 423 struct link *l;
419 424 struct vcpu *v;
420 425
421 426 for (l = vcpus; l != NULL; l = l->l_next) {
422 427 v = l->l_ptr;
423 428 if ((nspec == 0) || (v->v_doit)) {
424 429 (void) printf(_("%d\t%-8s since %s\n"),
425 430 l->l_id, _(v->v_state), timestr(v->v_state_begin));
426 431 }
427 432 }
428 433 }
429 434
430 435 int
431 436 main(int argc, char **argv)
432 437 {
433 438 kstat_ctl_t *kc;
434 439 kstat_t *ksp;
435 440 kstat_named_t *knp;
436 441 struct vcpu *vc;
437 442 struct core *core;
438 443 struct pchip *chip;
439 444 struct link **ins;
440 445 char *s;
441 446 int nspec;
442 447 int optc;
443 448 int opt_s = 0;
444 449 int opt_p = 0;
445 450 int opt_v = 0;
446 451 int ex = 0;
447 452
448 453 cmdname = basename(argv[0]);
449 454
450 455
451 456 (void) setlocale(LC_ALL, "");
452 457 #if !defined(TEXT_DOMAIN)
453 458 #define TEXT_DOMAIN "SYS_TEST"
454 459 #endif
455 460 (void) textdomain(TEXT_DOMAIN);
456 461
457 462 /* collect the kstats */
458 463 if ((kc = kstat_open()) == NULL)
459 464 die(_("kstat_open() failed"));
460 465
461 466 if ((ksp = kstat_lookup(kc, "cpu_info", -1, NULL)) == NULL)
462 467 die(_("kstat_lookup() failed"));
463 468
464 469 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
465 470
466 471 if (strcmp(ksp->ks_module, "cpu_info") != 0)
467 472 continue;
468 473 if (kstat_read(kc, ksp, NULL) == NULL)
469 474 die(_("kstat_read() failed"));
470 475
471 476 vc = find_link(&vcpus, ksp->ks_instance, &ins);
472 477 if (vc == NULL) {
473 478 vc = zalloc(sizeof (struct vcpu));
474 479 vc->v_link.l_id = ksp->ks_instance;
475 480 vc->v_link_core.l_id = ksp->ks_instance;
476 481 vc->v_link_pchip.l_id = ksp->ks_instance;
477 482 vc->v_link.l_ptr = vc;
478 483 vc->v_link_core.l_ptr = vc;
479 484 vc->v_link_pchip.l_ptr = vc;
480 485 ins_link(ins, &vc->v_link);
481 486 }
482 487
483 488 if ((knp = kstat_data_lookup(ksp, "state")) != NULL) {
484 489 vc->v_state = mystrdup(knp->value.c);
485 490 } else {
486 491 vc->v_state = "unknown";
487 492 }
488 493
489 494 if ((knp = kstat_data_lookup(ksp, "cpu_type")) != NULL) {
490 495 vc->v_cpu_type = mystrdup(knp->value.c);
491 496 }
492 497 if ((knp = kstat_data_lookup(ksp, "fpu_type")) != NULL) {
493 498 vc->v_fpu_type = mystrdup(knp->value.c);
494 499 }
495 500
496 501 if ((knp = kstat_data_lookup(ksp, "state_begin")) != NULL) {
497 502 vc->v_state_begin = knp->value.l;
498 503 }
499 504
↓ open down ↓ |
219 lines elided |
↑ open up ↑ |
500 505 if ((knp = kstat_data_lookup(ksp, "clock_MHz")) != NULL) {
501 506 vc->v_clock_mhz = knp->value.l;
502 507 }
503 508
504 509 if ((knp = kstat_data_lookup(ksp, "brand")) == NULL) {
505 510 vc->v_brand = _("(unknown)");
506 511 } else {
507 512 vc->v_brand = mystrdup(knp->value.str.addr.ptr);
508 513 }
509 514
515 + if ((knp = kstat_data_lookup(ksp, "socket_type")) == NULL) {
516 + vc->v_socket = "Unknown";
517 + } else {
518 + vc->v_socket = mystrdup(knp->value.str.addr.ptr);
519 + }
520 +
510 521 if ((knp = kstat_data_lookup(ksp, "implementation")) == NULL) {
511 522 vc->v_impl = _("(unknown)");
512 523 } else {
513 524 vc->v_impl = mystrdup(knp->value.str.addr.ptr);
514 525 }
515 526 /*
516 527 * Legacy code removed the chipid and cpuid fields... we
517 528 * do the same for compatibility. Note that the original
518 529 * pattern is a bit strange, and we have to emulate this because
519 530 * on SPARC we *do* emit these. The original pattern we are
520 531 * emulating is: $impl =~ s/(cpuid|chipid)\s*\w+\s+//;
521 532 */
522 533 if ((s = strstr(vc->v_impl, "chipid")) != NULL) {
523 534 char *x = s + strlen("chipid");
524 535 while (isspace(*x))
525 536 x++;
526 537 if ((!isalnum(*x)) && (*x != '_'))
527 538 goto nochipid;
528 539 while (isalnum(*x) || (*x == '_'))
529 540 x++;
530 541 if (!isspace(*x))
531 542 goto nochipid;
532 543 while (isspace(*x))
533 544 x++;
534 545 (void) strcpy(s, x);
535 546 }
536 547 nochipid:
537 548 if ((s = strstr(vc->v_impl, "cpuid")) != NULL) {
538 549 char *x = s + strlen("cpuid");
539 550 while (isspace(*x))
540 551 x++;
541 552 if ((!isalnum(*x)) && (*x != '_'))
542 553 goto nocpuid;
543 554 while (isalnum(*x) || (*x == '_'))
544 555 x++;
545 556 if (!isspace(*x))
546 557 goto nocpuid;
547 558 while (isspace(*x))
548 559 x++;
549 560 (void) strcpy(s, x);
550 561 }
551 562 nocpuid:
552 563
553 564 if ((knp = kstat_data_lookup(ksp, "chip_id")) != NULL)
554 565 vc->v_pchip_id = knp->value.l;
555 566 chip = find_link(&pchips, vc->v_pchip_id, &ins);
556 567 if (chip == NULL) {
557 568 chip = zalloc(sizeof (struct pchip));
558 569 chip->p_link.l_id = vc->v_pchip_id;
559 570 chip->p_link.l_ptr = chip;
560 571 ins_link(ins, &chip->p_link);
561 572 }
562 573 vc->v_pchip = chip;
563 574
564 575 if ((knp = kstat_data_lookup(ksp, "core_id")) != NULL)
565 576 vc->v_core_id = knp->value.l;
566 577 core = find_link(&cores, vc->v_core_id, &ins);
567 578 if (core == NULL) {
568 579 core = zalloc(sizeof (struct core));
569 580 core->c_link.l_id = vc->v_core_id;
570 581 core->c_link.l_ptr = core;
571 582 core->c_link_pchip.l_id = vc->v_core_id;
572 583 core->c_link_pchip.l_ptr = core;
573 584 core->c_pchip = chip;
574 585 ins_link(ins, &core->c_link);
575 586 chip->p_ncore++;
576 587 (void) find_link(&chip->p_cores, core->c_link.l_id,
577 588 &ins);
578 589 ins_link(ins, &core->c_link_pchip);
579 590 }
580 591 vc->v_core = core;
581 592
582 593
583 594
584 595 /* now put other linkages in place */
585 596 (void) find_link(&chip->p_vcpus, vc->v_link.l_id, &ins);
586 597 ins_link(ins, &vc->v_link_pchip);
587 598 chip->p_nvcpu++;
588 599
589 600 (void) find_link(&core->c_vcpus, vc->v_link.l_id, &ins);
590 601 ins_link(ins, &vc->v_link_core);
591 602 core->c_nvcpu++;
592 603 }
593 604
594 605 (void) kstat_close(kc);
595 606
596 607 nspec = 0;
597 608
598 609 while ((optc = getopt(argc, argv, "pvs")) != EOF) {
599 610 switch (optc) {
600 611 case 's':
601 612 opt_s = 1;
602 613 break;
603 614 case 'p':
604 615 opt_p = 1;
605 616 break;
606 617 case 'v':
607 618 opt_v = 1;
608 619 break;
609 620 default:
610 621 usage(NULL);
611 622 }
612 623 }
613 624
614 625 while (optind < argc) {
615 626 long id;
616 627 char *eptr;
617 628 struct link *l;
618 629 id = strtol(argv[optind], &eptr, 10);
619 630 l = find_link(&vcpus, id, NULL);
620 631 if ((*eptr != '\0') || (l == NULL)) {
621 632 (void) fprintf(stderr,
622 633 _("%s: processor %s: Invalid argument\n"),
623 634 cmdname, argv[optind]);
624 635 ex = 2;
625 636 } else {
626 637 ((struct vcpu *)l->l_ptr)->v_doit = 1;
627 638 ((struct vcpu *)l->l_ptr)->v_pchip->p_doit = 1;
628 639 ((struct vcpu *)l->l_ptr)->v_core->c_doit = 1;
629 640 }
630 641 nspec++;
631 642 optind++;
632 643 }
633 644
634 645 if (opt_s && opt_v) {
635 646 usage(_("options -s and -v are mutually exclusive"));
636 647 }
637 648 if (opt_s && nspec != 1) {
638 649 usage(_("must specify exactly one processor if -s used"));
639 650 }
640 651 if (opt_v && opt_p) {
641 652 print_vp(nspec);
642 653 } else if (opt_s && opt_p) {
643 654 print_ps();
644 655 } else if (opt_p) {
645 656 print_p(nspec);
646 657 } else if (opt_v) {
647 658 print_v(nspec);
648 659 } else if (opt_s) {
649 660 print_s();
650 661 } else {
651 662 print_normal(nspec);
652 663 }
653 664
654 665 return (ex);
655 666 }
↓ open down ↓ |
136 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX