]>
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> | |
88b60f0b KZ |
29 | #include <sys/time.h> |
30 | #include <sys/resource.h> | |
bd9d9f05 | 31 | |
b6534e4f | 32 | #include "c.h" |
bd9d9f05 | 33 | #include "nls.h" |
ed8ec2a6 | 34 | #include "closestream.h" |
8abcf290 | 35 | #include "strutils.h" |
78904e76 | 36 | #include "procutils.h" |
24295096 | 37 | |
09dd84ca KZ |
38 | /* the SCHED_BATCH is supported since Linux 2.6.16 |
39 | * -- temporary workaround for people with old glibc headers | |
40 | */ | |
b64279da | 41 | #if defined (__linux__) && !defined(SCHED_BATCH) |
09dd84ca KZ |
42 | # define SCHED_BATCH 3 |
43 | #endif | |
44 | ||
c779d6e9 MS |
45 | /* the SCHED_IDLE is supported since Linux 2.6.23 |
46 | * commit id 0e6aca43e08a62a48d6770e9a159dbec167bf4c6 | |
47 | * -- temporary workaround for people with old glibc headers | |
48 | */ | |
b64279da | 49 | #if defined (__linux__) && !defined(SCHED_IDLE) |
c779d6e9 MS |
50 | # define SCHED_IDLE 5 |
51 | #endif | |
52 | ||
acde3a05 | 53 | /* flag by sched_getscheduler() */ |
0fefbedc | 54 | #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK) |
acde3a05 KZ |
55 | # define SCHED_RESET_ON_FORK 0x40000000 |
56 | #endif | |
57 | ||
58 | /* flag by sched_getattr() */ | |
59 | #if defined(__linux__) && !defined(SCHED_FLAG_RESET_ON_FORK) | |
60 | # define SCHED_FLAG_RESET_ON_FORK 0x01 | |
0fefbedc AK |
61 | #endif |
62 | ||
15167589 KZ |
63 | #if defined (__linux__) && !defined(HAVE_SCHED_SETATTR) |
64 | # include <sys/syscall.h> | |
65 | #endif | |
66 | ||
6f27e449 KZ |
67 | /* usable kernel-headers, but old glibc-headers */ |
68 | #if defined (__linux__) && !defined(SYS_sched_setattr) && defined(__NR_sched_setattr) | |
69 | # define SYS_sched_setattr __NR_sched_setattr | |
70 | #endif | |
71 | ||
72 | #if defined (__linux__) && !defined(SYS_sched_getattr) && defined(__NR_sched_getattr) | |
73 | # define SYS_sched_getattr __NR_sched_getattr | |
74 | #endif | |
75 | ||
15167589 KZ |
76 | #if defined (__linux__) && !defined(HAVE_SCHED_SETATTR) && defined(SYS_sched_setattr) |
77 | # define HAVE_SCHED_SETATTR | |
78 | ||
79 | struct sched_attr { | |
80 | uint32_t size; | |
81 | uint32_t sched_policy; | |
82 | uint64_t sched_flags; | |
83 | ||
84 | /* SCHED_NORMAL, SCHED_BATCH */ | |
85 | int32_t sched_nice; | |
86 | ||
87 | /* SCHED_FIFO, SCHED_RR */ | |
88 | uint32_t sched_priority; | |
89 | ||
90 | /* SCHED_DEADLINE (nsec) */ | |
91 | uint64_t sched_runtime; | |
92 | uint64_t sched_deadline; | |
93 | uint64_t sched_period; | |
94 | }; | |
95 | ||
96 | static int sched_setattr(pid_t pid, const struct sched_attr *attr, unsigned int flags) | |
97 | { | |
98 | return syscall(SYS_sched_setattr, pid, attr, flags); | |
99 | } | |
100 | ||
101 | static int sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int size, unsigned int flags) | |
102 | { | |
103 | return syscall(SYS_sched_getattr, pid, attr, size, flags); | |
104 | } | |
1a7e6395 KZ |
105 | #endif |
106 | ||
107 | /* the SCHED_DEADLINE is supported since Linux 3.14 | |
108 | * commit id aab03e05e8f7e26f51dee792beddcb5cca9215a5 | |
109 | * -- sched_setattr() is required for this policy! | |
110 | */ | |
111 | #if defined (__linux__) && !defined(SCHED_DEADLINE) && defined(HAVE_SCHED_SETATTR) | |
112 | # define SCHED_DEADLINE 6 | |
113 | #endif | |
15167589 | 114 | |
7a4ea566 KZ |
115 | /* control struct */ |
116 | struct chrt_ctl { | |
117 | pid_t pid; | |
118 | int policy; /* SCHED_* */ | |
119 | int priority; | |
120 | ||
1a7e6395 KZ |
121 | uint64_t runtime; /* --sched-* options */ |
122 | uint64_t deadline; | |
123 | uint64_t period; | |
124 | ||
7a4ea566 KZ |
125 | unsigned int all_tasks : 1, /* all threads of the PID */ |
126 | reset_on_fork : 1, /* SCHED_RESET_ON_FORK */ | |
a30cf650 | 127 | altered : 1, /* sched_set**() used */ |
7a4ea566 KZ |
128 | verbose : 1; /* verbose output */ |
129 | }; | |
0fefbedc | 130 | |
5118d1be | 131 | static void __attribute__((__noreturn__)) usage(void) |
48d7b13a | 132 | { |
5118d1be | 133 | FILE *out = stdout; |
aaf6349f | 134 | |
451dbcfa | 135 | fputs(_("Show or change the real-time scheduling attributes of a process.\n"), out); |
9acbe2aa BS |
136 | fputs(USAGE_SEPARATOR, out); |
137 | fputs(_("Set policy:\n" | |
138 | " chrt [options] <priority> <command> [<arg>...]\n" | |
a6fec537 | 139 | " chrt [options] --pid <priority> <pid>\n"), out); |
9acbe2aa BS |
140 | fputs(USAGE_SEPARATOR, out); |
141 | fputs(_("Get policy:\n" | |
142 | " chrt [options] -p <pid>\n"), out); | |
aaf6349f | 143 | |
9acbe2aa BS |
144 | fputs(USAGE_SEPARATOR, out); |
145 | fputs(_("Policy options:\n"), out); | |
146 | fputs(_(" -b, --batch set policy to SCHED_BATCH\n"), out); | |
1a7e6395 | 147 | fputs(_(" -d, --deadline set policy to SCHED_DEADLINE\n"), out); |
9acbe2aa BS |
148 | fputs(_(" -f, --fifo set policy to SCHED_FIFO\n"), out); |
149 | fputs(_(" -i, --idle set policy to SCHED_IDLE\n"), out); | |
150 | fputs(_(" -o, --other set policy to SCHED_OTHER\n"), out); | |
151 | fputs(_(" -r, --rr set policy to SCHED_RR (default)\n"), out); | |
aaf6349f | 152 | |
9acbe2aa | 153 | fputs(USAGE_SEPARATOR, out); |
1a7e6395 KZ |
154 | fputs(_("Scheduling options:\n"), out); |
155 | fputs(_(" -R, --reset-on-fork set SCHED_RESET_ON_FORK for FIFO or RR\n"), out); | |
156 | fputs(_(" -T, --sched-runtime <ns> runtime parameter for DEADLINE\n"), out); | |
157 | fputs(_(" -P, --sched-period <ns> period parameter for DEADLINE\n"), out); | |
158 | fputs(_(" -D, --sched-deadline <ns> deadline parameter for DEADLINE\n"), out); | |
159 | ||
9acbe2aa BS |
160 | fputs(USAGE_SEPARATOR, out); |
161 | fputs(_("Other options:\n"), out); | |
162 | fputs(_(" -a, --all-tasks operate on all the tasks (threads) for a given pid\n"), out); | |
163 | fputs(_(" -m, --max show min and max valid priorities\n"), out); | |
164 | fputs(_(" -p, --pid operate on existing given pid\n"), out); | |
165 | fputs(_(" -v, --verbose display status information\n"), out); | |
166 | ||
167 | fputs(USAGE_SEPARATOR, out); | |
f45f3ec3 | 168 | printf(USAGE_HELP_OPTIONS(22)); |
bd9d9f05 | 169 | |
f45f3ec3 | 170 | printf(USAGE_MAN_TAIL("chrt(1)")); |
5118d1be | 171 | exit(EXIT_SUCCESS); |
48d7b13a KZ |
172 | } |
173 | ||
acde3a05 | 174 | static const char *get_policy_name(int policy) |
48d7b13a | 175 | { |
48d7b13a KZ |
176 | switch (policy) { |
177 | case SCHED_OTHER: | |
acde3a05 | 178 | return "SCHED_OTHER"; |
48d7b13a | 179 | case SCHED_FIFO: |
a03eac52 | 180 | #ifdef SCHED_RESET_ON_FORK |
110d680a | 181 | case SCHED_FIFO | SCHED_RESET_ON_FORK: |
a03eac52 | 182 | #endif |
acde3a05 | 183 | return "SCHED_FIFO"; |
b64279da | 184 | #ifdef SCHED_IDLE |
c779d6e9 | 185 | case SCHED_IDLE: |
acde3a05 | 186 | return "SCHED_IDLE"; |
b64279da | 187 | #endif |
48d7b13a | 188 | case SCHED_RR: |
a03eac52 | 189 | #ifdef SCHED_RESET_ON_FORK |
59e4a382 | 190 | case SCHED_RR | SCHED_RESET_ON_FORK: |
a03eac52 | 191 | #endif |
acde3a05 | 192 | return "SCHED_RR"; |
b64279da | 193 | #ifdef SCHED_BATCH |
df3773fb | 194 | case SCHED_BATCH: |
acde3a05 | 195 | return "SCHED_BATCH"; |
1a7e6395 KZ |
196 | #endif |
197 | #ifdef SCHED_DEADLINE | |
198 | case SCHED_DEADLINE: | |
acde3a05 | 199 | return "SCHED_DEADLINE"; |
b64279da | 200 | #endif |
48d7b13a | 201 | default: |
acde3a05 | 202 | break; |
48d7b13a KZ |
203 | } |
204 | ||
acde3a05 KZ |
205 | return _("unknown"); |
206 | } | |
207 | ||
208 | static void show_sched_pid_info(struct chrt_ctl *ctl, pid_t pid) | |
209 | { | |
685f5449 | 210 | int policy = -1, reset_on_fork = 0, prio = 0; |
acde3a05 KZ |
211 | #ifdef SCHED_DEADLINE |
212 | uint64_t deadline = 0, runtime = 0, period = 0; | |
213 | #endif | |
214 | ||
215 | /* don't display "pid 0" as that is confusing */ | |
216 | if (!pid) | |
217 | pid = getpid(); | |
218 | ||
6f27e449 KZ |
219 | errno = 0; |
220 | ||
221 | /* | |
222 | * New way | |
223 | */ | |
acde3a05 KZ |
224 | #ifdef HAVE_SCHED_SETATTR |
225 | { | |
226 | struct sched_attr sa; | |
227 | ||
6f27e449 KZ |
228 | if (sched_getattr(pid, &sa, sizeof(sa), 0) != 0) { |
229 | if (errno == ENOSYS) | |
230 | goto fallback; | |
acde3a05 | 231 | err(EXIT_FAILURE, _("failed to get pid %d's policy"), pid); |
6f27e449 | 232 | } |
acde3a05 KZ |
233 | |
234 | policy = sa.sched_policy; | |
235 | prio = sa.sched_priority; | |
236 | reset_on_fork = sa.sched_flags & SCHED_FLAG_RESET_ON_FORK; | |
237 | deadline = sa.sched_deadline; | |
238 | runtime = sa.sched_runtime; | |
239 | period = sa.sched_period; | |
240 | } | |
6f27e449 KZ |
241 | |
242 | /* | |
243 | * Old way | |
244 | */ | |
245 | fallback: | |
fded05ac RM |
246 | if (errno == ENOSYS) |
247 | #endif | |
248 | { | |
acde3a05 KZ |
249 | struct sched_param sp; |
250 | ||
251 | policy = sched_getscheduler(pid); | |
252 | if (policy == -1) | |
253 | err(EXIT_FAILURE, _("failed to get pid %d's policy"), pid); | |
254 | ||
255 | if (sched_getparam(pid, &sp) != 0) | |
256 | err(EXIT_FAILURE, _("failed to get pid %d's attributes"), pid); | |
257 | else | |
258 | prio = sp.sched_priority; | |
259 | # ifdef SCHED_RESET_ON_FORK | |
260 | if (policy == (SCHED_FIFO|SCHED_RESET_ON_FORK) || policy == (SCHED_BATCH|SCHED_RESET_ON_FORK)) | |
261 | reset_on_fork = 1; | |
262 | # endif | |
263 | } | |
48d7b13a | 264 | |
a30cf650 | 265 | if (ctl->altered) |
acde3a05 | 266 | printf(_("pid %d's new scheduling policy: %s"), pid, get_policy_name(policy)); |
a9a3e5f2 | 267 | else |
acde3a05 KZ |
268 | printf(_("pid %d's current scheduling policy: %s"), pid, get_policy_name(policy)); |
269 | ||
270 | if (reset_on_fork) | |
271 | printf("|SCHED_RESET_ON_FORK"); | |
272 | putchar('\n'); | |
273 | ||
274 | if (ctl->altered) | |
275 | printf(_("pid %d's new scheduling priority: %d\n"), pid, prio); | |
276 | else | |
277 | printf(_("pid %d's current scheduling priority: %d\n"), pid, prio); | |
278 | ||
279 | #ifdef SCHED_DEADLINE | |
280 | if (policy == SCHED_DEADLINE) { | |
281 | if (ctl->altered) | |
282 | printf(_("pid %d's new runtime/deadline/period parameters: %ju/%ju/%ju\n"), | |
283 | pid, runtime, deadline, period); | |
284 | else | |
285 | printf(_("pid %d's current runtime/deadline/period parameters: %ju/%ju/%ju\n"), | |
286 | pid, runtime, deadline, period); | |
287 | } | |
288 | #endif | |
48d7b13a KZ |
289 | } |
290 | ||
a30cf650 KZ |
291 | |
292 | static void show_sched_info(struct chrt_ctl *ctl) | |
293 | { | |
294 | if (ctl->all_tasks) { | |
295 | pid_t tid; | |
296 | struct proc_tasks *ts = proc_open_tasks(ctl->pid); | |
297 | ||
298 | if (!ts) | |
299 | err(EXIT_FAILURE, _("cannot obtain the list of tasks")); | |
300 | ||
301 | while (!proc_next_tid(ts, &tid)) | |
302 | show_sched_pid_info(ctl, tid); | |
303 | ||
304 | proc_close_tasks(ts); | |
305 | } else | |
306 | show_sched_pid_info(ctl, ctl->pid); | |
307 | } | |
308 | ||
48d7b13a KZ |
309 | static void show_min_max(void) |
310 | { | |
90b7d261 | 311 | unsigned long i; |
110d680a SK |
312 | int policies[] = { |
313 | SCHED_OTHER, | |
314 | SCHED_FIFO, | |
315 | SCHED_RR, | |
b64279da | 316 | #ifdef SCHED_BATCH |
110d680a | 317 | SCHED_BATCH, |
b64279da AJ |
318 | #endif |
319 | #ifdef SCHED_IDLE | |
110d680a | 320 | SCHED_IDLE, |
1a7e6395 KZ |
321 | #endif |
322 | #ifdef SCHED_DEADLINE | |
323 | SCHED_DEADLINE, | |
b64279da | 324 | #endif |
110d680a | 325 | }; |
bd9d9f05 KZ |
326 | |
327 | for (i = 0; i < ARRAY_SIZE(policies); i++) { | |
acde3a05 KZ |
328 | int plc = policies[i]; |
329 | int max = sched_get_priority_max(plc); | |
330 | int min = sched_get_priority_min(plc); | |
bd9d9f05 KZ |
331 | |
332 | if (max >= 0 && min >= 0) | |
078720a7 | 333 | printf(_("%s min/max priority\t: %d/%d\n"), |
acde3a05 | 334 | get_policy_name(plc), min, max); |
bd9d9f05 | 335 | else |
078720a7 | 336 | printf(_("%s not supported?\n"), get_policy_name(plc)); |
bd9d9f05 | 337 | } |
48d7b13a KZ |
338 | } |
339 | ||
6f27e449 | 340 | static int set_sched_one_by_setscheduler(struct chrt_ctl *ctl, pid_t pid) |
4820a737 KZ |
341 | { |
342 | struct sched_param sp = { .sched_priority = ctl->priority }; | |
15167589 | 343 | int policy = ctl->policy; |
4820a737 | 344 | |
88b60f0b | 345 | errno = 0; |
15167589 KZ |
346 | # ifdef SCHED_RESET_ON_FORK |
347 | if (ctl->reset_on_fork) | |
348 | policy |= SCHED_RESET_ON_FORK; | |
349 | # endif | |
350 | return sched_setscheduler(pid, policy, &sp); | |
351 | } | |
352 | ||
6f27e449 KZ |
353 | |
354 | #ifndef HAVE_SCHED_SETATTR | |
355 | static int set_sched_one(struct chrt_ctl *ctl, pid_t pid) | |
356 | { | |
357 | return set_sched_one_by_setscheduler(ctl, pid); | |
358 | } | |
359 | ||
15167589 KZ |
360 | #else /* !HAVE_SCHED_SETATTR */ |
361 | static int set_sched_one(struct chrt_ctl *ctl, pid_t pid) | |
362 | { | |
88b60f0b KZ |
363 | struct sched_attr sa = { .size = sizeof(struct sched_attr) }; |
364 | ||
365 | /* old API is good enough for non-deadline */ | |
366 | if (ctl->policy != SCHED_DEADLINE) | |
367 | return set_sched_one_by_setscheduler(ctl, pid); | |
368 | ||
369 | /* no changeed by chrt, follow the current setting */ | |
370 | sa.sched_nice = getpriority(PRIO_PROCESS, pid); | |
371 | ||
1a7e6395 | 372 | /* use main() to check if the setting makes sense */ |
88b60f0b KZ |
373 | sa.sched_policy = ctl->policy; |
374 | sa.sched_priority = ctl->priority; | |
375 | sa.sched_runtime = ctl->runtime; | |
376 | sa.sched_period = ctl->period; | |
377 | sa.sched_deadline = ctl->deadline; | |
6f27e449 | 378 | |
15167589 KZ |
379 | # ifdef SCHED_RESET_ON_FORK |
380 | if (ctl->reset_on_fork) | |
381 | sa.sched_flags |= SCHED_RESET_ON_FORK; | |
382 | # endif | |
6f27e449 | 383 | errno = 0; |
88b60f0b | 384 | return sched_setattr(pid, &sa, 0); |
15167589 KZ |
385 | } |
386 | #endif /* HAVE_SCHED_SETATTR */ | |
387 | ||
388 | static void set_sched(struct chrt_ctl *ctl) | |
389 | { | |
4820a737 KZ |
390 | if (ctl->all_tasks) { |
391 | pid_t tid; | |
392 | struct proc_tasks *ts = proc_open_tasks(ctl->pid); | |
393 | ||
394 | if (!ts) | |
395 | err(EXIT_FAILURE, _("cannot obtain the list of tasks")); | |
396 | ||
397 | while (!proc_next_tid(ts, &tid)) | |
15167589 | 398 | if (set_sched_one(ctl, tid) == -1) |
4820a737 KZ |
399 | err(EXIT_FAILURE, _("failed to set tid %d's policy"), tid); |
400 | ||
401 | proc_close_tasks(ts); | |
402 | ||
15167589 | 403 | } else if (set_sched_one(ctl, ctl->pid) == -1) |
4820a737 KZ |
404 | err(EXIT_FAILURE, _("failed to set pid %d's policy"), ctl->pid); |
405 | ||
406 | ctl->altered = 1; | |
407 | } | |
408 | ||
110d680a | 409 | int main(int argc, char **argv) |
48d7b13a | 410 | { |
c7adc2f2 | 411 | struct chrt_ctl _ctl = { .pid = -1, .policy = SCHED_RR }, *ctl = &_ctl; |
4820a737 | 412 | int c; |
48d7b13a | 413 | |
6c7d5ae9 | 414 | static const struct option longopts[] = { |
1a7e6395 KZ |
415 | { "all-tasks", no_argument, NULL, 'a' }, |
416 | { "batch", no_argument, NULL, 'b' }, | |
417 | { "deadline", no_argument, NULL, 'd' }, | |
418 | { "fifo", no_argument, NULL, 'f' }, | |
419 | { "idle", no_argument, NULL, 'i' }, | |
420 | { "pid", no_argument, NULL, 'p' }, | |
421 | { "help", no_argument, NULL, 'h' }, | |
422 | { "max", no_argument, NULL, 'm' }, | |
423 | { "other", no_argument, NULL, 'o' }, | |
424 | { "rr", no_argument, NULL, 'r' }, | |
425 | { "sched-runtime", required_argument, NULL, 'T' }, | |
426 | { "sched-period", required_argument, NULL, 'P' }, | |
427 | { "sched-deadline", required_argument, NULL, 'D' }, | |
428 | { "reset-on-fork", no_argument, NULL, 'R' }, | |
429 | { "verbose", no_argument, NULL, 'v' }, | |
430 | { "version", no_argument, NULL, 'V' }, | |
431 | { NULL, no_argument, NULL, 0 } | |
48d7b13a KZ |
432 | }; |
433 | ||
bd9d9f05 KZ |
434 | setlocale(LC_ALL, ""); |
435 | bindtextdomain(PACKAGE, LOCALEDIR); | |
436 | textdomain(PACKAGE); | |
2c308875 | 437 | close_stdout_atexit(); |
bd9d9f05 | 438 | |
b3a50671 | 439 | while((c = getopt_long(argc, argv, "+abdD:fiphmoP:T:rRvV", longopts, NULL)) != -1) |
48d7b13a | 440 | { |
4820a737 | 441 | switch (c) { |
78904e76 | 442 | case 'a': |
7a4ea566 | 443 | ctl->all_tasks = 1; |
78904e76 | 444 | break; |
df3773fb | 445 | case 'b': |
b64279da | 446 | #ifdef SCHED_BATCH |
7a4ea566 | 447 | ctl->policy = SCHED_BATCH; |
1a7e6395 KZ |
448 | #endif |
449 | break; | |
450 | ||
451 | case 'd': | |
452 | #ifdef SCHED_DEADLINE | |
453 | ctl->policy = SCHED_DEADLINE; | |
b64279da | 454 | #endif |
df3773fb | 455 | break; |
48d7b13a | 456 | case 'f': |
7a4ea566 | 457 | ctl->policy = SCHED_FIFO; |
48d7b13a | 458 | break; |
cdfb1e88 | 459 | case 'R': |
7a4ea566 | 460 | ctl->reset_on_fork = 1; |
c150589f | 461 | break; |
c779d6e9 | 462 | case 'i': |
b64279da | 463 | #ifdef SCHED_IDLE |
7a4ea566 | 464 | ctl->policy = SCHED_IDLE; |
b64279da | 465 | #endif |
c779d6e9 | 466 | break; |
48d7b13a KZ |
467 | case 'm': |
468 | show_min_max(); | |
110d680a | 469 | return EXIT_SUCCESS; |
48d7b13a | 470 | case 'o': |
7a4ea566 | 471 | ctl->policy = SCHED_OTHER; |
48d7b13a KZ |
472 | break; |
473 | case 'p': | |
474 | errno = 0; | |
7a4ea566 | 475 | ctl->pid = strtos32_or_err(argv[argc - 1], _("invalid PID argument")); |
48d7b13a KZ |
476 | break; |
477 | case 'r': | |
7a4ea566 | 478 | ctl->policy = SCHED_RR; |
48d7b13a KZ |
479 | break; |
480 | case 'v': | |
7a4ea566 | 481 | ctl->verbose = 1; |
48d7b13a | 482 | break; |
1a7e6395 KZ |
483 | case 'T': |
484 | ctl->runtime = strtou64_or_err(optarg, _("invalid runtime argument")); | |
485 | break; | |
486 | case 'P': | |
487 | ctl->period = strtou64_or_err(optarg, _("invalid period argument")); | |
488 | break; | |
489 | case 'D': | |
490 | ctl->deadline = strtou64_or_err(optarg, _("invalid deadline argument")); | |
491 | break; | |
2c308875 | 492 | |
48d7b13a | 493 | case 'V': |
2c308875 | 494 | print_version(EXIT_SUCCESS); |
48d7b13a | 495 | case 'h': |
5118d1be | 496 | usage(); |
48d7b13a | 497 | default: |
677ec86c | 498 | errtryhelp(EXIT_FAILURE); |
48d7b13a | 499 | } |
48d7b13a KZ |
500 | } |
501 | ||
7a4ea566 | 502 | if (((ctl->pid > -1) && argc - optind < 1) || |
5118d1be RM |
503 | ((ctl->pid == -1) && argc - optind < 2)) { |
504 | warnx(_("bad usage")); | |
505 | errtryhelp(EXIT_FAILURE); | |
506 | } | |
48d7b13a | 507 | |
7a4ea566 | 508 | if ((ctl->pid > -1) && (ctl->verbose || argc - optind == 1)) { |
a30cf650 | 509 | show_sched_info(ctl); |
48d7b13a | 510 | if (argc - optind == 1) |
bd9d9f05 | 511 | return EXIT_SUCCESS; |
48d7b13a KZ |
512 | } |
513 | ||
514 | errno = 0; | |
7a4ea566 | 515 | ctl->priority = strtos32_or_err(argv[optind], _("invalid priority argument")); |
48d7b13a | 516 | |
4951f9b3 | 517 | #ifdef SCHED_RESET_ON_FORK |
1a7e6395 KZ |
518 | if (ctl->reset_on_fork && ctl->policy != SCHED_FIFO && ctl->policy != SCHED_RR) |
519 | errx(EXIT_FAILURE, _("--reset-on-fork option is supported for " | |
520 | "SCHED_FIFO and SCHED_RR policies only")); | |
521 | #endif | |
522 | #ifdef SCHED_DEADLINE | |
523 | if ((ctl->runtime || ctl->deadline || ctl->period) && ctl->policy != SCHED_DEADLINE) | |
524 | errx(EXIT_FAILURE, _("--sched-{runtime,deadline,period} options " | |
525 | "are supported for SCHED_DEADLINE only")); | |
526 | if (ctl->policy == SCHED_DEADLINE) { | |
527 | /* The basic rule is runtime <= deadline <= period, so we can | |
528 | * make deadline and runtime optional on command line. Note we | |
529 | * don't check any values or set any defaults, it's kernel | |
530 | * responsibility. | |
531 | */ | |
532 | if (ctl->deadline == 0) | |
533 | ctl->deadline = ctl->period; | |
534 | if (ctl->runtime == 0) | |
535 | ctl->runtime = ctl->deadline; | |
536 | } | |
537 | #else | |
538 | if (ctl->runtime || ctl->deadline || ctl->period) | |
539 | errx(EXIT_FAILURE, _("SCHED_DEADLINE is unsupported")); | |
4951f9b3 | 540 | #endif |
7a4ea566 KZ |
541 | if (ctl->pid == -1) |
542 | ctl->pid = 0; | |
2e31d1c3 SK |
543 | if (ctl->priority < sched_get_priority_min(ctl->policy) || |
544 | sched_get_priority_max(ctl->policy) < ctl->priority) | |
545 | errx(EXIT_FAILURE, | |
546 | _("unsupported priority value for the policy: %d: see --max for valid range"), | |
547 | ctl->priority); | |
4820a737 | 548 | set_sched(ctl); |
a30cf650 | 549 | |
7a4ea566 | 550 | if (ctl->verbose) |
a30cf650 | 551 | show_sched_info(ctl); |
48d7b13a | 552 | |
7a4ea566 | 553 | if (!ctl->pid) { |
48d7b13a KZ |
554 | argv += optind + 1; |
555 | execvp(argv[0], argv); | |
61b62222 | 556 | errexec(argv[0]); |
48d7b13a KZ |
557 | } |
558 | ||
bd9d9f05 | 559 | return EXIT_SUCCESS; |
48d7b13a | 560 | } |