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 | ||
