8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / psrset / psrset.c
blob41724137efbfff71ed34da97ea8afd579993b534
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
30 * psrset - create and manage processor sets
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>
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
53 #define MAX_PROCFS_PATH 80
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 */
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;
79 extern int pset_assign_forced(psetid_t, processorid_t, psetid_t *);
81 /*PRINTFLIKE1*/
82 static void
83 warn(char *format, ...)
85 int err = errno;
86 va_list alist;
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));
96 /*PRINTFLIKE1*/
97 static void
98 die(char *format, ...)
100 int err = errno;
101 va_list alist;
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);
112 static struct ps_prochandle *
113 grab_proc(id_t pid)
115 int ret;
116 struct ps_prochandle *Pr;
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);
125 return (Pr);
128 static void
129 rele_proc(struct ps_prochandle *Pr)
131 if (Pr == NULL)
132 return;
133 Prelease(Pr, 0);
136 static void
137 bind_err(psetid_t pset, const char *zname, id_t pid, id_t lwpid, int err)
139 char *msg;
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;
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);
163 * Output for create.
165 static void
166 create_out(psetid_t pset)
168 (void) printf("%s %d\n", gettext("created processor set"), pset);
172 * Output for assign.
174 static void
175 assign_out(processorid_t cpu, psetid_t old, psetid_t new)
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);
195 * Output for query.
197 static void
198 query_out(id_t pid, id_t lwpid, psetid_t pset)
200 char *proclwp;
201 char pidstr[21];
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";
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);
219 * Output for info.
221 static void
222 info_out(psetid_t pset, int type, uint_t numcpus, processorid_t *cpus)
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");
241 * Output for print.
243 static void
244 print_out(processorid_t cpu, psetid_t pset)
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);
253 * Output for bind.
255 static void
256 bind_out(id_t pid, id_t lwpid, psetid_t old, psetid_t new)
258 char *proclwp;
259 char pidstr[21];
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";
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);
286 static void
287 bind_lwp(id_t pid, id_t lwpid, psetid_t pset)
289 psetid_t old_pset;
291 if (pset_bind_lwp(pset, lwpid, pid, &old_pset) != 0) {
292 bind_err(pset, NULL, pid, lwpid, errno);
293 errors = ERR_FAIL;
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);
303 static int
304 do_cpu(psetid_t pset, processorid_t cpu, int print, int mustexist)
306 psetid_t old_pset;
307 int err;
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;
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;
326 return (err);
328 if (print)
329 print_out(cpu, old_pset);
330 else
331 assign_out(cpu, old_pset, pset);
332 return (0);
335 static int
336 do_range(psetid_t pset, processorid_t first, processorid_t last, int print)
338 processorid_t cpu;
339 int error = ERR_OK;
340 int err;
341 int found_one = 0;
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;
349 if (!found_one && error == ERR_OK) {
350 warn(gettext("no processors in range %d-%d\n"), first, last);
351 error = ERR_FAIL;
353 return (error);
356 static int
357 do_info(psetid_t pset)
359 int type;
360 uint_t numcpus;
361 processorid_t *cpus;
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);
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);
375 info_out(pset, type, numcpus, cpus);
376 free(cpus);
377 return (ERR_OK);
380 static int
381 do_destroy(psetid_t pset)
383 if (pset_destroy(pset) != 0) {
384 warn(gettext("could not remove processor set %d"), pset);
385 return (ERR_FAIL);
387 (void) printf(gettext("removed processor set %d\n"), pset);
388 return (ERR_OK);
391 static int
392 do_intr(psetid_t pset, int flag)
394 uint_t i, numcpus;
395 processorid_t *cpus;
396 int error = ERR_OK;
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);
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);
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;
421 free(cpus);
422 return (error);
426 * Query the type and CPUs for all active processor sets in the system.
428 static int
429 info_all(void)
431 psetid_t *psetlist;
432 uint_t npsets, oldnpsets;
433 int i;
434 int errors = ERR_OK;
436 if (pset_list(NULL, &npsets) != 0) {
437 warn(gettext("cannot get number of processor sets"));
438 return (1);
440 for (;;) {
441 psetlist = malloc(sizeof (psetid_t) * npsets);
442 if (psetlist == NULL) {
443 warn(gettext("memory allocation failed"));
444 return (ERR_FAIL);
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);
452 if (npsets <= oldnpsets)
453 break;
454 free(psetlist);
457 for (i = 0; i < npsets; i++) {
458 if (do_info(psetlist[i]))
459 errors = ERR_FAIL;
461 free(psetlist);
462 return (errors);
466 * Query the processor set assignments for all CPUs in the system.
468 static int
469 print_all(void)
471 psetid_t pset;
472 processorid_t cpuid, max_cpuid;
473 int errors = ERR_OK;
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;
485 return (errors);
488 /*ARGSUSED*/
489 static int
490 query_all_proc(psinfo_t *psinfo, lwpsinfo_t *lwpsinfo, void *arg)
492 id_t pid = psinfo->pr_pid;
493 psetid_t binding;
495 if (pset_bind(PS_QUERY, P_PID, pid, &binding) < 0) {
497 * Ignore search errors. The process may have exited
498 * since we read the directory.
500 if (errno == ESRCH)
501 return (0);
502 bind_err(PS_QUERY, NULL, pid, -1, errno);
503 errors = ERR_FAIL;
504 return (0);
506 if (binding != PS_NONE)
507 query_out(pid, -1, binding);
508 return (0);
511 static int
512 query_all_lwp(psinfo_t *psinfo, lwpsinfo_t *lwpsinfo, void *arg)
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;
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);
527 void
528 exec_cmd(psetid_t pset, char **argv)
530 if (pset_bind(pset, P_PID, P_MYID, NULL) != 0) {
531 warn(gettext("cannot exec in processor set %d"), pset);
532 return;
535 (void) execvp(argv[0], argv);
536 warn(gettext("cannot exec command %s"), argv[0]);
540 usage(void)
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);
564 * Query, set, or clear bindings for the range of LWPs in the given process.
566 static int
567 do_lwps(id_t pid, const char *range, psetid_t pset)
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;
579 * Report bindings for LWPs in process 'pid'.
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);
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);
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);
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);
608 if ((bflag || uflag) && (Pr = grab_proc(pid)) == NULL) {
609 free(lpsinfo);
610 (void) close(fd);
611 return (ERR_FAIL);
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);
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);
636 return (ERR_OK);
640 main(int argc, char *argv[])
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;
650 progname = argv[0]; /* put actual command name in messages */
652 (void) setlocale(LC_ALL, ""); /* setup localization */
653 (void) textdomain(TEXT_DOMAIN);
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());
711 if (zflag) {
712 warn(gettext("-z can only be specified "
713 "once\n"));
714 return (usage());
716 zflag = 1;
717 zname = optarg;
718 break;
719 default:
720 return (usage());
725 * Make sure that at most one of the options was specified.
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());
737 if (Fflag && (cflag + aflag + rflag == 0))
738 return (usage());
740 errors = 0;
741 argc -= optind;
742 argv += optind;
744 if (argc == 0) {
746 * Handle single option cases.
748 if (qflag) {
749 (void) proc_walk(query_all_proc, NULL, PR_WALK_PROC);
750 return (errors);
752 if (Qflag) {
753 (void) proc_walk(query_all_lwp, NULL, PR_WALK_LWP);
754 return (errors);
756 if (Uflag) {
757 if (pset_bind(PS_NONE, P_ALL, 0, &old_pset) != 0)
758 die(gettext("failed to unbind all LWPs"));
760 if (pflag)
761 return (print_all());
762 if (iflag)
763 return (info_all());
767 * Get processor set id.
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());
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);
780 argv++;
781 argc--;
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);
793 } else if (iflag || dflag) {
794 if (argc == 0) {
795 warn(gettext("must specify at least one "
796 "processor set\n"));
797 return (usage());
800 * Go through listed processor sets.
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;
810 if (iflag) {
811 errors = do_info(pset);
812 } else {
813 errors = do_destroy(pset);
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());
825 exec_cmd(pset, argv);
826 /* if returning, must have had an error */
827 return (ERR_USAGE);
830 if (cflag || aflag || rflag || pflag) {
832 * Perform function for each processor specified.
834 if (argc == 0) {
835 warn(gettext("must specify at least one processor\n"));
836 return (usage());
840 * Go through listed processors.
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;
852 if (do_cpu(pset, cpu, pflag, 1))
853 errors = ERR_FAIL;
854 } else {
855 /* range of processors */
856 processorid_t first, last;
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;
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;
877 if (do_range(pset, first, last, pflag))
878 errors = ERR_FAIL;
881 } else if (bflag || uflag || qflag) {
883 * Perform function for each pid/lwpid specified.
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());
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);
910 * Go through listed processes/lwp_ranges.
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;
921 if (errptr != NULL && *errptr == '/') {
922 int ret;
924 * Handle lwp range case
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;
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 {
943 * Handle whole process case.
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;
951 if (qflag)
952 query_out(pid, -1, old_pset);
953 else
954 bind_out(pid, -1, old_pset, pset);
959 if (Qflag || Uflag) {
961 * Go through listed processor set IDs.
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;
971 if (Qflag) {
972 (void) proc_walk(query_all_lwp,
973 &pset, PR_WALK_LWP);
974 continue;
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;
983 continue;
988 return (errors);