Contents of /tags/mkinitrd-6_3_1/busybox/miscutils/taskset.c
Parent Directory | Revision Log
Revision 1123 -
(show annotations)
(download)
Wed Aug 18 21:56:57 2010 UTC (14 years, 1 month ago) by niro
Original Path: trunk/mkinitrd-magellan/busybox/miscutils/taskset.c
File MIME type: text/plain
File size: 3676 byte(s)
Wed Aug 18 21:56:57 2010 UTC (14 years, 1 month ago) by niro
Original Path: trunk/mkinitrd-magellan/busybox/miscutils/taskset.c
File MIME type: text/plain
File size: 3676 byte(s)
-updated to busybox-1.17.1
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 tarball for details. |
7 | */ |
8 | |
9 | #include <sched.h> |
10 | #include "libbb.h" |
11 | |
12 | #if ENABLE_FEATURE_TASKSET_FANCY |
13 | #define TASKSET_PRINTF_MASK "%s" |
14 | /* craft a string from the mask */ |
15 | static char *from_cpuset(cpu_set_t *mask) |
16 | { |
17 | int i; |
18 | char *ret = NULL; |
19 | char *str = xzalloc((CPU_SETSIZE / 4) + 1); /* we will leak it */ |
20 | |
21 | for (i = CPU_SETSIZE - 4; i >= 0; i -= 4) { |
22 | int val = 0; |
23 | int off; |
24 | for (off = 0; off <= 3; ++off) |
25 | if (CPU_ISSET(i + off, mask)) |
26 | val |= 1 << off; |
27 | if (!ret && val) |
28 | ret = str; |
29 | *str++ = bb_hexdigits_upcase[val] | 0x20; |
30 | } |
31 | return ret; |
32 | } |
33 | #else |
34 | #define TASKSET_PRINTF_MASK "%llx" |
35 | static unsigned long long from_cpuset(cpu_set_t *mask) |
36 | { |
37 | struct BUG_CPU_SETSIZE_is_too_small { |
38 | char BUG_CPU_SETSIZE_is_too_small[ |
39 | CPU_SETSIZE < sizeof(int) ? -1 : 1]; |
40 | }; |
41 | char *p = (void*)mask; |
42 | |
43 | /* Take the least significant bits. Careful! |
44 | * Consider both CPU_SETSIZE=4 and CPU_SETSIZE=1024 cases |
45 | */ |
46 | #if BB_BIG_ENDIAN |
47 | /* For big endian, it means LAST bits */ |
48 | if (CPU_SETSIZE < sizeof(long)) |
49 | p += CPU_SETSIZE - sizeof(int); |
50 | else if (CPU_SETSIZE < sizeof(long long)) |
51 | p += CPU_SETSIZE - sizeof(long); |
52 | else |
53 | p += CPU_SETSIZE - sizeof(long long); |
54 | #endif |
55 | if (CPU_SETSIZE < sizeof(long)) |
56 | return *(unsigned*)p; |
57 | if (CPU_SETSIZE < sizeof(long long)) |
58 | return *(unsigned long*)p; |
59 | return *(unsigned long long*)p; |
60 | } |
61 | #endif |
62 | |
63 | |
64 | int taskset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
65 | int taskset_main(int argc UNUSED_PARAM, char **argv) |
66 | { |
67 | cpu_set_t mask; |
68 | pid_t pid = 0; |
69 | unsigned opt_p; |
70 | const char *current_new; |
71 | char *pid_str; |
72 | char *aff = aff; /* for compiler */ |
73 | |
74 | /* NB: we mimic util-linux's taskset: -p does not take |
75 | * an argument, i.e., "-pN" is NOT valid, only "-p N"! |
76 | * Indeed, util-linux-2.13-pre7 uses: |
77 | * getopt_long(argc, argv, "+pchV", ...), not "...p:..." */ |
78 | |
79 | opt_complementary = "-1"; /* at least 1 arg */ |
80 | opt_p = getopt32(argv, "+p"); |
81 | argv += optind; |
82 | |
83 | if (opt_p) { |
84 | pid_str = *argv++; |
85 | if (*argv) { /* "-p <aff> <pid> ...rest.is.ignored..." */ |
86 | aff = pid_str; |
87 | pid_str = *argv; /* NB: *argv != NULL in this case */ |
88 | } |
89 | /* else it was just "-p <pid>", and *argv == NULL */ |
90 | pid = xatoul_range(pid_str, 1, ((unsigned)(pid_t)ULONG_MAX) >> 1); |
91 | } else { |
92 | aff = *argv++; /* <aff> <cmd...> */ |
93 | if (!*argv) |
94 | bb_show_usage(); |
95 | } |
96 | |
97 | current_new = "current\0new"; |
98 | if (opt_p) { |
99 | print_aff: |
100 | if (sched_getaffinity(pid, sizeof(mask), &mask) < 0) |
101 | bb_perror_msg_and_die("can't %cet pid %d's affinity", 'g', pid); |
102 | printf("pid %d's %s affinity mask: "TASKSET_PRINTF_MASK"\n", |
103 | pid, current_new, from_cpuset(&mask)); |
104 | if (!*argv) { |
105 | /* Either it was just "-p <pid>", |
106 | * or it was "-p <aff> <pid>" and we came here |
107 | * for the second time (see goto below) */ |
108 | return EXIT_SUCCESS; |
109 | } |
110 | *argv = NULL; |
111 | current_new += 8; /* "new" */ |
112 | } |
113 | |
114 | { /* Affinity was specified, translate it into cpu_set_t */ |
115 | unsigned i; |
116 | /* Do not allow zero mask: */ |
117 | unsigned long long m = xstrtoull_range(aff, 0, 1, ULLONG_MAX); |
118 | enum { CNT_BIT = CPU_SETSIZE < sizeof(m)*8 ? CPU_SETSIZE : sizeof(m)*8 }; |
119 | |
120 | CPU_ZERO(&mask); |
121 | for (i = 0; i < CNT_BIT; i++) { |
122 | unsigned long long bit = (1ULL << i); |
123 | if (bit & m) |
124 | CPU_SET(i, &mask); |
125 | } |
126 | } |
127 | |
128 | /* Set pid's or our own (pid==0) affinity */ |
129 | if (sched_setaffinity(pid, sizeof(mask), &mask)) |
130 | bb_perror_msg_and_die("can't %cet pid %d's affinity", 's', pid); |
131 | |
132 | if (!argv[0]) /* "-p <aff> <pid> [...ignored...]" */ |
133 | goto print_aff; /* print new affinity and exit */ |
134 | |
135 | BB_EXECVP_or_die(argv); |
136 | } |