]>
Commit | Line | Data |
---|---|---|
48d7b13a | 1 | /* |
a7560c06 | 2 | * chrt.c - manipulate a task's real-time attributes |
48d7b13a | 3 | * |
a7560c06 BS |
4 | * 27-Apr-2002: initial version - Robert Love <rml@tech9.net> |
5 | * 04-May-2011: make it thread-aware - Davidlohr Bueso <dave@gnu.org> | |
48d7b13a KZ |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify | |
a7560c06 | 8 | * it under the terms of the GNU General Public License, version 2, as |
48d7b13a KZ |
9 | * published by the Free Software Foundation |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
7cebf0bb SK |
16 | * You should have received a copy of the GNU General Public License along |
17 | * with this program; if not, write to the Free Software Foundation, Inc., | |
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
48d7b13a KZ |
19 | * |
20 | * Copyright (C) 2004 Robert Love | |
21 | */ | |
22 | ||
48d7b13a KZ |
23 | #include <stdio.h> |
24 | #include <stdlib.h> | |
25 | #include <sched.h> | |
26 | #include <unistd.h> | |
27 | #include <getopt.h> | |
28 | #include <errno.h> | |
bd9d9f05 | 29 | |
b6534e4f | 30 | #include "c.h" |
bd9d9f05 | 31 | #include "nls.h" |
ed8ec2a6 | 32 | #include "closestream.h" |
8abcf290 | 33 | #include "strutils.h" |
78904e76 | 34 | #include "procutils.h" |
24295096 | 35 | |
09dd84ca KZ |
36 | /* the SCHED_BATCH is supported since Linux 2.6.16 |
37 | * -- temporary workaround for people with old glibc headers | |
38 | */ | |
b64279da | 39 | #if defined (__linux__) && !defined(SCHED_BATCH) |
09dd84ca KZ |
40 | # define SCHED_BATCH 3 |
41 | #endif | |
42 | ||
c779d6e9 MS |
43 | /* the SCHED_IDLE is supported since Linux 2.6.23 |
44 | * commit id 0e6aca43e08a62a48d6770e9a159dbec167bf4c6 | |
45 | * -- temporary workaround for people with old glibc headers | |
46 | */ | |
b64279da | 47 | #if defined (__linux__) && !defined(SCHED_IDLE) |
c779d6e9 MS |
48 | # define SCHED_IDLE 5 |
49 | #endif | |
50 | ||
0fefbedc AK |
51 | #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK) |
52 | #define SCHED_RESET_ON_FORK 0x40000000 | |
53 | #endif | |
54 | ||
55 | ||
98da1298 | 56 | static void __attribute__((__noreturn__)) show_usage(int rc) |
48d7b13a | 57 | { |
aaf6349f BS |
58 | FILE *out = rc == EXIT_SUCCESS ? stdout : stderr; |
59 | ||
60 | fprintf(out, _( | |
61 | "\nchrt - manipulate real-time attributes of a process\n" | |
bd9d9f05 | 62 | "\nSet policy:\n" |
4ce393f4 | 63 | " chrt [options] [<policy>] <priority> [-p <pid> | <command> [<arg>...]]\n" |
bd9d9f05 | 64 | "\nGet policy:\n" |
fdf8fb1c | 65 | " chrt [options] -p <pid>\n")); |
aaf6349f BS |
66 | |
67 | fprintf(out, _( | |
bd9d9f05 KZ |
68 | "\nScheduling policies:\n" |
69 | " -b | --batch set policy to SCHED_BATCH\n" | |
70 | " -f | --fifo set policy to SCHED_FIFO\n" | |
71 | " -i | --idle set policy to SCHED_IDLE\n" | |
72 | " -o | --other set policy to SCHED_OTHER\n" | |
aaf6349f BS |
73 | " -r | --rr set policy to SCHED_RR (default)\n")); |
74 | ||
4951f9b3 | 75 | #ifdef SCHED_RESET_ON_FORK |
aaf6349f | 76 | fprintf(out, _( |
cdfb1e88 | 77 | "\nScheduling flags:\n" |
aaf6349f | 78 | " -R | --reset-on-fork set SCHED_RESET_ON_FORK for FIFO or RR\n")); |
4951f9b3 | 79 | #endif |
aaf6349f | 80 | fprintf(out, _( |
bd9d9f05 | 81 | "\nOptions:\n" |
1b9b57ac | 82 | " -a | --all-tasks operate on all the tasks (threads) for a given pid\n" |
bd9d9f05 | 83 | " -h | --help display this help\n" |
bd9d9f05 | 84 | " -m | --max show min and max valid priorities\n" |
aaf6349f | 85 | " -p | --pid operate on existing given pid\n" |
bd9d9f05 KZ |
86 | " -v | --verbose display status information\n" |
87 | " -V | --version output version information\n\n")); | |
88 | ||
89 | exit(rc); | |
48d7b13a KZ |
90 | } |
91 | ||
a9a3e5f2 | 92 | static void show_rt_info(pid_t pid, int isnew) |
48d7b13a KZ |
93 | { |
94 | struct sched_param sp; | |
95 | int policy; | |
96 | ||
97 | /* don't display "pid 0" as that is confusing */ | |
98 | if (!pid) | |
99 | pid = getpid(); | |
100 | ||
101 | policy = sched_getscheduler(pid); | |
bd9d9f05 KZ |
102 | if (policy == -1) |
103 | err(EXIT_FAILURE, _("failed to get pid %d's policy"), pid); | |
48d7b13a | 104 | |
a9a3e5f2 BS |
105 | if (isnew) |
106 | printf(_("pid %d's new scheduling policy: "), pid); | |
107 | else | |
108 | printf(_("pid %d's current scheduling policy: "), pid); | |
109 | ||
48d7b13a KZ |
110 | switch (policy) { |
111 | case SCHED_OTHER: | |
112 | printf("SCHED_OTHER\n"); | |
113 | break; | |
114 | case SCHED_FIFO: | |
115 | printf("SCHED_FIFO\n"); | |
116 | break; | |
4951f9b3 | 117 | #ifdef SCHED_RESET_ON_FORK |
110d680a | 118 | case SCHED_FIFO | SCHED_RESET_ON_FORK: |
0fefbedc AK |
119 | printf("SCHED_FIFO|SCHED_RESET_ON_FORK\n"); |
120 | break; | |
4951f9b3 | 121 | #endif |
b64279da | 122 | #ifdef SCHED_IDLE |
c779d6e9 MS |
123 | case SCHED_IDLE: |
124 | printf("SCHED_IDLE\n"); | |
6c00cbbe | 125 | break; |
b64279da | 126 | #endif |
48d7b13a KZ |
127 | case SCHED_RR: |
128 | printf("SCHED_RR\n"); | |
129 | break; | |
4951f9b3 | 130 | #ifdef SCHED_RESET_ON_FORK |
110d680a | 131 | case SCHED_RR | SCHED_RESET_ON_FORK: |
0fefbedc AK |
132 | printf("SCHED_RR|SCHED_RESET_ON_FORK\n"); |
133 | break; | |
4951f9b3 | 134 | #endif |
b64279da | 135 | #ifdef SCHED_BATCH |
df3773fb KZ |
136 | case SCHED_BATCH: |
137 | printf("SCHED_BATCH\n"); | |
138 | break; | |
b64279da | 139 | #endif |
48d7b13a | 140 | default: |
8a44fb01 | 141 | warnx(_("unknown scheduling policy")); |
48d7b13a KZ |
142 | } |
143 | ||
bd9d9f05 KZ |
144 | if (sched_getparam(pid, &sp)) |
145 | err(EXIT_FAILURE, _("failed to get pid %d's attributes"), pid); | |
48d7b13a | 146 | |
a9a3e5f2 BS |
147 | if (isnew) |
148 | printf(_("pid %d's new scheduling priority: %d\n"), | |
149 | pid, sp.sched_priority); | |
150 | else | |
151 | printf(_("pid %d's current scheduling priority: %d\n"), | |
152 | pid, sp.sched_priority); | |
48d7b13a KZ |
153 | } |
154 | ||
155 | static void show_min_max(void) | |
156 | { | |
90b7d261 | 157 | unsigned long i; |
110d680a SK |
158 | int policies[] = { |
159 | SCHED_OTHER, | |
160 | SCHED_FIFO, | |
161 | SCHED_RR, | |
b64279da | 162 | #ifdef SCHED_BATCH |
110d680a | 163 | SCHED_BATCH, |
b64279da AJ |
164 | #endif |
165 | #ifdef SCHED_IDLE | |
110d680a | 166 | SCHED_IDLE, |
b64279da | 167 | #endif |
110d680a SK |
168 | }; |
169 | const char *names[] = { | |
170 | "OTHER", | |
171 | "FIFO", | |
172 | "RR", | |
b64279da | 173 | #ifdef SCHED_BATCH |
110d680a | 174 | "BATCH", |
b64279da AJ |
175 | #endif |
176 | #ifdef SCHED_IDLE | |
110d680a | 177 | "IDLE", |
b64279da | 178 | #endif |
110d680a | 179 | }; |
bd9d9f05 KZ |
180 | |
181 | for (i = 0; i < ARRAY_SIZE(policies); i++) { | |
182 | int max = sched_get_priority_max(policies[i]); | |
183 | int min = sched_get_priority_min(policies[i]); | |
184 | ||
185 | if (max >= 0 && min >= 0) | |
186 | printf(_("SCHED_%s min/max priority\t: %d/%d\n"), | |
187 | names[i], min, max); | |
188 | else | |
189 | printf(_("SCHED_%s not supported?\n"), names[i]); | |
190 | } | |
48d7b13a KZ |
191 | } |
192 | ||
110d680a | 193 | int main(int argc, char **argv) |
48d7b13a | 194 | { |
503cbbe1 KZ |
195 | int i, policy = SCHED_RR, priority = 0, verbose = 0, policy_flag = 0, |
196 | all_tasks = 0; | |
48d7b13a | 197 | struct sched_param sp; |
697d58e8 | 198 | pid_t pid = -1; |
48d7b13a | 199 | |
6c7d5ae9 | 200 | static const struct option longopts[] = { |
78904e76 | 201 | { "all-tasks", 0, NULL, 'a' }, |
df3773fb | 202 | { "batch", 0, NULL, 'b' }, |
48d7b13a | 203 | { "fifo", 0, NULL, 'f' }, |
c779d6e9 | 204 | { "idle", 0, NULL, 'i' }, |
48d7b13a KZ |
205 | { "pid", 0, NULL, 'p' }, |
206 | { "help", 0, NULL, 'h' }, | |
207 | { "max", 0, NULL, 'm' }, | |
208 | { "other", 0, NULL, 'o' }, | |
209 | { "rr", 0, NULL, 'r' }, | |
cdfb1e88 | 210 | { "reset-on-fork", 0, NULL, 'R' }, |
48d7b13a KZ |
211 | { "verbose", 0, NULL, 'v' }, |
212 | { "version", 0, NULL, 'V' }, | |
213 | { NULL, 0, NULL, 0 } | |
214 | }; | |
215 | ||
bd9d9f05 KZ |
216 | setlocale(LC_ALL, ""); |
217 | bindtextdomain(PACKAGE, LOCALEDIR); | |
218 | textdomain(PACKAGE); | |
ed8ec2a6 | 219 | atexit(close_stdout); |
bd9d9f05 | 220 | |
78904e76 | 221 | while((i = getopt_long(argc, argv, "+abfiphmoRrvV", longopts, NULL)) != -1) |
48d7b13a | 222 | { |
bd9d9f05 | 223 | int ret = EXIT_FAILURE; |
48d7b13a KZ |
224 | |
225 | switch (i) { | |
78904e76 DB |
226 | case 'a': |
227 | all_tasks = 1; | |
228 | break; | |
df3773fb | 229 | case 'b': |
b64279da | 230 | #ifdef SCHED_BATCH |
df3773fb | 231 | policy = SCHED_BATCH; |
b64279da | 232 | #endif |
df3773fb | 233 | break; |
48d7b13a KZ |
234 | case 'f': |
235 | policy = SCHED_FIFO; | |
236 | break; | |
cdfb1e88 | 237 | case 'R': |
c150589f | 238 | #ifdef SCHED_RESET_ON_FORK |
cdfb1e88 | 239 | policy_flag |= SCHED_RESET_ON_FORK; |
4951f9b3 | 240 | #endif |
c150589f | 241 | break; |
c779d6e9 | 242 | case 'i': |
b64279da | 243 | #ifdef SCHED_IDLE |
c779d6e9 | 244 | policy = SCHED_IDLE; |
b64279da | 245 | #endif |
c779d6e9 | 246 | break; |
48d7b13a KZ |
247 | case 'm': |
248 | show_min_max(); | |
110d680a | 249 | return EXIT_SUCCESS; |
48d7b13a KZ |
250 | case 'o': |
251 | policy = SCHED_OTHER; | |
252 | break; | |
253 | case 'p': | |
254 | errno = 0; | |
630ed89d | 255 | pid = strtos32_or_err(argv[argc - 1], _("invalid PID argument")); |
48d7b13a KZ |
256 | break; |
257 | case 'r': | |
258 | policy = SCHED_RR; | |
259 | break; | |
260 | case 'v': | |
261 | verbose = 1; | |
262 | break; | |
263 | case 'V': | |
8c219bf4 BS |
264 | printf(_("%s from %s\n"), program_invocation_short_name, |
265 | PACKAGE_STRING); | |
110d680a | 266 | return EXIT_SUCCESS; |
48d7b13a | 267 | case 'h': |
bd9d9f05 | 268 | ret = EXIT_SUCCESS; |
337b8ead | 269 | /* fallthrough */ |
48d7b13a | 270 | default: |
bd9d9f05 | 271 | show_usage(ret); |
48d7b13a | 272 | } |
48d7b13a KZ |
273 | } |
274 | ||
110d680a SK |
275 | if (((pid > -1) && argc - optind < 1) || |
276 | ((pid == -1) && argc - optind < 2)) | |
bd9d9f05 | 277 | show_usage(EXIT_FAILURE); |
48d7b13a | 278 | |
697d58e8 | 279 | if ((pid > -1) && (verbose || argc - optind == 1)) { |
503cbbe1 KZ |
280 | if (all_tasks) { |
281 | pid_t tid; | |
282 | struct proc_tasks *ts = proc_open_tasks(pid); | |
283 | ||
284 | if (!ts) | |
8a44fb01 | 285 | err(EXIT_FAILURE, _("cannot obtain the list of tasks")); |
503cbbe1 KZ |
286 | while (!proc_next_tid(ts, &tid)) |
287 | show_rt_info(tid, FALSE); | |
288 | proc_close_tasks(ts); | |
289 | } else | |
290 | show_rt_info(pid, FALSE); | |
291 | ||
48d7b13a | 292 | if (argc - optind == 1) |
bd9d9f05 | 293 | return EXIT_SUCCESS; |
48d7b13a KZ |
294 | } |
295 | ||
296 | errno = 0; | |
630ed89d | 297 | priority = strtos32_or_err(argv[optind], _("invalid priority argument")); |
48d7b13a | 298 | |
4951f9b3 | 299 | #ifdef SCHED_RESET_ON_FORK |
cdfb1e88 KZ |
300 | /* sanity check */ |
301 | if ((policy_flag & SCHED_RESET_ON_FORK) && | |
302 | !(policy == SCHED_FIFO || policy == SCHED_RR)) | |
bbac757b | 303 | errx(EXIT_FAILURE, _("SCHED_RESET_ON_FORK flag is supported for " |
110d680a | 304 | "SCHED_FIFO and SCHED_RR policies only")); |
4951f9b3 | 305 | #endif |
cdfb1e88 KZ |
306 | |
307 | policy |= policy_flag; | |
308 | ||
697d58e8 MK |
309 | if (pid == -1) |
310 | pid = 0; | |
48d7b13a | 311 | sp.sched_priority = priority; |
78904e76 DB |
312 | |
313 | if (all_tasks) { | |
314 | pid_t tid; | |
315 | struct proc_tasks *ts = proc_open_tasks(pid); | |
316 | ||
317 | if (!ts) | |
8a44fb01 | 318 | err(EXIT_FAILURE, _("cannot obtain the list of tasks")); |
78904e76 DB |
319 | while (!proc_next_tid(ts, &tid)) |
320 | if (sched_setscheduler(tid, policy, &sp) == -1) | |
321 | err(EXIT_FAILURE, _("failed to set tid %d's policy"), tid); | |
78904e76 | 322 | proc_close_tasks(ts); |
110d680a SK |
323 | } else if (sched_setscheduler(pid, policy, &sp) == -1) |
324 | err(EXIT_FAILURE, _("failed to set pid %d's policy"), pid); | |
48d7b13a KZ |
325 | |
326 | if (verbose) | |
a9a3e5f2 | 327 | show_rt_info(pid, TRUE); |
48d7b13a KZ |
328 | |
329 | if (!pid) { | |
330 | argv += optind + 1; | |
331 | execvp(argv[0], argv); | |
bd9d9f05 | 332 | err(EXIT_FAILURE, _("failed to execute %s"), argv[0]); |
48d7b13a KZ |
333 | } |
334 | ||
bd9d9f05 | 335 | return EXIT_SUCCESS; |
48d7b13a | 336 | } |