Annotation of /tags/mkinitrd-6_3_1/busybox/miscutils/taskset.c
Parent Directory
|
Revision Log
Revision 1143 -
(hide annotations)
(download)
Thu Aug 19 12:44:27 2010 UTC (13 years, 10 months ago) by niro
File MIME type: text/plain
File size: 3676 byte(s)
Thu Aug 19 12:44:27 2010 UTC (13 years, 10 months ago) by niro
File MIME type: text/plain
File size: 3676 byte(s)
tagged 'mkinitrd-6_3_1'
1 | niro | 532 | /* vi: set sw=4 ts=4: */ |
2 | /* | ||
3 | * taskset - retrieve or set a processes' CPU affinity | ||
4 | niro | 816 | * Copyright (c) 2006 Bernhard Reutner-Fischer |
5 | niro | 532 | * |
6 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | ||
7 | */ | ||
8 | |||
9 | #include <sched.h> | ||
10 | niro | 816 | #include "libbb.h" |
11 | niro | 532 | |
12 | #if ENABLE_FEATURE_TASKSET_FANCY | ||
13 | #define TASKSET_PRINTF_MASK "%s" | ||
14 | /* craft a string from the mask */ | ||
15 | niro | 816 | static char *from_cpuset(cpu_set_t *mask) |
16 | niro | 532 | { |
17 | int i; | ||
18 | niro | 816 | char *ret = NULL; |
19 | char *str = xzalloc((CPU_SETSIZE / 4) + 1); /* we will leak it */ | ||
20 | niro | 532 | |
21 | for (i = CPU_SETSIZE - 4; i >= 0; i -= 4) { | ||
22 | niro | 816 | int val = 0; |
23 | niro | 532 | int off; |
24 | for (off = 0; off <= 3; ++off) | ||
25 | niro | 816 | if (CPU_ISSET(i + off, mask)) |
26 | val |= 1 << off; | ||
27 | niro | 532 | if (!ret && val) |
28 | ret = str; | ||
29 | niro | 816 | *str++ = bb_hexdigits_upcase[val] | 0x20; |
30 | niro | 532 | } |
31 | return ret; | ||
32 | } | ||
33 | #else | ||
34 | niro | 816 | #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 | niro | 532 | #endif |
55 | niro | 816 | 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 | niro | 532 | |
63 | |||
64 | niro | 816 | int taskset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
65 | int taskset_main(int argc UNUSED_PARAM, char **argv) | ||
66 | niro | 532 | { |
67 | niro | 816 | cpu_set_t mask; |
68 | niro | 532 | pid_t pid = 0; |
69 | niro | 816 | unsigned opt_p; |
70 | const char *current_new; | ||
71 | char *pid_str; | ||
72 | char *aff = aff; /* for compiler */ | ||
73 | niro | 532 | |
74 | niro | 816 | /* 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 | niro | 532 | |
79 | niro | 816 | opt_complementary = "-1"; /* at least 1 arg */ |
80 | opt_p = getopt32(argv, "+p"); | ||
81 | argv += optind; | ||
82 | niro | 532 | |
83 | niro | 816 | 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 | niro | 532 | } |
89 | niro | 816 | /* 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 | niro | 532 | } |
96 | |||
97 | niro | 816 | current_new = "current\0new"; |
98 | if (opt_p) { | ||
99 | niro | 532 | print_aff: |
100 | if (sched_getaffinity(pid, sizeof(mask), &mask) < 0) | ||
101 | niro | 816 | bb_perror_msg_and_die("can't %cet pid %d's affinity", 'g', pid); |
102 | niro | 532 | printf("pid %d's %s affinity mask: "TASKSET_PRINTF_MASK"\n", |
103 | niro | 816 | 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 | niro | 532 | return EXIT_SUCCESS; |
109 | niro | 816 | } |
110 | *argv = NULL; | ||
111 | current_new += 8; /* "new" */ | ||
112 | niro | 532 | } |
113 | |||
114 | niro | 816 | { /* 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 | niro | 532 | } |
127 | niro | 816 | |
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 | niro | 1123 | if (!argv[0]) /* "-p <aff> <pid> [...ignored...]" */ |
133 | niro | 816 | goto print_aff; /* print new affinity and exit */ |
134 | |||
135 | niro | 1123 | BB_EXECVP_or_die(argv); |
136 | niro | 532 | } |