]> git.ipfire.org Git - thirdparty/util-linux.git/blame - schedutils/chrt.c
chrt: make usage more readable
[thirdparty/util-linux.git] / schedutils / chrt.c
CommitLineData
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
7a4ea566
KZ
55/* control struct */
56struct chrt_ctl {
57 pid_t pid;
58 int policy; /* SCHED_* */
59 int priority;
60
61 unsigned int all_tasks : 1, /* all threads of the PID */
62 reset_on_fork : 1, /* SCHED_RESET_ON_FORK */
a30cf650 63 altered : 1, /* sched_set**() used */
7a4ea566
KZ
64 verbose : 1; /* verbose output */
65};
0fefbedc 66
98da1298 67static void __attribute__((__noreturn__)) show_usage(int rc)
48d7b13a 68{
aaf6349f
BS
69 FILE *out = rc == EXIT_SUCCESS ? stdout : stderr;
70
451dbcfa 71 fputs(_("Show or change the real-time scheduling attributes of a process.\n"), out);
9acbe2aa
BS
72 fputs(USAGE_SEPARATOR, out);
73 fputs(_("Set policy:\n"
74 " chrt [options] <priority> <command> [<arg>...]\n"
a6fec537 75 " chrt [options] --pid <priority> <pid>\n"), out);
9acbe2aa
BS
76 fputs(USAGE_SEPARATOR, out);
77 fputs(_("Get policy:\n"
78 " chrt [options] -p <pid>\n"), out);
aaf6349f 79
9acbe2aa
BS
80 fputs(USAGE_SEPARATOR, out);
81 fputs(_("Policy options:\n"), out);
82 fputs(_(" -b, --batch set policy to SCHED_BATCH\n"), out);
83 fputs(_(" -f, --fifo set policy to SCHED_FIFO\n"), out);
84 fputs(_(" -i, --idle set policy to SCHED_IDLE\n"), out);
85 fputs(_(" -o, --other set policy to SCHED_OTHER\n"), out);
86 fputs(_(" -r, --rr set policy to SCHED_RR (default)\n"), out);
aaf6349f 87
4951f9b3 88#ifdef SCHED_RESET_ON_FORK
9acbe2aa
BS
89 fputs(USAGE_SEPARATOR, out);
90 fputs(_("Scheduling flag:\n"), out);
91 fputs(_(" -R, --reset-on-fork set SCHED_RESET_ON_FORK for FIFO or RR\n"), out);
4951f9b3 92#endif
9acbe2aa
BS
93 fputs(USAGE_SEPARATOR, out);
94 fputs(_("Other options:\n"), out);
95 fputs(_(" -a, --all-tasks operate on all the tasks (threads) for a given pid\n"), out);
96 fputs(_(" -m, --max show min and max valid priorities\n"), out);
97 fputs(_(" -p, --pid operate on existing given pid\n"), out);
98 fputs(_(" -v, --verbose display status information\n"), out);
99
100 fputs(USAGE_SEPARATOR, out);
101 fputs(USAGE_HELP, out);
102 fputs(USAGE_VERSION, out);
bd9d9f05 103
a587cc55 104 fprintf(out, USAGE_MAN_TAIL("chrt(1)"));
bd9d9f05 105 exit(rc);
48d7b13a
KZ
106}
107
a30cf650 108static void show_sched_pid_info(struct chrt_ctl *ctl, pid_t pid)
48d7b13a
KZ
109{
110 struct sched_param sp;
111 int policy;
112
113 /* don't display "pid 0" as that is confusing */
114 if (!pid)
115 pid = getpid();
116
117 policy = sched_getscheduler(pid);
bd9d9f05
KZ
118 if (policy == -1)
119 err(EXIT_FAILURE, _("failed to get pid %d's policy"), pid);
48d7b13a 120
a30cf650 121 if (ctl->altered)
a9a3e5f2
BS
122 printf(_("pid %d's new scheduling policy: "), pid);
123 else
124 printf(_("pid %d's current scheduling policy: "), pid);
125
48d7b13a
KZ
126 switch (policy) {
127 case SCHED_OTHER:
128 printf("SCHED_OTHER\n");
129 break;
130 case SCHED_FIFO:
131 printf("SCHED_FIFO\n");
132 break;
4951f9b3 133#ifdef SCHED_RESET_ON_FORK
110d680a 134 case SCHED_FIFO | SCHED_RESET_ON_FORK:
0fefbedc
AK
135 printf("SCHED_FIFO|SCHED_RESET_ON_FORK\n");
136 break;
4951f9b3 137#endif
b64279da 138#ifdef SCHED_IDLE
c779d6e9
MS
139 case SCHED_IDLE:
140 printf("SCHED_IDLE\n");
6c00cbbe 141 break;
b64279da 142#endif
48d7b13a
KZ
143 case SCHED_RR:
144 printf("SCHED_RR\n");
145 break;
4951f9b3 146#ifdef SCHED_RESET_ON_FORK
110d680a 147 case SCHED_RR | SCHED_RESET_ON_FORK:
0fefbedc
AK
148 printf("SCHED_RR|SCHED_RESET_ON_FORK\n");
149 break;
4951f9b3 150#endif
b64279da 151#ifdef SCHED_BATCH
df3773fb
KZ
152 case SCHED_BATCH:
153 printf("SCHED_BATCH\n");
154 break;
b64279da 155#endif
48d7b13a 156 default:
8a44fb01 157 warnx(_("unknown scheduling policy"));
48d7b13a
KZ
158 }
159
bd9d9f05
KZ
160 if (sched_getparam(pid, &sp))
161 err(EXIT_FAILURE, _("failed to get pid %d's attributes"), pid);
48d7b13a 162
a30cf650 163 if (ctl->altered)
a9a3e5f2
BS
164 printf(_("pid %d's new scheduling priority: %d\n"),
165 pid, sp.sched_priority);
166 else
167 printf(_("pid %d's current scheduling priority: %d\n"),
168 pid, sp.sched_priority);
48d7b13a
KZ
169}
170
a30cf650
KZ
171
172static void show_sched_info(struct chrt_ctl *ctl)
173{
174 if (ctl->all_tasks) {
175 pid_t tid;
176 struct proc_tasks *ts = proc_open_tasks(ctl->pid);
177
178 if (!ts)
179 err(EXIT_FAILURE, _("cannot obtain the list of tasks"));
180
181 while (!proc_next_tid(ts, &tid))
182 show_sched_pid_info(ctl, tid);
183
184 proc_close_tasks(ts);
185 } else
186 show_sched_pid_info(ctl, ctl->pid);
187}
188
48d7b13a
KZ
189static void show_min_max(void)
190{
90b7d261 191 unsigned long i;
110d680a
SK
192 int policies[] = {
193 SCHED_OTHER,
194 SCHED_FIFO,
195 SCHED_RR,
b64279da 196#ifdef SCHED_BATCH
110d680a 197 SCHED_BATCH,
b64279da
AJ
198#endif
199#ifdef SCHED_IDLE
110d680a 200 SCHED_IDLE,
b64279da 201#endif
110d680a
SK
202 };
203 const char *names[] = {
204 "OTHER",
205 "FIFO",
206 "RR",
b64279da 207#ifdef SCHED_BATCH
110d680a 208 "BATCH",
b64279da
AJ
209#endif
210#ifdef SCHED_IDLE
110d680a 211 "IDLE",
b64279da 212#endif
110d680a 213 };
bd9d9f05
KZ
214
215 for (i = 0; i < ARRAY_SIZE(policies); i++) {
216 int max = sched_get_priority_max(policies[i]);
217 int min = sched_get_priority_min(policies[i]);
218
219 if (max >= 0 && min >= 0)
220 printf(_("SCHED_%s min/max priority\t: %d/%d\n"),
221 names[i], min, max);
222 else
223 printf(_("SCHED_%s not supported?\n"), names[i]);
224 }
48d7b13a
KZ
225}
226
4820a737
KZ
227static void set_sched(struct chrt_ctl *ctl)
228{
229 struct sched_param sp = { .sched_priority = ctl->priority };
230
231 if (ctl->all_tasks) {
232 pid_t tid;
233 struct proc_tasks *ts = proc_open_tasks(ctl->pid);
234
235 if (!ts)
236 err(EXIT_FAILURE, _("cannot obtain the list of tasks"));
237
238 while (!proc_next_tid(ts, &tid))
239 if (sched_setscheduler(tid, ctl->policy, &sp) == -1)
240 err(EXIT_FAILURE, _("failed to set tid %d's policy"), tid);
241
242 proc_close_tasks(ts);
243
244 } else if (sched_setscheduler(ctl->pid, ctl->policy, &sp) == -1)
245 err(EXIT_FAILURE, _("failed to set pid %d's policy"), ctl->pid);
246
247 ctl->altered = 1;
248}
249
110d680a 250int main(int argc, char **argv)
48d7b13a 251{
7a4ea566 252 struct chrt_ctl _ctl = { .pid = -1 }, *ctl = &_ctl;
4820a737 253 int c;
48d7b13a 254
6c7d5ae9 255 static const struct option longopts[] = {
78904e76 256 { "all-tasks", 0, NULL, 'a' },
df3773fb 257 { "batch", 0, NULL, 'b' },
48d7b13a 258 { "fifo", 0, NULL, 'f' },
c779d6e9 259 { "idle", 0, NULL, 'i' },
48d7b13a
KZ
260 { "pid", 0, NULL, 'p' },
261 { "help", 0, NULL, 'h' },
262 { "max", 0, NULL, 'm' },
263 { "other", 0, NULL, 'o' },
264 { "rr", 0, NULL, 'r' },
cdfb1e88 265 { "reset-on-fork", 0, NULL, 'R' },
48d7b13a
KZ
266 { "verbose", 0, NULL, 'v' },
267 { "version", 0, NULL, 'V' },
268 { NULL, 0, NULL, 0 }
269 };
270
bd9d9f05
KZ
271 setlocale(LC_ALL, "");
272 bindtextdomain(PACKAGE, LOCALEDIR);
273 textdomain(PACKAGE);
ed8ec2a6 274 atexit(close_stdout);
bd9d9f05 275
4820a737 276 while((c = getopt_long(argc, argv, "+abfiphmoRrvV", longopts, NULL)) != -1)
48d7b13a 277 {
bd9d9f05 278 int ret = EXIT_FAILURE;
48d7b13a 279
4820a737 280 switch (c) {
78904e76 281 case 'a':
7a4ea566 282 ctl->all_tasks = 1;
78904e76 283 break;
df3773fb 284 case 'b':
b64279da 285#ifdef SCHED_BATCH
7a4ea566 286 ctl->policy = SCHED_BATCH;
b64279da 287#endif
df3773fb 288 break;
48d7b13a 289 case 'f':
7a4ea566 290 ctl->policy = SCHED_FIFO;
48d7b13a 291 break;
cdfb1e88 292 case 'R':
7a4ea566 293 ctl->reset_on_fork = 1;
c150589f 294 break;
c779d6e9 295 case 'i':
b64279da 296#ifdef SCHED_IDLE
7a4ea566 297 ctl->policy = SCHED_IDLE;
b64279da 298#endif
c779d6e9 299 break;
48d7b13a
KZ
300 case 'm':
301 show_min_max();
110d680a 302 return EXIT_SUCCESS;
48d7b13a 303 case 'o':
7a4ea566 304 ctl->policy = SCHED_OTHER;
48d7b13a
KZ
305 break;
306 case 'p':
307 errno = 0;
7a4ea566 308 ctl->pid = strtos32_or_err(argv[argc - 1], _("invalid PID argument"));
48d7b13a
KZ
309 break;
310 case 'r':
7a4ea566 311 ctl->policy = SCHED_RR;
48d7b13a
KZ
312 break;
313 case 'v':
7a4ea566 314 ctl->verbose = 1;
48d7b13a
KZ
315 break;
316 case 'V':
f6277500 317 printf(UTIL_LINUX_VERSION);
110d680a 318 return EXIT_SUCCESS;
48d7b13a 319 case 'h':
bd9d9f05 320 ret = EXIT_SUCCESS;
337b8ead 321 /* fallthrough */
48d7b13a 322 default:
bd9d9f05 323 show_usage(ret);
48d7b13a 324 }
48d7b13a
KZ
325 }
326
7a4ea566
KZ
327 if (((ctl->pid > -1) && argc - optind < 1) ||
328 ((ctl->pid == -1) && argc - optind < 2))
bd9d9f05 329 show_usage(EXIT_FAILURE);
48d7b13a 330
7a4ea566 331 if ((ctl->pid > -1) && (ctl->verbose || argc - optind == 1)) {
a30cf650 332 show_sched_info(ctl);
48d7b13a 333 if (argc - optind == 1)
bd9d9f05 334 return EXIT_SUCCESS;
48d7b13a
KZ
335 }
336
337 errno = 0;
7a4ea566 338 ctl->priority = strtos32_or_err(argv[optind], _("invalid priority argument"));
48d7b13a 339
4951f9b3 340#ifdef SCHED_RESET_ON_FORK
7a4ea566
KZ
341 if (ctl->reset_on_fork) {
342 if (ctl->policy != SCHED_FIFO && ctl->policy != SCHED_RR)
343 errx(EXIT_FAILURE, _("SCHED_RESET_ON_FORK flag is supported for "
344 "SCHED_FIFO and SCHED_RR policies only"));
345 ctl->policy |= SCHED_RESET_ON_FORK;
346 }
4951f9b3 347#endif
cdfb1e88 348
7a4ea566
KZ
349 if (ctl->pid == -1)
350 ctl->pid = 0;
48d7b13a 351
4820a737 352 set_sched(ctl);
a30cf650 353
7a4ea566 354 if (ctl->verbose)
a30cf650 355 show_sched_info(ctl);
48d7b13a 356
7a4ea566 357 if (!ctl->pid) {
48d7b13a
KZ
358 argv += optind + 1;
359 execvp(argv[0], argv);
bd9d9f05 360 err(EXIT_FAILURE, _("failed to execute %s"), argv[0]);
48d7b13a
KZ
361 }
362
bd9d9f05 363 return EXIT_SUCCESS;
48d7b13a 364}