1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51#include <sched.h>
52#include "libbb.h"
53
54typedef 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
62static char *from_mask(const ul *mask, unsigned sz_in_bytes)
63{
64 char *str = xzalloc((sz_in_bytes+1) * 2);
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"
84static unsigned long long from_mask(ul *mask, unsigned sz_in_bytes UNUSED_PARAM)
85{
86 return *mask;
87}
88#endif
89
90static 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
107 *sz = sz_in_bytes;
108 return mask;
109}
110
111int taskset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
112int 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
122
123
124
125
126 opt_p = getopt32(argv, "^+" "p" "\0" "-1" );
127 argv += optind;
128
129 aff = *argv++;
130 if (opt_p) {
131 char *pid_str = aff;
132 if (*argv) {
133 pid_str = *argv;
134 }
135
136 pid = xatoul_range(pid_str, 1, ((unsigned)(pid_t)ULONG_MAX) >> 1);
137 } else {
138
139 if (!*argv)
140 bb_show_usage();
141 }
142
143 mask_size_in_bytes = SZOF_UL;
144 current_new = "current";
145 print_aff:
146 mask = get_aff(pid, &mask_size_in_bytes);
147 if (opt_p) {
148 printf("pid %d's %s affinity mask: "TASKSET_PRINTF_MASK"\n",
149 pid, current_new, from_mask(mask, mask_size_in_bytes));
150 if (*argv == NULL) {
151
152
153
154 return EXIT_SUCCESS;
155 }
156 *argv = NULL;
157 current_new = "new";
158 }
159 memset(mask, 0, mask_size_in_bytes);
160
161
162
163 if (aff[0] == '0' && (aff[1]|0x20) == 'x')
164 aff += 2;
165
166 if (!ENABLE_FEATURE_TASKSET_FANCY) {
167 mask[0] = xstrtoul(aff, 16);
168 } else {
169 unsigned i;
170 char *last_char;
171
172 i = 0;
173
174
175
176
177
178
179
180 last_char = strchrnul(aff, '\0');
181 while (last_char > aff) {
182 char c;
183 ul val;
184
185 last_char--;
186 c = *last_char;
187 if (isdigit(c))
188 val = c - '0';
189 else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
190 val = (c|0x20) - ('a' - 10);
191 else
192 bb_error_msg_and_die("bad affinity '%s'", aff);
193
194 if (i < mask_size_in_bytes * 8) {
195 mask[i / BITS_UL] |= val << (i & MASK_UL);
196
197 }
198
199
200
201
202
203
204
205
206
207 i += 4;
208 }
209 }
210
211
212 if (sched_setaffinity(pid, mask_size_in_bytes, (void*)mask))
213 bb_perror_msg_and_die("can't %cet pid %d's affinity", 's', pid);
214
215
216 if (!argv[0])
217 goto print_aff;
218
219 BB_EXECVP_or_die(argv);
220}
221