1*7f26fba0Sjoerg /* $NetBSD: psrset.c,v 1.3 2011/08/31 13:32:39 joerg Exp $ */
244eb18fdSad
344eb18fdSad /*-
444eb18fdSad * Copyright (c) 2008 The NetBSD Foundation, Inc.
544eb18fdSad * All rights reserved.
644eb18fdSad *
744eb18fdSad * Redistribution and use in source and binary forms, with or without
844eb18fdSad * modification, are permitted provided that the following conditions
944eb18fdSad * are met:
1044eb18fdSad * 1. Redistributions of source code must retain the above copyright
1144eb18fdSad * notice, this list of conditions and the following disclaimer.
1244eb18fdSad * 2. Redistributions in binary form must reproduce the above copyright
1344eb18fdSad * notice, this list of conditions and the following disclaimer in the
1444eb18fdSad * documentation and/or other materials provided with the distribution.
1544eb18fdSad *
1644eb18fdSad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1744eb18fdSad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1844eb18fdSad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1944eb18fdSad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2044eb18fdSad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2144eb18fdSad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2244eb18fdSad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2344eb18fdSad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2444eb18fdSad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2544eb18fdSad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2644eb18fdSad * POSSIBILITY OF SUCH DAMAGE.
2744eb18fdSad */
2844eb18fdSad
2944eb18fdSad #include <sys/cdefs.h>
3044eb18fdSad #ifndef lint
31*7f26fba0Sjoerg __RCSID("$NetBSD: psrset.c,v 1.3 2011/08/31 13:32:39 joerg Exp $");
3244eb18fdSad #endif
3344eb18fdSad
3444eb18fdSad #include <sys/types.h>
3544eb18fdSad #include <sys/pset.h>
3644eb18fdSad #include <sys/sched.h>
3744eb18fdSad #include <sys/sysctl.h>
3844eb18fdSad
3944eb18fdSad #include <stdio.h>
4044eb18fdSad #include <stdlib.h>
4144eb18fdSad #include <string.h>
4244eb18fdSad #include <fcntl.h>
4344eb18fdSad #include <err.h>
4444eb18fdSad #include <unistd.h>
4544eb18fdSad #include <ctype.h>
4644eb18fdSad
47*7f26fba0Sjoerg __dead static void usage(void);
4844eb18fdSad static int eatopt(char **);
4944eb18fdSad static int cmd_a(char **, int);
5044eb18fdSad static int cmd_b(char **, int);
5144eb18fdSad static int cmd_c(char **, int);
5244eb18fdSad static int cmd_d(char **, int);
5344eb18fdSad static int cmd_e(char **, int);
5444eb18fdSad static int cmd_i(char **, int);
5544eb18fdSad static int cmd_p(char **, int);
5644eb18fdSad static int cmd_r(char **, int);
5744eb18fdSad static int cmd_u(char **, int);
5844eb18fdSad static int cmd__(char **, int);
5944eb18fdSad
6044eb18fdSad static psetid_t psid;
6144eb18fdSad static int ncpu;
6244eb18fdSad static cpuset_t *cpuset;
6344eb18fdSad
6444eb18fdSad int
main(int argc,char ** argv)6544eb18fdSad main(int argc, char **argv)
6644eb18fdSad {
6744eb18fdSad int (*cmd)(char **, int);
6844eb18fdSad int off;
6944eb18fdSad
7044eb18fdSad ncpu = sysconf(_SC_NPROCESSORS_CONF);
7144eb18fdSad cpuset = cpuset_create();
7244eb18fdSad if (cpuset == NULL)
7344eb18fdSad err(EXIT_FAILURE, "cpuset_create");
7444eb18fdSad cpuset_zero(cpuset);
7544eb18fdSad
7644eb18fdSad if (argc == 1 || argv[1][0] != '-') {
7744eb18fdSad cmd = cmd_i;
7844eb18fdSad off = 1;
7944eb18fdSad } else if (strncmp(argv[1], "-a", 2) == 0) {
8044eb18fdSad cmd = cmd_a;
8144eb18fdSad off = eatopt(argv);
8244eb18fdSad } else if (strncmp(argv[1], "-b", 2) == 0) {
8344eb18fdSad cmd = cmd_b;
8444eb18fdSad off = eatopt(argv);
8544eb18fdSad } else if (strncmp(argv[1], "-c", 2) == 0) {
8644eb18fdSad cmd = cmd_c;
8744eb18fdSad off = eatopt(argv);
8844eb18fdSad } else if (strncmp(argv[1], "-d", 2) == 0) {
8944eb18fdSad cmd = cmd_d;
9044eb18fdSad off = eatopt(argv);
9144eb18fdSad } else if (strncmp(argv[1], "-e", 2) == 0) {
9244eb18fdSad cmd = cmd_e;
9344eb18fdSad off = eatopt(argv);
9444eb18fdSad } else if (strncmp(argv[1], "-i", 2) == 0) {
9544eb18fdSad cmd = cmd_i;
9644eb18fdSad off = eatopt(argv);
9744eb18fdSad } else if (strncmp(argv[1], "-p", 2) == 0) {
9844eb18fdSad cmd = cmd_p;
9944eb18fdSad off = eatopt(argv);
10044eb18fdSad } else if (strncmp(argv[1], "-r", 2) == 0) {
10144eb18fdSad cmd = cmd_r;
10244eb18fdSad off = eatopt(argv);
10344eb18fdSad } else if (strncmp(argv[1], "-u", 2) == 0) {
10444eb18fdSad cmd = cmd_u;
10544eb18fdSad off = eatopt(argv);
10644eb18fdSad } else {
10744eb18fdSad cmd = cmd__;
10844eb18fdSad off = 0;
10944eb18fdSad }
11044eb18fdSad
11144eb18fdSad return (*cmd)(argv + off, argc - off);
11244eb18fdSad }
11344eb18fdSad
11444eb18fdSad static int
eatopt(char ** argv)11544eb18fdSad eatopt(char **argv)
11644eb18fdSad {
11744eb18fdSad
11844eb18fdSad if (argv[1][2] != '\0') {
11944eb18fdSad argv[1] += 2;
12044eb18fdSad return 1;
12144eb18fdSad }
12244eb18fdSad return 2;
12344eb18fdSad }
12444eb18fdSad
12544eb18fdSad static int
getint(char * p)12644eb18fdSad getint(char *p)
12744eb18fdSad {
12844eb18fdSad char *q;
12944eb18fdSad int rv;
13044eb18fdSad
13144eb18fdSad rv = (int)strtol(p, &q, 10);
13244eb18fdSad if (q == p || *q != '\0')
13344eb18fdSad usage();
13444eb18fdSad return rv;
13544eb18fdSad }
13644eb18fdSad
13744eb18fdSad static void
usage(void)13844eb18fdSad usage(void)
13944eb18fdSad {
14044eb18fdSad
14144eb18fdSad fprintf(stderr, "usage:\n"
14244eb18fdSad "\tpsrset [setid ...]\n"
14344eb18fdSad "\tpsrset -a setid cpuid ...\n"
14444eb18fdSad "\tpsrset -b setid pid ...\n"
14544eb18fdSad "\tpsrset -c [cpuid ...]\n"
14644eb18fdSad "\tpsrset -d setid\n"
14744eb18fdSad "\tpsrset -e setid command\n"
14844eb18fdSad "\tpsrset -i [setid ...]\n"
14944eb18fdSad "\tpsrset -p\n"
15044eb18fdSad "\tpsrset -r cpuid ...\n"
15144eb18fdSad "\tpsrset -u pid ...\n");
15244eb18fdSad
15344eb18fdSad exit(EXIT_FAILURE);
15444eb18fdSad }
15544eb18fdSad
15644eb18fdSad static void
makecpuset(char ** argv)15744eb18fdSad makecpuset(char **argv)
15844eb18fdSad {
15944eb18fdSad char *p, *q;
16044eb18fdSad int i, j;
16144eb18fdSad
16244eb18fdSad if (*argv == NULL) {
16344eb18fdSad for (i = 0; i < ncpu; i++)
16444eb18fdSad cpuset_set(i, cpuset);
16544eb18fdSad return;
16644eb18fdSad }
16744eb18fdSad
16844eb18fdSad for (; *argv != NULL; argv++) {
16944eb18fdSad if (!isdigit((unsigned)**argv))
17044eb18fdSad usage();
17144eb18fdSad i = (int)strtol(*argv, &p, 10);
17244eb18fdSad if ((*p != '\0' && *p != '-') || p == *argv)
17344eb18fdSad usage();
17444eb18fdSad if (*p == '-') {
17544eb18fdSad if (!isdigit((unsigned)p[1]))
17644eb18fdSad usage();
17744eb18fdSad j = (int)strtol(p + 1, &q, 10);
17844eb18fdSad if (q == p || *q != '\0')
17944eb18fdSad usage();
18044eb18fdSad } else {
18144eb18fdSad j = i;
18244eb18fdSad }
18329f2e1ceSlukem if (i >= ncpu) {
18444eb18fdSad errx(EXIT_FAILURE, "value out of range");
18544eb18fdSad }
18644eb18fdSad while (i <= j)
18744eb18fdSad cpuset_set(i++, cpuset);
18844eb18fdSad }
18944eb18fdSad }
19044eb18fdSad
19144eb18fdSad /*
19244eb18fdSad * Assign processors to set.
19344eb18fdSad */
19444eb18fdSad static int
cmd_a(char ** argv,int argc)19544eb18fdSad cmd_a(char **argv, int argc)
19644eb18fdSad {
19744eb18fdSad int i;
19844eb18fdSad
19944eb18fdSad if (argc < 2)
20044eb18fdSad usage();
20144eb18fdSad psid = getint(argv[0]);
20244eb18fdSad makecpuset(argv + 1);
20344eb18fdSad for (i = 0; i < ncpu; i++) {
20444eb18fdSad if (!cpuset_isset(i, cpuset))
20544eb18fdSad continue;
20644eb18fdSad if (pset_assign(psid, i, NULL))
20744eb18fdSad err(EXIT_FAILURE, "pset_assign");
20844eb18fdSad }
20944eb18fdSad
21044eb18fdSad return 0;
21144eb18fdSad }
21244eb18fdSad
21344eb18fdSad /*
21444eb18fdSad * Bind LWPs within processes to set.
21544eb18fdSad */
21644eb18fdSad static int
cmd_b(char ** argv,int argc)21744eb18fdSad cmd_b(char **argv, int argc)
21844eb18fdSad {
21944eb18fdSad
22044eb18fdSad if (argc < 2)
22144eb18fdSad usage();
22244eb18fdSad psid = getint(*argv);
22344eb18fdSad for (argv++; *argv != NULL; argv++) {
22444eb18fdSad if (pset_bind(psid, P_PID, (idtype_t)getint(*argv), NULL))
22544eb18fdSad err(EXIT_FAILURE, "pset_bind");
22644eb18fdSad }
22744eb18fdSad
22844eb18fdSad return 0;
22944eb18fdSad }
23044eb18fdSad
23144eb18fdSad /*
23244eb18fdSad * Create set.
23344eb18fdSad */
23444eb18fdSad static int
cmd_c(char ** argv,int argc)23544eb18fdSad cmd_c(char **argv, int argc)
23644eb18fdSad {
23744eb18fdSad int i;
23844eb18fdSad
23944eb18fdSad if (pset_create(&psid))
24044eb18fdSad err(EXIT_FAILURE, "pset_create");
24144eb18fdSad printf("%d\n", (int)psid);
24244eb18fdSad if (argc != 0)
24344eb18fdSad makecpuset(argv);
24444eb18fdSad for (i = 0; i < ncpu; i++) {
24544eb18fdSad if (!cpuset_isset(i, cpuset))
24644eb18fdSad continue;
24744eb18fdSad if (pset_assign(psid, i, NULL))
24844eb18fdSad err(EXIT_FAILURE, "pset_assign");
24944eb18fdSad }
25044eb18fdSad
25144eb18fdSad return 0;
25244eb18fdSad }
25344eb18fdSad
25444eb18fdSad /*
25544eb18fdSad * Destroy set.
25644eb18fdSad */
25744eb18fdSad static int
cmd_d(char ** argv,int argc)25844eb18fdSad cmd_d(char **argv, int argc)
25944eb18fdSad {
26044eb18fdSad
26144eb18fdSad if (argc != 1)
26244eb18fdSad usage();
26344eb18fdSad if (pset_destroy(getint(argv[0])))
26444eb18fdSad err(EXIT_FAILURE, "pset_destroy");
26544eb18fdSad
26644eb18fdSad return 0;
26744eb18fdSad }
26844eb18fdSad
26944eb18fdSad /*
27044eb18fdSad * Execute command in set.
27144eb18fdSad */
27244eb18fdSad static int
cmd_e(char ** argv,int argc)27344eb18fdSad cmd_e(char **argv, int argc)
27444eb18fdSad {
27544eb18fdSad
27644eb18fdSad if (argc < 2)
27744eb18fdSad usage();
27844eb18fdSad if (pset_bind(getint(argv[0]), P_PID, getpid(), NULL))
27944eb18fdSad err(EXIT_FAILURE, "pset_bind");
28044eb18fdSad (void)execvp(argv[1], argv + 1);
28144eb18fdSad return 1;
28244eb18fdSad }
28344eb18fdSad
28444eb18fdSad /*
28544eb18fdSad * Print info about each set.
28644eb18fdSad */
28744eb18fdSad static int
cmd_i(char ** argv,int argc)28844eb18fdSad cmd_i(char **argv, int argc)
28944eb18fdSad {
29044eb18fdSad char buf[1024];
29144eb18fdSad size_t len;
29244eb18fdSad char *p, *q;
29344eb18fdSad int i, j, k;
29444eb18fdSad
29544eb18fdSad len = sizeof(buf);
29644eb18fdSad if (sysctlbyname("kern.pset.list", buf, &len, NULL, 0) == -1)
29744eb18fdSad err(EXIT_FAILURE, "kern.pset.list");
29844eb18fdSad
29944eb18fdSad p = buf;
30044eb18fdSad while ((q = strsep(&p, ",")) != NULL) {
30144eb18fdSad i = (int)strtol(q, &q, 10);
30244eb18fdSad if (*q != ':')
30344eb18fdSad errx(EXIT_FAILURE, "bad kern.pset.list");
30444eb18fdSad printf("%s processor set %d: ",
30544eb18fdSad (atoi(q + 1) == 1 ? "system" : "user"), i);
30644eb18fdSad for (j = 0, k = 0; j < ncpu; j++) {
30744eb18fdSad if (pset_assign(PS_QUERY, j, &psid))
30844eb18fdSad err(EXIT_FAILURE, "pset_assign");
30944eb18fdSad if (psid == i) {
31044eb18fdSad if (k++ == 0)
31144eb18fdSad printf("processor(s)");
31244eb18fdSad printf(" %d", j);
31344eb18fdSad }
31444eb18fdSad }
31544eb18fdSad if (k == 0)
31644eb18fdSad printf("empty");
31744eb18fdSad putchar('\n');
31844eb18fdSad }
31944eb18fdSad
32044eb18fdSad return 0;
32144eb18fdSad }
32244eb18fdSad
32344eb18fdSad /*
32444eb18fdSad * Print set ID for each processor.
32544eb18fdSad */
32644eb18fdSad static int
cmd_p(char ** argv,int argc)32744eb18fdSad cmd_p(char **argv, int argc)
32844eb18fdSad {
32944eb18fdSad int i;
33044eb18fdSad
33144eb18fdSad makecpuset(argv);
33244eb18fdSad
33344eb18fdSad for (i = 0; i < ncpu; i++) {
33444eb18fdSad if (!cpuset_isset(i, cpuset))
33544eb18fdSad continue;
33644eb18fdSad if (pset_assign(PS_QUERY, i, &psid))
33744eb18fdSad err(EXIT_FAILURE, "ioctl");
33844eb18fdSad printf("processor %d: ", i);
33944eb18fdSad if (psid == PS_NONE)
34044eb18fdSad printf("not assigned\n");
34144eb18fdSad else
34244eb18fdSad printf("%d\n", (int)psid);
34344eb18fdSad }
34444eb18fdSad
34544eb18fdSad return 0;
34644eb18fdSad }
34744eb18fdSad
34844eb18fdSad /*
34944eb18fdSad * Remove CPU from set and return to system.
35044eb18fdSad */
35144eb18fdSad static int
cmd_r(char ** argv,int argc)35244eb18fdSad cmd_r(char **argv, int argc)
35344eb18fdSad {
35444eb18fdSad int i;
35544eb18fdSad
35644eb18fdSad makecpuset(argv);
35744eb18fdSad
35844eb18fdSad for (i = 0; i < ncpu; i++) {
35944eb18fdSad if (!cpuset_isset(i, cpuset))
36044eb18fdSad continue;
36144eb18fdSad if (pset_assign(PS_NONE, i, NULL))
36244eb18fdSad err(EXIT_FAILURE, "ioctl");
36344eb18fdSad }
36444eb18fdSad
36544eb18fdSad return 0;
36644eb18fdSad }
36744eb18fdSad
36844eb18fdSad /*
36944eb18fdSad * Unbind LWPs within process.
37044eb18fdSad */
37144eb18fdSad static int
cmd_u(char ** argv,int argc)37244eb18fdSad cmd_u(char **argv, int argc)
37344eb18fdSad {
37444eb18fdSad
37544eb18fdSad if (argc < 1)
37644eb18fdSad usage();
37744eb18fdSad for (; *argv != NULL; argv++) {
37844eb18fdSad if (pset_bind(PS_NONE, P_PID, (idtype_t)getint(*argv), NULL))
37944eb18fdSad err(EXIT_FAILURE, "pset_bind");
38044eb18fdSad }
38144eb18fdSad
38244eb18fdSad return 0;
38344eb18fdSad }
38444eb18fdSad
38544eb18fdSad
38644eb18fdSad /*
38744eb18fdSad * Dummy.
38844eb18fdSad */
38944eb18fdSad static int
cmd__(char ** argv,int argc)39044eb18fdSad cmd__(char **argv, int argc)
39144eb18fdSad {
39244eb18fdSad
39344eb18fdSad usage();
39444eb18fdSad return 0;
39544eb18fdSad }
396