1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 /* 26 * Copyright (c) 2013, Joyent, Inc. All rights reserved. 27 */ 28 29 /* 30 * psrset - create and manage processor sets 31 */ 32 33 #include <sys/types.h> 34 #include <sys/procset.h> 35 #include <sys/processor.h> 36 #include <sys/pset.h> 37 #include <fcntl.h> 38 #include <stdio.h> 39 #include <errno.h> 40 #include <dirent.h> 41 #include <locale.h> 42 #include <string.h> 43 #include <limits.h> 44 #include <procfs.h> 45 #include <libproc.h> 46 #include <stdarg.h> 47 #include <zone.h> 48 49 #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */ 50 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ 51 #endif 52 53 #define MAX_PROCFS_PATH 80 54 55 #define ERR_OK 0 /* exit status for success */ 56 #define ERR_FAIL 1 /* exit status for errors */ 57 #define ERR_USAGE 2 /* exit status for usage errors */ 58 59 static char *progname; 60 static int errors; 61 static char cflag; 62 static char dflag; 63 static char aflag; 64 static char rflag; 65 static char iflag; 66 static char bflag; 67 static char uflag; 68 static char Uflag; 69 static char qflag; 70 static char Qflag; 71 static char pflag; 72 static char nflag; 73 static char fflag; 74 static char Fflag; 75 static char eflag; 76 static char zflag; 77 static const char *zname; 78 79 extern int pset_assign_forced(psetid_t, processorid_t, psetid_t *); 80 81 /*PRINTFLIKE1*/ 82 static void 83 warn(char *format, ...) 84 { 85 int err = errno; 86 va_list alist; 87 88 (void) fprintf(stderr, "%s: ", progname); 89 va_start(alist, format); 90 (void) vfprintf(stderr, format, alist); 91 va_end(alist); 92 if (strchr(format, '\n') == NULL) 93 (void) fprintf(stderr, ": %s\n", strerror(err)); 94 } 95 96 /*PRINTFLIKE1*/ 97 static void 98 die(char *format, ...) 99 { 100 int err = errno; 101 va_list alist; 102 103 (void) fprintf(stderr, "%s: ", progname); 104 va_start(alist, format); 105 (void) vfprintf(stderr, format, alist); 106 va_end(alist); 107 if (strchr(format, '\n') == NULL) 108 (void) fprintf(stderr, ": %s\n", strerror(err)); 109 exit(ERR_FAIL); 110 } 111 112 static struct ps_prochandle * 113 grab_proc(id_t pid) 114 { 115 int ret; 116 struct ps_prochandle *Pr; 117 118 if ((Pr = Pgrab(pid, 0, &ret)) == NULL) { 119 warn(gettext("cannot control process %d: %s\n"), 120 (int)pid, Pgrab_error(ret)); 121 errors = ERR_FAIL; 122 return (NULL); 123 } 124 125 return (Pr); 126 } 127 128 static void 129 rele_proc(struct ps_prochandle *Pr) 130 { 131 if (Pr == NULL) 132 return; 133 Prelease(Pr, 0); 134 } 135 136 static void 137 bind_err(psetid_t pset, const char *zname, id_t pid, id_t lwpid, int err) 138 { 139 char *msg; 140 141 switch (pset) { 142 case PS_NONE: 143 msg = gettext("unbind"); 144 break; 145 case PS_QUERY: 146 msg = gettext("query"); 147 break; 148 default: 149 msg = gettext("bind"); 150 break; 151 } 152 153 errno = err; 154 if (zname != NULL) 155 warn(gettext("cannot %s zone %s"), msg, zname); 156 else if (lwpid == -1) 157 warn(gettext("cannot %s pid %d"), msg, pid); 158 else 159 warn(gettext("cannot %s lwpid %d/%d"), msg, pid, lwpid); 160 } 161 162 /* 163 * Output for create. 164 */ 165 static void 166 create_out(psetid_t pset) 167 { 168 (void) printf("%s %d\n", gettext("created processor set"), pset); 169 } 170 171 /* 172 * Output for assign. 173 */ 174 static void 175 assign_out(processorid_t cpu, psetid_t old, psetid_t new) 176 { 177 if (old == PS_NONE) { 178 if (new == PS_NONE) 179 (void) printf(gettext("processor %d: was not assigned," 180 " now not assigned\n"), cpu); 181 else 182 (void) printf(gettext("processor %d: was not assigned," 183 " now %d\n"), cpu, new); 184 } else { 185 if (new == PS_NONE) 186 (void) printf(gettext("processor %d: was %d, " 187 "now not assigned\n"), cpu, old); 188 else 189 (void) printf(gettext("processor %d: was %d, " 190 "now %d\n"), cpu, old, new); 191 } 192 } 193 194 /* 195 * Output for query. 196 */ 197 static void 198 query_out(id_t pid, id_t lwpid, psetid_t pset) 199 { 200 char *proclwp; 201 char pidstr[21]; 202 203 if (lwpid == -1) { 204 (void) snprintf(pidstr, 20, "%d", pid); 205 proclwp = "process"; 206 } else { 207 (void) snprintf(pidstr, 20, "%d/%d", pid, lwpid); 208 proclwp = "lwp"; 209 } 210 211 if (pset == PS_NONE) 212 (void) printf(gettext("%s id %s: not bound\n"), 213 proclwp, pidstr); 214 else 215 (void) printf(gettext("%s id %s: %d\n"), proclwp, pidstr, pset); 216 } 217 218 /* 219 * Output for info. 220 */ 221 static void 222 info_out(psetid_t pset, int type, uint_t numcpus, processorid_t *cpus) 223 { 224 int i; 225 if (type == PS_SYSTEM) 226 (void) printf(gettext("system processor set %d:"), pset); 227 else 228 (void) printf(gettext("user processor set %d:"), pset); 229 if (numcpus == 0) 230 (void) printf(gettext(" empty")); 231 else if (numcpus > 1) 232 (void) printf(gettext(" processors")); 233 else 234 (void) printf(gettext(" processor")); 235 for (i = 0; i < numcpus; i++) 236 (void) printf(" %d", cpus[i]); 237 (void) printf("\n"); 238 } 239 240 /* 241 * Output for print. 242 */ 243 static void 244 print_out(processorid_t cpu, psetid_t pset) 245 { 246 if (pset == PS_NONE) 247 (void) printf(gettext("processor %d: not assigned\n"), cpu); 248 else 249 (void) printf(gettext("processor %d: %d\n"), cpu, pset); 250 } 251 252 /* 253 * Output for bind. 254 */ 255 static void 256 bind_out(id_t pid, id_t lwpid, psetid_t old, psetid_t new) 257 { 258 char *proclwp; 259 char pidstr[21]; 260 261 if (lwpid == -1) { 262 (void) snprintf(pidstr, 20, "%d", pid); 263 proclwp = "process"; 264 } else { 265 (void) snprintf(pidstr, 20, "%d/%d", pid, lwpid); 266 proclwp = "lwp"; 267 } 268 269 if (old == PS_NONE) { 270 if (new == PS_NONE) 271 (void) printf(gettext("%s id %s: was not bound, " 272 "now not bound\n"), proclwp, pidstr); 273 else 274 (void) printf(gettext("%s id %s: was not bound, " 275 "now %d\n"), proclwp, pidstr, new); 276 } else { 277 if (new == PS_NONE) 278 (void) printf(gettext("%s id %s: was %d, " 279 "now not bound\n"), proclwp, pidstr, old); 280 else 281 (void) printf(gettext("%s id %s: was %d, " 282 "now %d\n"), proclwp, pidstr, old, new); 283 } 284 } 285 286 static void 287 bind_lwp(id_t pid, id_t lwpid, psetid_t pset) 288 { 289 psetid_t old_pset; 290 291 if (pset_bind_lwp(pset, lwpid, pid, &old_pset) != 0) { 292 bind_err(pset, NULL, pid, lwpid, errno); 293 errors = ERR_FAIL; 294 } 295 if (errors != ERR_FAIL) { 296 if (qflag) 297 query_out(pid, lwpid, old_pset); 298 else 299 bind_out(pid, lwpid, old_pset, pset); 300 } 301 } 302 303 static int 304 do_cpu(psetid_t pset, processorid_t cpu, int print, int mustexist) 305 { 306 psetid_t old_pset; 307 int err; 308 309 if ((!Fflag && pset_assign(pset, cpu, &old_pset) != 0) || 310 (Fflag && pset_assign_forced(pset, cpu, &old_pset) != 0)) { 311 if (errno == EINVAL && !mustexist) 312 return (EINVAL); 313 err = errno; 314 315 switch (pset) { 316 case PS_NONE: 317 warn(gettext("cannot remove processor %d"), cpu); 318 break; 319 case PS_QUERY: 320 warn(gettext("cannot query processor %d"), cpu); 321 break; 322 default: 323 warn(gettext("cannot assign processor %d"), cpu); 324 break; 325 } 326 return (err); 327 } 328 if (print) 329 print_out(cpu, old_pset); 330 else 331 assign_out(cpu, old_pset, pset); 332 return (0); 333 } 334 335 static int 336 do_range(psetid_t pset, processorid_t first, processorid_t last, int print) 337 { 338 processorid_t cpu; 339 int error = ERR_OK; 340 int err; 341 int found_one = 0; 342 343 for (cpu = first; cpu <= last; cpu++) { 344 if ((err = do_cpu(pset, cpu, print, 0)) == 0) 345 found_one = 1; 346 else if (err != EINVAL) 347 error = ERR_FAIL; 348 } 349 if (!found_one && error == ERR_OK) { 350 warn(gettext("no processors in range %d-%d\n"), first, last); 351 error = ERR_FAIL; 352 } 353 return (error); 354 } 355 356 static int 357 do_info(psetid_t pset) 358 { 359 int type; 360 uint_t numcpus; 361 processorid_t *cpus; 362 363 numcpus = (uint_t)sysconf(_SC_NPROCESSORS_MAX); 364 cpus = (processorid_t *) 365 malloc(numcpus * sizeof (processorid_t)); 366 if (cpus == NULL) { 367 warn(gettext("memory allocation failed")); 368 return (ERR_FAIL); 369 } 370 if (pset_info(pset, &type, &numcpus, cpus) != 0) { 371 warn(gettext("cannot get info for processor set %d"), pset); 372 free(cpus); 373 return (ERR_FAIL); 374 } 375 info_out(pset, type, numcpus, cpus); 376 free(cpus); 377 return (ERR_OK); 378 } 379 380 static int 381 do_destroy(psetid_t pset) 382 { 383 if (pset_destroy(pset) != 0) { 384 warn(gettext("could not remove processor set %d"), pset); 385 return (ERR_FAIL); 386 } 387 (void) printf(gettext("removed processor set %d\n"), pset); 388 return (ERR_OK); 389 } 390 391 static int 392 do_intr(psetid_t pset, int flag) 393 { 394 uint_t i, numcpus; 395 processorid_t *cpus; 396 int error = ERR_OK; 397 398 numcpus = (uint_t)sysconf(_SC_NPROCESSORS_MAX); 399 cpus = (processorid_t *) 400 malloc(numcpus * sizeof (processorid_t)); 401 if (cpus == NULL) { 402 warn(gettext("memory allocation failed")); 403 return (ERR_FAIL); 404 } 405 if (pset_info(pset, NULL, &numcpus, cpus) != 0) { 406 warn(gettext( 407 "cannot set interrupt status for processor set %d"), pset); 408 free(cpus); 409 return (ERR_FAIL); 410 } 411 for (i = 0; i < numcpus; i++) { 412 int status = p_online(cpus[i], P_STATUS); 413 if (status != P_OFFLINE && status != P_POWEROFF && 414 status != flag) { 415 if (p_online(cpus[i], flag) == -1) { 416 warn(gettext("processor %d"), cpus[i]); 417 error = ERR_FAIL; 418 } 419 } 420 } 421 free(cpus); 422 return (error); 423 } 424 425 /* 426 * Query the type and CPUs for all active processor sets in the system. 427 */ 428 static int 429 info_all(void) 430 { 431 psetid_t *psetlist; 432 uint_t npsets, oldnpsets; 433 int i; 434 int errors = ERR_OK; 435 436 if (pset_list(NULL, &npsets) != 0) { 437 warn(gettext("cannot get number of processor sets")); 438 return (1); 439 } 440 for (;;) { 441 psetlist = malloc(sizeof (psetid_t) * npsets); 442 if (psetlist == NULL) { 443 warn(gettext("memory allocation failed")); 444 return (ERR_FAIL); 445 } 446 oldnpsets = npsets; 447 if (pset_list(psetlist, &npsets) != 0) { 448 warn(gettext("cannot get list of processor sets")); 449 free(psetlist); 450 return (ERR_FAIL); 451 } 452 if (npsets <= oldnpsets) 453 break; 454 free(psetlist); 455 } 456 457 for (i = 0; i < npsets; i++) { 458 if (do_info(psetlist[i])) 459 errors = ERR_FAIL; 460 } 461 free(psetlist); 462 return (errors); 463 } 464 465 /* 466 * Query the processor set assignments for all CPUs in the system. 467 */ 468 static int 469 print_all(void) 470 { 471 psetid_t pset; 472 processorid_t cpuid, max_cpuid; 473 int errors = ERR_OK; 474 475 max_cpuid = (processorid_t)sysconf(_SC_CPUID_MAX); 476 for (cpuid = 0; cpuid <= max_cpuid; cpuid++) { 477 if (pset_assign(PS_QUERY, cpuid, &pset) == 0) { 478 if (pset != PS_NONE) 479 print_out(cpuid, pset); 480 } else if (errno != EINVAL) { 481 warn(gettext("cannot query processor %d"), cpuid); 482 errors = ERR_FAIL; 483 } 484 } 485 return (errors); 486 } 487 488 /*ARGSUSED*/ 489 static int 490 query_all_proc(psinfo_t *psinfo, lwpsinfo_t *lwpsinfo, void *arg) 491 { 492 id_t pid = psinfo->pr_pid; 493 psetid_t binding; 494 495 if (pset_bind(PS_QUERY, P_PID, pid, &binding) < 0) { 496 /* 497 * Ignore search errors. The process may have exited 498 * since we read the directory. 499 */ 500 if (errno == ESRCH) 501 return (0); 502 bind_err(PS_QUERY, NULL, pid, -1, errno); 503 errors = ERR_FAIL; 504 return (0); 505 } 506 if (binding != PS_NONE) 507 query_out(pid, -1, binding); 508 return (0); 509 } 510 511 static int 512 query_all_lwp(psinfo_t *psinfo, lwpsinfo_t *lwpsinfo, void *arg) 513 { 514 id_t pid = psinfo->pr_pid; 515 id_t lwpid = lwpsinfo->pr_lwpid; 516 psetid_t *cpuid = arg; 517 psetid_t binding = lwpsinfo->pr_bindpset; 518 519 if (psinfo->pr_nlwp == 1) 520 lwpid = -1; /* report process bindings if only 1 lwp */ 521 if ((cpuid != NULL && *cpuid == binding) || 522 (cpuid == NULL && binding != PBIND_NONE)) 523 query_out(pid, lwpid, binding); 524 return (0); 525 } 526 527 void 528 exec_cmd(psetid_t pset, char **argv) 529 { 530 if (pset_bind(pset, P_PID, P_MYID, NULL) != 0) { 531 warn(gettext("cannot exec in processor set %d"), pset); 532 return; 533 } 534 535 (void) execvp(argv[0], argv); 536 warn(gettext("cannot exec command %s"), argv[0]); 537 } 538 539 int 540 usage(void) 541 { 542 (void) fprintf(stderr, gettext( 543 "usage: \n" 544 "\t%1$s -c [-F] [processor_id ...]\n" 545 "\t%1$s -d processor_set_id ...\n" 546 "\t%1$s -n processor_set_id\n" 547 "\t%1$s -f processor_set_id\n" 548 "\t%1$s -e processor_set_id command [argument(s)...]\n" 549 "\t%1$s -a [-F] processor_set_id processor_id ...\n" 550 "\t%1$s -r [-F] processor_id ...\n" 551 "\t%1$s -p [processorid ...]\n" 552 "\t%1$s -b processor_set_id pid[/lwpids] ...\n" 553 "\t%1$s -b -z zonename processor_set_id\n" 554 "\t%1$s -u pid[/lwpids] ...\n" 555 "\t%1$s -q [pid[/lwpids] ...]\n" 556 "\t%1$s -U [processor_set_id] ...\n" 557 "\t%1$s -Q [processor_set_id] ...\n" 558 "\t%1$s [-i] [processor_set_id ...]\n"), 559 progname); 560 return (ERR_USAGE); 561 } 562 563 /* 564 * Query, set, or clear bindings for the range of LWPs in the given process. 565 */ 566 static int 567 do_lwps(id_t pid, const char *range, psetid_t pset) 568 { 569 char procfile[MAX_PROCFS_PATH]; 570 struct ps_prochandle *Pr; 571 struct prheader header; 572 struct lwpsinfo *lwp; 573 char *lpsinfo, *ptr; 574 psetid_t binding; 575 int nent, size; 576 int i, fd, found; 577 578 /* 579 * Report bindings for LWPs in process 'pid'. 580 */ 581 (void) snprintf(procfile, MAX_PROCFS_PATH, 582 "/proc/%d/lpsinfo", (int)pid); 583 if ((fd = open(procfile, O_RDONLY)) < 0) { 584 if (errno == ENOENT) 585 errno = ESRCH; 586 bind_err(pset, NULL, pid, -1, errno); 587 return (ERR_FAIL); 588 } 589 if (pread(fd, &header, sizeof (header), 0) != sizeof (header)) { 590 (void) close(fd); 591 bind_err(pset, NULL, pid, -1, errno); 592 return (ERR_FAIL); 593 } 594 nent = header.pr_nent; 595 size = header.pr_entsize * nent; 596 ptr = lpsinfo = malloc(size); 597 if (lpsinfo == NULL) { 598 bind_err(pset, NULL, pid, -1, errno); 599 return (ERR_FAIL); 600 } 601 if (pread(fd, lpsinfo, size, sizeof (header)) != size) { 602 bind_err(pset, NULL, pid, -1, errno); 603 free(lpsinfo); 604 (void) close(fd); 605 return (ERR_FAIL); 606 } 607 608 if ((bflag || uflag) && (Pr = grab_proc(pid)) == NULL) { 609 free(lpsinfo); 610 (void) close(fd); 611 return (ERR_FAIL); 612 } 613 found = 0; 614 for (i = 0; i < nent; i++, ptr += header.pr_entsize) { 615 /*LINTED ALIGNMENT*/ 616 lwp = (lwpsinfo_t *)ptr; 617 binding = lwp->pr_bindpset; 618 if (!proc_lwp_in_set(range, lwp->pr_lwpid)) 619 continue; 620 found++; 621 if (bflag || uflag) 622 bind_lwp(pid, lwp->pr_lwpid, pset); 623 else if (binding != PBIND_NONE) 624 query_out(pid, lwp->pr_lwpid, binding); 625 } 626 if (bflag || uflag) 627 rele_proc(Pr); 628 free(lpsinfo); 629 (void) close(fd); 630 if (found == 0) { 631 warn(gettext("cannot %s lwpid %d/%s: " 632 "No matching LWPs found\n"), 633 bflag ? "bind" : "query", pid, range); 634 return (ERR_FAIL); 635 } 636 return (ERR_OK); 637 } 638 639 int 640 main(int argc, char *argv[]) 641 { 642 extern int optind; 643 int c; 644 id_t pid; 645 processorid_t cpu; 646 psetid_t pset, old_pset; 647 zoneid_t zid; 648 char *errptr; 649 650 progname = argv[0]; /* put actual command name in messages */ 651 652 (void) setlocale(LC_ALL, ""); /* setup localization */ 653 (void) textdomain(TEXT_DOMAIN); 654 655 while ((c = getopt(argc, argv, "cdFarpibqQuUnfez:")) != EOF) { 656 switch (c) { 657 case 'c': 658 cflag = 1; 659 break; 660 case 'd': 661 dflag = 1; 662 break; 663 case 'e': 664 eflag = 1; 665 break; 666 case 'a': 667 aflag = 1; 668 break; 669 case 'r': 670 rflag = 1; 671 pset = PS_NONE; 672 break; 673 case 'p': 674 pflag = 1; 675 pset = PS_QUERY; 676 break; 677 case 'i': 678 iflag = 1; 679 break; 680 case 'b': 681 bflag = 1; 682 break; 683 case 'u': 684 uflag = 1; 685 pset = PS_NONE; 686 break; 687 case 'U': 688 Uflag = 1; 689 break; 690 case 'q': 691 qflag = 1; 692 pset = PS_QUERY; 693 break; 694 case 'Q': 695 Qflag = 1; 696 break; 697 case 'f': 698 fflag = 1; 699 break; 700 case 'F': 701 Fflag = 1; 702 break; 703 case 'n': 704 nflag = 1; 705 break; 706 case 'z': 707 if (!bflag) { 708 warn(gettext("-z can only be used after -b\n")); 709 return (usage()); 710 } 711 if (zflag) { 712 warn(gettext("-z can only be specified " 713 "once\n")); 714 return (usage()); 715 } 716 zflag = 1; 717 zname = optarg; 718 break; 719 default: 720 return (usage()); 721 } 722 } 723 724 /* 725 * Make sure that at most one of the options was specified. 726 */ 727 c = cflag + dflag + aflag + rflag + pflag + 728 iflag + bflag + uflag + Uflag + 729 qflag + Qflag + fflag + nflag + eflag; 730 if (c < 1) { /* nothing specified */ 731 iflag = 1; /* default is to get info */ 732 } else if (c > 1) { 733 warn(gettext("options are mutually exclusive\n")); 734 return (usage()); 735 } 736 737 if (Fflag && (cflag + aflag + rflag == 0)) 738 return (usage()); 739 740 errors = 0; 741 argc -= optind; 742 argv += optind; 743 744 if (argc == 0) { 745 /* 746 * Handle single option cases. 747 */ 748 if (qflag) { 749 (void) proc_walk(query_all_proc, NULL, PR_WALK_PROC); 750 return (errors); 751 } 752 if (Qflag) { 753 (void) proc_walk(query_all_lwp, NULL, PR_WALK_LWP); 754 return (errors); 755 } 756 if (Uflag) { 757 if (pset_bind(PS_NONE, P_ALL, 0, &old_pset) != 0) 758 die(gettext("failed to unbind all LWPs")); 759 } 760 if (pflag) 761 return (print_all()); 762 if (iflag) 763 return (info_all()); 764 } 765 766 /* 767 * Get processor set id. 768 */ 769 if (aflag || bflag || fflag || nflag || eflag) { 770 if (argc < 1) { 771 /* must specify processor set */ 772 warn(gettext("must specify processor set\n")); 773 return (usage()); 774 } 775 pset = strtol(*argv, &errptr, 10); 776 if (errptr != NULL && *errptr != '\0' || pset < 0) { 777 warn(gettext("invalid processor set ID %s\n"), *argv); 778 return (ERR_FAIL); 779 } 780 argv++; 781 argc--; 782 } 783 784 if (cflag) { 785 if (pset_create(&pset) != 0) { 786 warn(gettext("could not create processor set")); 787 return (ERR_FAIL); 788 } else { 789 create_out(pset); 790 if (argc == 0) 791 return (ERR_OK); 792 } 793 } else if (iflag || dflag) { 794 if (argc == 0) { 795 warn(gettext("must specify at least one " 796 "processor set\n")); 797 return (usage()); 798 } 799 /* 800 * Go through listed processor sets. 801 */ 802 for (; argc > 0; argv++, argc--) { 803 pset = (psetid_t)strtol(*argv, &errptr, 10); 804 if (errptr != NULL && *errptr != '\0') { 805 warn(gettext("invalid processor set ID %s\n"), 806 *argv); 807 errors = ERR_FAIL; 808 continue; 809 } 810 if (iflag) { 811 errors = do_info(pset); 812 } else { 813 errors = do_destroy(pset); 814 } 815 } 816 } else if (nflag) { 817 errors = do_intr(pset, P_ONLINE); 818 } else if (fflag) { 819 errors = do_intr(pset, P_NOINTR); 820 } else if (eflag) { 821 if (argc == 0) { 822 warn(gettext("must specify command\n")); 823 return (usage()); 824 } 825 exec_cmd(pset, argv); 826 /* if returning, must have had an error */ 827 return (ERR_USAGE); 828 } 829 830 if (cflag || aflag || rflag || pflag) { 831 /* 832 * Perform function for each processor specified. 833 */ 834 if (argc == 0) { 835 warn(gettext("must specify at least one processor\n")); 836 return (usage()); 837 } 838 839 /* 840 * Go through listed processors. 841 */ 842 for (; argc > 0; argv++, argc--) { 843 if (strchr(*argv, '-') == NULL) { 844 /* individual processor id */ 845 cpu = (processorid_t)strtol(*argv, &errptr, 10); 846 if (errptr != NULL && *errptr != '\0') { 847 warn(gettext("invalid processor " 848 "ID %s\n"), *argv); 849 errors = ERR_FAIL; 850 continue; 851 } 852 if (do_cpu(pset, cpu, pflag, 1)) 853 errors = ERR_FAIL; 854 } else { 855 /* range of processors */ 856 processorid_t first, last; 857 858 first = (processorid_t) 859 strtol(*argv, &errptr, 10); 860 if (*errptr++ != '-') { 861 warn(gettext( 862 "invalid processor range %s\n"), 863 *argv); 864 errors = ERR_USAGE; 865 continue; 866 } 867 last = (processorid_t) 868 strtol(errptr, &errptr, 10); 869 if ((errptr != NULL && *errptr != '\0') || 870 last < first || first < 0) { 871 warn(gettext( 872 "invalid processor range %s\n"), 873 *argv); 874 errors = ERR_USAGE; 875 continue; 876 } 877 if (do_range(pset, first, last, pflag)) 878 errors = ERR_FAIL; 879 } 880 } 881 } else if (bflag || uflag || qflag) { 882 /* 883 * Perform function for each pid/lwpid specified. 884 */ 885 if (argc == 0 && !zflag) { 886 warn(gettext("must specify at least one pid\n")); 887 return (usage()); 888 } else if (argc > 0 && zflag) { 889 warn(gettext("cannot specify extra pids with -z\n")); 890 return (usage()); 891 } 892 893 if (zflag) { 894 zid = getzoneidbyname(zname); 895 if (zid < 0) { 896 warn(gettext("invalid zone name: %s\n"), 897 zname); 898 errors = ERR_FAIL; 899 } else if (pset_bind(pset, P_ZONEID, zid, 900 &old_pset) < 0) { 901 bind_err(pset, zname, -1, -1, errno); 902 errors = ERR_FAIL; 903 } else { 904 (void) printf(gettext("zone %s: bound to %d\n"), 905 zname, pset); 906 } 907 } 908 909 /* 910 * Go through listed processes/lwp_ranges. 911 */ 912 for (; argc > 0; argv++, argc--) { 913 pid = (id_t)strtol(*argv, &errptr, 10); 914 if (errno != 0 || 915 (errptr != NULL && *errptr != '\0' && 916 *errptr != '/')) { 917 warn(gettext("invalid process ID: %s\n"), 918 *argv); 919 continue; 920 } 921 if (errptr != NULL && *errptr == '/') { 922 int ret; 923 /* 924 * Handle lwp range case 925 */ 926 const char *lwps = (const char *)(++errptr); 927 if (*lwps == '\0' || 928 proc_lwp_range_valid(lwps) != 0) { 929 warn(gettext("invalid lwp range " 930 "for pid %d\n"), (int)pid); 931 errors = ERR_FAIL; 932 continue; 933 } 934 if (!qflag) 935 (void) proc_initstdio(); 936 ret = do_lwps(pid, lwps, pset); 937 if (!qflag) 938 (void) proc_finistdio(); 939 if (ret != ERR_OK) 940 errors = ret; 941 } else { 942 /* 943 * Handle whole process case. 944 */ 945 if (pset_bind(pset, P_PID, pid, 946 &old_pset) < 0) { 947 bind_err(pset, NULL, pid, -1, errno); 948 errors = ERR_FAIL; 949 continue; 950 } 951 if (qflag) 952 query_out(pid, -1, old_pset); 953 else 954 bind_out(pid, -1, old_pset, pset); 955 } 956 } 957 } 958 959 if (Qflag || Uflag) { 960 /* 961 * Go through listed processor set IDs. 962 */ 963 for (; argc > 0; argv++, argc--) { 964 errno = 0; 965 pset = (id_t)strtol(*argv, &errptr, 10); 966 if (errno != 0 || 967 (errptr != NULL && *errptr != '\0')) { 968 warn(gettext("invalid processor set ID\n")); 969 continue; 970 } 971 if (Qflag) { 972 (void) proc_walk(query_all_lwp, 973 &pset, PR_WALK_LWP); 974 continue; 975 } 976 if (Uflag) { 977 if (pset_bind(PS_NONE, P_PSETID, pset, 978 &old_pset) != 0) { 979 warn(gettext("failed to unbind from " 980 "processor set %d"), (int)pset); 981 errors = ERR_FAIL; 982 } 983 continue; 984 } 985 } 986 } 987 988 return (errors); 989 } 990