1*cf5a6c84SAndroid Build Coastguard Worker /* taskset.c - Retrieve or set the CPU affinity of a process.
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2012 Elie De Brauwer <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker
5*cf5a6c84SAndroid Build Coastguard Worker USE_TASKSET(NEWTOY(taskset, "<1^pa", TOYFLAG_USR|TOYFLAG_BIN))
6*cf5a6c84SAndroid Build Coastguard Worker USE_NPROC(NEWTOY(nproc, "(all)", TOYFLAG_USR|TOYFLAG_BIN))
7*cf5a6c84SAndroid Build Coastguard Worker
8*cf5a6c84SAndroid Build Coastguard Worker config NPROC
9*cf5a6c84SAndroid Build Coastguard Worker bool "nproc"
10*cf5a6c84SAndroid Build Coastguard Worker default y
11*cf5a6c84SAndroid Build Coastguard Worker help
12*cf5a6c84SAndroid Build Coastguard Worker usage: nproc [--all]
13*cf5a6c84SAndroid Build Coastguard Worker
14*cf5a6c84SAndroid Build Coastguard Worker Print number of processors.
15*cf5a6c84SAndroid Build Coastguard Worker
16*cf5a6c84SAndroid Build Coastguard Worker --all Show all processors, not just ones this task can run on
17*cf5a6c84SAndroid Build Coastguard Worker
18*cf5a6c84SAndroid Build Coastguard Worker config TASKSET
19*cf5a6c84SAndroid Build Coastguard Worker bool "taskset"
20*cf5a6c84SAndroid Build Coastguard Worker default y
21*cf5a6c84SAndroid Build Coastguard Worker help
22*cf5a6c84SAndroid Build Coastguard Worker usage: taskset [-ap] [mask] [PID | cmd [args...]]
23*cf5a6c84SAndroid Build Coastguard Worker
24*cf5a6c84SAndroid Build Coastguard Worker Launch a new task which may only run on certain processors, or change
25*cf5a6c84SAndroid Build Coastguard Worker the processor affinity of an existing PID.
26*cf5a6c84SAndroid Build Coastguard Worker
27*cf5a6c84SAndroid Build Coastguard Worker Mask is a hex string where each bit represents a processor the process
28*cf5a6c84SAndroid Build Coastguard Worker is allowed to run on. PID without a mask displays existing affinity.
29*cf5a6c84SAndroid Build Coastguard Worker
30*cf5a6c84SAndroid Build Coastguard Worker -p Set/get the affinity of given PID instead of a new command
31*cf5a6c84SAndroid Build Coastguard Worker -a Set/get the affinity of all threads of the PID
32*cf5a6c84SAndroid Build Coastguard Worker */
33*cf5a6c84SAndroid Build Coastguard Worker
34*cf5a6c84SAndroid Build Coastguard Worker #define FOR_taskset
35*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
36*cf5a6c84SAndroid Build Coastguard Worker
37*cf5a6c84SAndroid Build Coastguard Worker // mask is array of long which makes layout a bit weird on big endian systems
38*cf5a6c84SAndroid Build Coastguard Worker #define sched_setaffinity(pid, size, cpuset) \
39*cf5a6c84SAndroid Build Coastguard Worker syscall(__NR_sched_setaffinity, (pid_t)pid, (size_t)size, (void *)cpuset)
40*cf5a6c84SAndroid Build Coastguard Worker #define sched_getaffinity(pid, size, cpuset) \
41*cf5a6c84SAndroid Build Coastguard Worker syscall(__NR_sched_getaffinity, (pid_t)pid, (size_t)size, (void *)cpuset)
42*cf5a6c84SAndroid Build Coastguard Worker
do_taskset(pid_t pid,int quiet)43*cf5a6c84SAndroid Build Coastguard Worker static void do_taskset(pid_t pid, int quiet)
44*cf5a6c84SAndroid Build Coastguard Worker {
45*cf5a6c84SAndroid Build Coastguard Worker unsigned long *mask = (unsigned long *)toybuf;
46*cf5a6c84SAndroid Build Coastguard Worker char *s, *failed = "failed to %s pid %d's affinity";
47*cf5a6c84SAndroid Build Coastguard Worker int i, j, k;
48*cf5a6c84SAndroid Build Coastguard Worker
49*cf5a6c84SAndroid Build Coastguard Worker // loop through twice to display before/after affinity masks
50*cf5a6c84SAndroid Build Coastguard Worker for (i=0; ; i++) {
51*cf5a6c84SAndroid Build Coastguard Worker if (!quiet) {
52*cf5a6c84SAndroid Build Coastguard Worker if (-1 == sched_getaffinity(pid, sizeof(toybuf), (void *)mask))
53*cf5a6c84SAndroid Build Coastguard Worker perror_exit(failed, "get", pid);
54*cf5a6c84SAndroid Build Coastguard Worker
55*cf5a6c84SAndroid Build Coastguard Worker printf("pid %d's %s affinity mask: ", pid, i ? "new" : "current");
56*cf5a6c84SAndroid Build Coastguard Worker
57*cf5a6c84SAndroid Build Coastguard Worker for (j = sizeof(toybuf)/sizeof(long), k = 0; --j>=0;) {
58*cf5a6c84SAndroid Build Coastguard Worker if (k) printf("%0*lx", (int)(2*sizeof(long)), mask[j]);
59*cf5a6c84SAndroid Build Coastguard Worker else if (mask[j]) {
60*cf5a6c84SAndroid Build Coastguard Worker k++;
61*cf5a6c84SAndroid Build Coastguard Worker printf("%lx", mask[j]);
62*cf5a6c84SAndroid Build Coastguard Worker }
63*cf5a6c84SAndroid Build Coastguard Worker }
64*cf5a6c84SAndroid Build Coastguard Worker putchar('\n');
65*cf5a6c84SAndroid Build Coastguard Worker }
66*cf5a6c84SAndroid Build Coastguard Worker
67*cf5a6c84SAndroid Build Coastguard Worker if (i || toys.optc < 2) return;
68*cf5a6c84SAndroid Build Coastguard Worker
69*cf5a6c84SAndroid Build Coastguard Worker // Convert hex strong to mask[] bits
70*cf5a6c84SAndroid Build Coastguard Worker memset(toybuf, 0, sizeof(toybuf));
71*cf5a6c84SAndroid Build Coastguard Worker k = strlen(s = *toys.optargs);
72*cf5a6c84SAndroid Build Coastguard Worker s += k;
73*cf5a6c84SAndroid Build Coastguard Worker for (j = 0; j<k; j++) {
74*cf5a6c84SAndroid Build Coastguard Worker unsigned long digit = *(--s) - '0';
75*cf5a6c84SAndroid Build Coastguard Worker
76*cf5a6c84SAndroid Build Coastguard Worker if (digit > 9) digit = 10 + tolower(*s)-'a';
77*cf5a6c84SAndroid Build Coastguard Worker if (digit > 15) error_exit("bad mask '%s'", *toys.optargs);
78*cf5a6c84SAndroid Build Coastguard Worker mask[j/(2*sizeof(long))] |= digit << 4*(j&((2*sizeof(long))-1));
79*cf5a6c84SAndroid Build Coastguard Worker }
80*cf5a6c84SAndroid Build Coastguard Worker
81*cf5a6c84SAndroid Build Coastguard Worker if (-1 == sched_setaffinity(pid, sizeof(toybuf), (void *)mask))
82*cf5a6c84SAndroid Build Coastguard Worker perror_exit(failed, "set", pid);
83*cf5a6c84SAndroid Build Coastguard Worker }
84*cf5a6c84SAndroid Build Coastguard Worker }
85*cf5a6c84SAndroid Build Coastguard Worker
task_callback(struct dirtree * new)86*cf5a6c84SAndroid Build Coastguard Worker static int task_callback(struct dirtree *new)
87*cf5a6c84SAndroid Build Coastguard Worker {
88*cf5a6c84SAndroid Build Coastguard Worker if (!new->parent) return DIRTREE_RECURSE|DIRTREE_SHUTUP|DIRTREE_PROC;
89*cf5a6c84SAndroid Build Coastguard Worker do_taskset(atoi(new->name), 0);
90*cf5a6c84SAndroid Build Coastguard Worker
91*cf5a6c84SAndroid Build Coastguard Worker return 0;
92*cf5a6c84SAndroid Build Coastguard Worker }
93*cf5a6c84SAndroid Build Coastguard Worker
taskset_main(void)94*cf5a6c84SAndroid Build Coastguard Worker void taskset_main(void)
95*cf5a6c84SAndroid Build Coastguard Worker {
96*cf5a6c84SAndroid Build Coastguard Worker if (!FLAG(p)) {
97*cf5a6c84SAndroid Build Coastguard Worker if (toys.optc < 2) error_exit("Needs 2 args");
98*cf5a6c84SAndroid Build Coastguard Worker do_taskset(getpid(), 1);
99*cf5a6c84SAndroid Build Coastguard Worker xexec(toys.optargs+1);
100*cf5a6c84SAndroid Build Coastguard Worker } else {
101*cf5a6c84SAndroid Build Coastguard Worker char *c, buf[33];
102*cf5a6c84SAndroid Build Coastguard Worker pid_t pid = strtol(toys.optargs[toys.optc-1], &c, 10);
103*cf5a6c84SAndroid Build Coastguard Worker
104*cf5a6c84SAndroid Build Coastguard Worker if (*c) error_exit("Not int %s", toys.optargs[toys.optc-1]);
105*cf5a6c84SAndroid Build Coastguard Worker
106*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(a)) {
107*cf5a6c84SAndroid Build Coastguard Worker sprintf(buf, "/proc/%ld/task/", (long)pid);
108*cf5a6c84SAndroid Build Coastguard Worker dirtree_read(buf, task_callback);
109*cf5a6c84SAndroid Build Coastguard Worker } else do_taskset(pid, 0);
110*cf5a6c84SAndroid Build Coastguard Worker }
111*cf5a6c84SAndroid Build Coastguard Worker }
112*cf5a6c84SAndroid Build Coastguard Worker
nproc_main(void)113*cf5a6c84SAndroid Build Coastguard Worker void nproc_main(void)
114*cf5a6c84SAndroid Build Coastguard Worker {
115*cf5a6c84SAndroid Build Coastguard Worker unsigned i, j, nproc = 0;
116*cf5a6c84SAndroid Build Coastguard Worker DIR *dd;
117*cf5a6c84SAndroid Build Coastguard Worker
118*cf5a6c84SAndroid Build Coastguard Worker // This can only detect 32768 processors. Call getaffinity and count bits.
119*cf5a6c84SAndroid Build Coastguard Worker if (!toys.optflags && -1!=sched_getaffinity(getpid(), 4096, toybuf))
120*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i<4096; i++)
121*cf5a6c84SAndroid Build Coastguard Worker if (toybuf[i]) for (j=0; j<8; j++) if (toybuf[i]&(1<<j)) nproc++;
122*cf5a6c84SAndroid Build Coastguard Worker
123*cf5a6c84SAndroid Build Coastguard Worker // If getaffinity failed or --all, count cpu entries in sysfs
124*cf5a6c84SAndroid Build Coastguard Worker // (/proc/cpuinfo filters out hot-unplugged CPUs, sysfs doesn't)
125*cf5a6c84SAndroid Build Coastguard Worker if (!nproc && (dd = opendir("/sys/devices/system/cpu"))) {
126*cf5a6c84SAndroid Build Coastguard Worker struct dirent *de;
127*cf5a6c84SAndroid Build Coastguard Worker char *ss;
128*cf5a6c84SAndroid Build Coastguard Worker
129*cf5a6c84SAndroid Build Coastguard Worker while ((de = readdir(dd))) {
130*cf5a6c84SAndroid Build Coastguard Worker if (smemcmp(de->d_name, "cpu", 3)) continue;
131*cf5a6c84SAndroid Build Coastguard Worker for (ss = de->d_name+3; isdigit(*ss); ss++);
132*cf5a6c84SAndroid Build Coastguard Worker if (!*ss) nproc++;
133*cf5a6c84SAndroid Build Coastguard Worker }
134*cf5a6c84SAndroid Build Coastguard Worker closedir(dd);
135*cf5a6c84SAndroid Build Coastguard Worker }
136*cf5a6c84SAndroid Build Coastguard Worker
137*cf5a6c84SAndroid Build Coastguard Worker xprintf("%u\n", nproc ? : 1);
138*cf5a6c84SAndroid Build Coastguard Worker }
139