diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-04-12 13:58:40 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-04-12 13:58:40 +0200 |
commit | 783d57af7bb2b851c16cf87df848e0365e5052da (patch) | |
tree | 71bb23e51b9cb40eac4a6fb831383134c1fc45a0 /miscutils/taskset.c | |
parent | ac47a00e2ec398b04c3141cd3434a6e4b95740b1 (diff) | |
download | busybox-w32-783d57af7bb2b851c16cf87df848e0365e5052da.tar.gz busybox-w32-783d57af7bb2b851c16cf87df848e0365e5052da.tar.bz2 busybox-w32-783d57af7bb2b851c16cf87df848e0365e5052da.zip |
Sort some miscutils/ applets into coreutils or util-linux
No code changes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils/taskset.c')
-rw-r--r-- | miscutils/taskset.c | 221 |
1 files changed, 0 insertions, 221 deletions
diff --git a/miscutils/taskset.c b/miscutils/taskset.c deleted file mode 100644 index 94a07383a..000000000 --- a/miscutils/taskset.c +++ /dev/null | |||
@@ -1,221 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * taskset - retrieve or set a processes' CPU affinity | ||
4 | * Copyright (c) 2006 Bernhard Reutner-Fischer | ||
5 | * | ||
6 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | ||
7 | */ | ||
8 | |||
9 | //config:config TASKSET | ||
10 | //config: bool "taskset" | ||
11 | //config: default y | ||
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: Needed for machines with more than 32-64 CPUs: | ||
22 | //config: affinity parameter 0xHHHHHHHHHHHHHHHHHHHH can be arbitrarily long | ||
23 | //config: in this case. Otherwise, it is limited to sizeof(long). | ||
24 | |||
25 | //applet:IF_TASKSET(APPLET(taskset, BB_DIR_USR_BIN, BB_SUID_DROP)) | ||
26 | //kbuild:lib-$(CONFIG_TASKSET) += taskset.o | ||
27 | |||
28 | //usage:#define taskset_trivial_usage | ||
29 | //usage: "[-p] [HEXMASK] PID | PROG ARGS" | ||
30 | //usage:#define taskset_full_usage "\n\n" | ||
31 | //usage: "Set or get CPU affinity\n" | ||
32 | //usage: "\n -p Operate on an existing PID" | ||
33 | //usage: | ||
34 | //usage:#define taskset_example_usage | ||
35 | //usage: "$ taskset 0x7 ./dgemm_test&\n" | ||
36 | //usage: "$ taskset -p 0x1 $!\n" | ||
37 | //usage: "pid 4790's current affinity mask: 7\n" | ||
38 | //usage: "pid 4790's new affinity mask: 1\n" | ||
39 | //usage: "$ taskset 0x7 /bin/sh -c './taskset -p 0x1 $$'\n" | ||
40 | //usage: "pid 6671's current affinity mask: 1\n" | ||
41 | //usage: "pid 6671's new affinity mask: 1\n" | ||
42 | //usage: "$ taskset -p 1\n" | ||
43 | //usage: "pid 1's current affinity mask: 3\n" | ||
44 | /* | ||
45 | * Not yet implemented: | ||
46 | * -a/--all-tasks (affect all threads) | ||
47 | * needs to get TIDs from /proc/PID/task/ and use _them_ as "pid" in sched_setaffinity(pid) | ||
48 | * -c/--cpu-list (specify CPUs via "1,3,5-7") | ||
49 | */ | ||
50 | |||
51 | #include <sched.h> | ||
52 | #include "libbb.h" | ||
53 | |||
54 | typedef unsigned long ul; | ||
55 | #define SZOF_UL (unsigned)(sizeof(ul)) | ||
56 | #define BITS_UL (unsigned)(sizeof(ul)*8) | ||
57 | #define MASK_UL (unsigned)(sizeof(ul)*8 - 1) | ||
58 | |||
59 | #if ENABLE_FEATURE_TASKSET_FANCY | ||
60 | #define TASKSET_PRINTF_MASK "%s" | ||
61 | /* craft a string from the mask */ | ||
62 | static char *from_mask(const ul *mask, unsigned sz_in_bytes) | ||
63 | { | ||
64 | char *str = xzalloc((sz_in_bytes+1) * 2); /* we will leak it */ | ||
65 | char *p = str; | ||
66 | for (;;) { | ||
67 | ul v = *mask++; | ||
68 | if (SZOF_UL == 4) | ||
69 | p += sprintf(p, "%08lx", v); | ||
70 | if (SZOF_UL == 8) | ||
71 | p += sprintf(p, "%016lx", v); | ||
72 | if (SZOF_UL == 16) | ||
73 | p += sprintf(p, "%032lx", v); /* :) */ | ||
74 | sz_in_bytes -= SZOF_UL; | ||
75 | if ((int)sz_in_bytes <= 0) | ||
76 | break; | ||
77 | } | ||
78 | while (str[0] == '0' && str[1]) | ||
79 | str++; | ||
80 | return str; | ||
81 | } | ||
82 | #else | ||
83 | #define TASKSET_PRINTF_MASK "%lx" | ||
84 | static unsigned long long from_mask(ul *mask, unsigned sz_in_bytes UNUSED_PARAM) | ||
85 | { | ||
86 | return *mask; | ||
87 | } | ||
88 | #endif | ||
89 | |||
90 | static unsigned long *get_aff(int pid, unsigned *sz) | ||
91 | { | ||
92 | int r; | ||
93 | unsigned long *mask = NULL; | ||
94 | unsigned sz_in_bytes = *sz; | ||
95 | |||
96 | for (;;) { | ||
97 | mask = xrealloc(mask, sz_in_bytes); | ||
98 | r = sched_getaffinity(pid, sz_in_bytes, (void*)mask); | ||
99 | if (r == 0) | ||
100 | break; | ||
101 | sz_in_bytes *= 2; | ||
102 | if (errno == EINVAL && (int)sz_in_bytes > 0) | ||
103 | continue; | ||
104 | bb_perror_msg_and_die("can't %cet pid %d's affinity", 'g', pid); | ||
105 | } | ||
106 | //bb_error_msg("get mask[0]:%lx sz_in_bytes:%d", mask[0], sz_in_bytes); | ||
107 | *sz = sz_in_bytes; | ||
108 | return mask; | ||
109 | } | ||
110 | |||
111 | int taskset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
112 | int taskset_main(int argc UNUSED_PARAM, char **argv) | ||
113 | { | ||
114 | ul *mask; | ||
115 | unsigned mask_size_in_bytes; | ||
116 | pid_t pid = 0; | ||
117 | unsigned opt_p; | ||
118 | const char *current_new; | ||
119 | char *aff; | ||
120 | |||
121 | /* NB: we mimic util-linux's taskset: -p does not take | ||
122 | * an argument, i.e., "-pN" is NOT valid, only "-p N"! | ||
123 | * Indeed, util-linux-2.13-pre7 uses: | ||
124 | * getopt_long(argc, argv, "+pchV", ...), not "...p:..." */ | ||
125 | |||
126 | opt_complementary = "-1"; /* at least 1 arg */ | ||
127 | opt_p = getopt32(argv, "+p"); | ||
128 | argv += optind; | ||
129 | |||
130 | aff = *argv++; | ||
131 | if (opt_p) { | ||
132 | char *pid_str = aff; | ||
133 | if (*argv) { /* "-p <aff> <pid> ...rest.is.ignored..." */ | ||
134 | pid_str = *argv; /* NB: *argv != NULL in this case */ | ||
135 | } | ||
136 | /* else it was just "-p <pid>", and *argv == NULL */ | ||
137 | pid = xatoul_range(pid_str, 1, ((unsigned)(pid_t)ULONG_MAX) >> 1); | ||
138 | } else { | ||
139 | /* <aff> <cmd...> */ | ||
140 | if (!*argv) | ||
141 | bb_show_usage(); | ||
142 | } | ||
143 | |||
144 | mask_size_in_bytes = SZOF_UL; | ||
145 | current_new = "current"; | ||
146 | print_aff: | ||
147 | mask = get_aff(pid, &mask_size_in_bytes); | ||
148 | if (opt_p) { | ||
149 | printf("pid %d's %s affinity mask: "TASKSET_PRINTF_MASK"\n", | ||
150 | pid, current_new, from_mask(mask, mask_size_in_bytes)); | ||
151 | if (*argv == NULL) { | ||
152 | /* Either it was just "-p <pid>", | ||
153 | * or it was "-p <aff> <pid>" and we came here | ||
154 | * for the second time (see goto below) */ | ||
155 | return EXIT_SUCCESS; | ||
156 | } | ||
157 | *argv = NULL; | ||
158 | current_new = "new"; | ||
159 | } | ||
160 | memset(mask, 0, mask_size_in_bytes); | ||
161 | |||
162 | /* Affinity was specified, translate it into mask */ | ||
163 | /* it is always in hex, skip "0x" if it exists */ | ||
164 | if (aff[0] == '0' && (aff[1]|0x20) == 'x') | ||
165 | aff += 2; | ||
166 | |||
167 | if (!ENABLE_FEATURE_TASKSET_FANCY) { | ||
168 | mask[0] = xstrtoul(aff, 16); | ||
169 | } else { | ||
170 | unsigned i; | ||
171 | char *last_char; | ||
172 | |||
173 | i = 0; /* bit pos in mask[] */ | ||
174 | |||
175 | /* aff is ASCII hex string, accept very long masks in this form. | ||
176 | * Process hex string AABBCCDD... to ulong mask[] | ||
177 | * from the rightmost nibble, which is least-significant. | ||
178 | * Bits not fitting into mask[] are ignored: (example: 1234 | ||
179 | * in 12340000000000000000000000000000000000000ff) | ||
180 | */ | ||
181 | last_char = strchrnul(aff, '\0'); | ||
182 | while (last_char > aff) { | ||
183 | char c; | ||
184 | ul val; | ||
185 | |||
186 | last_char--; | ||
187 | c = *last_char; | ||
188 | if (isdigit(c)) | ||
189 | val = c - '0'; | ||
190 | else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') | ||
191 | val = (c|0x20) - ('a' - 10); | ||
192 | else | ||
193 | bb_error_msg_and_die("bad affinity '%s'", aff); | ||
194 | |||
195 | if (i < mask_size_in_bytes * 8) { | ||
196 | mask[i / BITS_UL] |= val << (i & MASK_UL); | ||
197 | //bb_error_msg("bit %d set", i); | ||
198 | } | ||
199 | /* else: | ||
200 | * We can error out here, but we don't. | ||
201 | * For one, kernel itself ignores bits in mask[] | ||
202 | * which do not map to any CPUs: | ||
203 | * if mask[] has one 32-bit long element, | ||
204 | * but you have only 8 CPUs, all bits beyond first 8 | ||
205 | * are ignored, silently. | ||
206 | * No point in making bits past 31th to be errors. | ||
207 | */ | ||
208 | i += 4; | ||
209 | } | ||
210 | } | ||
211 | |||
212 | /* Set pid's or our own (pid==0) affinity */ | ||
213 | if (sched_setaffinity(pid, mask_size_in_bytes, (void*)mask)) | ||
214 | bb_perror_msg_and_die("can't %cet pid %d's affinity", 's', pid); | ||
215 | //bb_error_msg("set mask[0]:%lx", mask[0]); | ||
216 | |||
217 | if (!argv[0]) /* "-p <aff> <pid> [...ignored...]" */ | ||
218 | goto print_aff; /* print new affinity and exit */ | ||
219 | |||
220 | BB_EXECVP_or_die(argv); | ||
221 | } | ||