xref: /netbsd/usr.sbin/psrset/psrset.c (revision 7f26fba0)
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