diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2014-08-17 19:36:22 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2014-08-17 19:36:22 +0200 |
commit | 962c4e822012a6d4c83b869eb47506881b4abc57 (patch) | |
tree | 6f23eaa2b896bcb65d081014682b564ffc0dd6fe /miscutils | |
parent | fb8d1ef2d00db013eae3cc675fc8b34fd0a7a987 (diff) | |
download | busybox-w32-962c4e822012a6d4c83b869eb47506881b4abc57.tar.gz busybox-w32-962c4e822012a6d4c83b869eb47506881b4abc57.tar.bz2 busybox-w32-962c4e822012a6d4c83b869eb47506881b4abc57.zip |
taskset: support CPU masks for more than 64 CPUs
function old new delta
taskset_main 522 631 +109
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils')
-rw-r--r-- | miscutils/Config.src | 16 | ||||
-rw-r--r-- | miscutils/Kbuild.src | 1 | ||||
-rw-r--r-- | miscutils/taskset.c | 86 |
3 files changed, 79 insertions, 24 deletions
diff --git a/miscutils/Config.src b/miscutils/Config.src index 1b2a3ae9a..d69abf1a2 100644 --- a/miscutils/Config.src +++ b/miscutils/Config.src | |||
@@ -499,22 +499,6 @@ config STRINGS | |||
499 | strings prints the printable character sequences for each file | 499 | strings prints the printable character sequences for each file |
500 | specified. | 500 | specified. |
501 | 501 | ||
502 | config TASKSET | ||
503 | bool "taskset" | ||
504 | default n # doesn't build on some non-x86 targets (m68k) | ||
505 | help | ||
506 | Retrieve or set a processes's CPU affinity. | ||
507 | This requires sched_{g,s}etaffinity support in your libc. | ||
508 | |||
509 | config FEATURE_TASKSET_FANCY | ||
510 | bool "Fancy output" | ||
511 | default y | ||
512 | depends on TASKSET | ||
513 | help | ||
514 | Add code for fancy output. This merely silences a compiler-warning | ||
515 | and adds about 135 Bytes. May be needed for machines with alot | ||
516 | of CPUs. | ||
517 | |||
518 | config TIME | 502 | config TIME |
519 | bool "time" | 503 | bool "time" |
520 | default y | 504 | default y |
diff --git a/miscutils/Kbuild.src b/miscutils/Kbuild.src index 8eaa82de9..7b449e6e8 100644 --- a/miscutils/Kbuild.src +++ b/miscutils/Kbuild.src | |||
@@ -39,7 +39,6 @@ lib-$(CONFIG_RUNLEVEL) += runlevel.o | |||
39 | lib-$(CONFIG_RX) += rx.o | 39 | lib-$(CONFIG_RX) += rx.o |
40 | lib-$(CONFIG_SETSID) += setsid.o | 40 | lib-$(CONFIG_SETSID) += setsid.o |
41 | lib-$(CONFIG_STRINGS) += strings.o | 41 | lib-$(CONFIG_STRINGS) += strings.o |
42 | lib-$(CONFIG_TASKSET) += taskset.o | ||
43 | lib-$(CONFIG_TIME) += time.o | 42 | lib-$(CONFIG_TIME) += time.o |
44 | lib-$(CONFIG_TIMEOUT) += timeout.o | 43 | lib-$(CONFIG_TIMEOUT) += timeout.o |
45 | lib-$(CONFIG_TTYSIZE) += ttysize.o | 44 | lib-$(CONFIG_TTYSIZE) += ttysize.o |
diff --git a/miscutils/taskset.c b/miscutils/taskset.c index 4a9e3230d..8bd32ed61 100644 --- a/miscutils/taskset.c +++ b/miscutils/taskset.c | |||
@@ -6,6 +6,25 @@ | |||
6 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 6 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | //config:config TASKSET | ||
10 | //config: bool "taskset" | ||
11 | //config: default n # doesn't build on some non-x86 targets (m68k) | ||
12 | //config: help | ||
13 | //config: Retrieve or set a processes's CPU affinity. | ||
14 | //config: This requires sched_{g,s}etaffinity support in your libc. | ||
15 | //config: | ||
16 | //config:config FEATURE_TASKSET_FANCY | ||
17 | //config: bool "Fancy output" | ||
18 | //config: default y | ||
19 | //config: depends on TASKSET | ||
20 | //config: help | ||
21 | //config: Add code for fancy output. This merely silences a compiler-warning | ||
22 | //config: and adds about 135 Bytes. May be needed for machines with alot | ||
23 | //config: of CPUs. | ||
24 | |||
25 | //applet:IF_TASKSET(APPLET(taskset, BB_DIR_USR_BIN, BB_SUID_DROP)) | ||
26 | //kbuild:lib-$(CONFIG_TASKSET) += taskset.o | ||
27 | |||
9 | //usage:#define taskset_trivial_usage | 28 | //usage:#define taskset_trivial_usage |
10 | //usage: "[-p] [MASK] [PID | PROG ARGS]" | 29 | //usage: "[-p] [MASK] [PID | PROG ARGS]" |
11 | //usage:#define taskset_full_usage "\n\n" | 30 | //usage:#define taskset_full_usage "\n\n" |
@@ -22,6 +41,11 @@ | |||
22 | //usage: "pid 6671's new affinity mask: 1\n" | 41 | //usage: "pid 6671's new affinity mask: 1\n" |
23 | //usage: "$ taskset -p 1\n" | 42 | //usage: "$ taskset -p 1\n" |
24 | //usage: "pid 1's current affinity mask: 3\n" | 43 | //usage: "pid 1's current affinity mask: 3\n" |
44 | /* | ||
45 | Not yet implemented: | ||
46 | * -a/--all-tasks (affect all threads) | ||
47 | * -c/--cpu-list (specify CPUs via "1,3,5-7") | ||
48 | */ | ||
25 | 49 | ||
26 | #include <sched.h> | 50 | #include <sched.h> |
27 | #include "libbb.h" | 51 | #include "libbb.h" |
@@ -128,17 +152,65 @@ int taskset_main(int argc UNUSED_PARAM, char **argv) | |||
128 | current_new += 8; /* "new" */ | 152 | current_new += 8; /* "new" */ |
129 | } | 153 | } |
130 | 154 | ||
131 | { /* Affinity was specified, translate it into cpu_set_t */ | 155 | /* Affinity was specified, translate it into cpu_set_t */ |
156 | CPU_ZERO(&mask); | ||
157 | if (!ENABLE_FEATURE_TASKSET_FANCY) { | ||
132 | unsigned i; | 158 | unsigned i; |
159 | unsigned long long m; | ||
160 | |||
133 | /* Do not allow zero mask: */ | 161 | /* Do not allow zero mask: */ |
134 | unsigned long long m = xstrtoull_range(aff, 0, 1, ULLONG_MAX); | 162 | m = xstrtoull_range(aff, 0, 1, ULLONG_MAX); |
135 | enum { CNT_BIT = CPU_SETSIZE < sizeof(m)*8 ? CPU_SETSIZE : sizeof(m)*8 }; | 163 | i = 0; |
164 | do { | ||
165 | if (m & 1) | ||
166 | CPU_SET(i, &mask); | ||
167 | i++; | ||
168 | m >>= 1; | ||
169 | } while (m != 0); | ||
170 | } else { | ||
171 | unsigned i; | ||
172 | char *last_byte; | ||
173 | char *bin; | ||
174 | uint8_t bit_in_byte; | ||
175 | |||
176 | /* Cheap way to get "long enough" buffer */ | ||
177 | bin = xstrdup(aff); | ||
178 | |||
179 | if (aff[0] != '0' && (aff[1]|0x20) != 'x') { | ||
180 | /* TODO: decimal/octal masks are still limited to 2^64 */ | ||
181 | unsigned long long m = xstrtoull_range(aff, 0, 1, ULLONG_MAX); | ||
182 | bin += strlen(bin); | ||
183 | last_byte = bin - 1; | ||
184 | while (m) { | ||
185 | *--bin = m & 0xff; | ||
186 | m >>= 8; | ||
187 | } | ||
188 | } else { | ||
189 | /* aff is "0x.....", we accept very long masks in this form */ | ||
190 | last_byte = hex2bin(bin, aff + 2, INT_MAX); | ||
191 | if (!last_byte) { | ||
192 | bad_aff: | ||
193 | bb_error_msg_and_die("bad affinity '%s'", aff); | ||
194 | } | ||
195 | last_byte--; /* now points to the last byte */ | ||
196 | } | ||
136 | 197 | ||
137 | CPU_ZERO(&mask); | 198 | i = 0; |
138 | for (i = 0; i < CNT_BIT; i++) { | 199 | bit_in_byte = 1; |
139 | unsigned long long bit = (1ULL << i); | 200 | while (last_byte >= bin) { |
140 | if (bit & m) | 201 | if (bit_in_byte & *last_byte) { |
202 | if (i >= CPU_SETSIZE) | ||
203 | goto bad_aff; | ||
141 | CPU_SET(i, &mask); | 204 | CPU_SET(i, &mask); |
205 | //bb_error_msg("bit %d set", i); | ||
206 | } | ||
207 | i++; | ||
208 | /* bit_in_byte is uint8_t! & 0xff is implied */ | ||
209 | bit_in_byte = (bit_in_byte << 1); | ||
210 | if (!bit_in_byte) { | ||
211 | bit_in_byte = 1; | ||
212 | last_byte--; | ||
213 | } | ||
142 | } | 214 | } |
143 | } | 215 | } |
144 | 216 | ||