]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - schedutils/chrt.c
2 * chrt.c - manipulate a task's real-time attributes
4 * 27-Apr-2002: initial version - Robert Love <rml@tech9.net>
5 * 04-May-2011: make it thread-aware - Davidlohr Bueso <dave@gnu.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License, version 2, as
9 * published by the Free Software Foundation
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.
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.
20 * Copyright (C) 2004 Robert Love
32 #include "closestream.h"
34 #include "procutils.h"
36 /* the SCHED_BATCH is supported since Linux 2.6.16
37 * -- temporary workaround for people with old glibc headers
39 #if defined (__linux__) && !defined(SCHED_BATCH)
40 # define SCHED_BATCH 3
43 /* the SCHED_IDLE is supported since Linux 2.6.23
44 * commit id 0e6aca43e08a62a48d6770e9a159dbec167bf4c6
45 * -- temporary workaround for people with old glibc headers
47 #if defined (__linux__) && !defined(SCHED_IDLE)
51 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
52 #define SCHED_RESET_ON_FORK 0x40000000
56 #if defined (__linux__) && !defined(HAVE_SCHED_SETATTR)
57 # include <sys/syscall.h>
60 #if defined (__linux__) && !defined(HAVE_SCHED_SETATTR) && defined(SYS_sched_setattr)
61 # define HAVE_SCHED_SETATTR
65 uint32_t sched_policy
;
68 /* SCHED_NORMAL, SCHED_BATCH */
71 /* SCHED_FIFO, SCHED_RR */
72 uint32_t sched_priority
;
74 /* SCHED_DEADLINE (nsec) */
75 uint64_t sched_runtime
;
76 uint64_t sched_deadline
;
77 uint64_t sched_period
;
80 static int sched_setattr(pid_t pid
, const struct sched_attr
*attr
, unsigned int flags
)
82 return syscall(SYS_sched_setattr
, pid
, attr
, flags
);
85 static int sched_getattr(pid_t pid
, struct sched_attr
*attr
, unsigned int size
, unsigned int flags
)
87 return syscall(SYS_sched_getattr
, pid
, attr
, size
, flags
);
91 /* the SCHED_DEADLINE is supported since Linux 3.14
92 * commit id aab03e05e8f7e26f51dee792beddcb5cca9215a5
93 * -- sched_setattr() is required for this policy!
95 #if defined (__linux__) && !defined(SCHED_DEADLINE) && defined(HAVE_SCHED_SETATTR)
96 # define SCHED_DEADLINE 6
103 int policy
; /* SCHED_* */
106 uint64_t runtime
; /* --sched-* options */
110 unsigned int all_tasks
: 1, /* all threads of the PID */
111 reset_on_fork
: 1, /* SCHED_RESET_ON_FORK */
112 altered
: 1, /* sched_set**() used */
113 verbose
: 1; /* verbose output */
116 static void __attribute__((__noreturn__
)) show_usage(int rc
)
118 FILE *out
= rc
== EXIT_SUCCESS
? stdout
: stderr
;
120 fputs(_("Show or change the real-time scheduling attributes of a process.\n"), out
);
121 fputs(USAGE_SEPARATOR
, out
);
122 fputs(_("Set policy:\n"
123 " chrt [options] <priority> <command> [<arg>...]\n"
124 " chrt [options] --pid <priority> <pid>\n"), out
);
125 fputs(USAGE_SEPARATOR
, out
);
126 fputs(_("Get policy:\n"
127 " chrt [options] -p <pid>\n"), out
);
129 fputs(USAGE_SEPARATOR
, out
);
130 fputs(_("Policy options:\n"), out
);
131 fputs(_(" -b, --batch set policy to SCHED_BATCH\n"), out
);
132 fputs(_(" -d, --deadline set policy to SCHED_DEADLINE\n"), out
);
133 fputs(_(" -f, --fifo set policy to SCHED_FIFO\n"), out
);
134 fputs(_(" -i, --idle set policy to SCHED_IDLE\n"), out
);
135 fputs(_(" -o, --other set policy to SCHED_OTHER\n"), out
);
136 fputs(_(" -r, --rr set policy to SCHED_RR (default)\n"), out
);
138 fputs(USAGE_SEPARATOR
, out
);
139 fputs(_("Scheduling options:\n"), out
);
140 fputs(_(" -R, --reset-on-fork set SCHED_RESET_ON_FORK for FIFO or RR\n"), out
);
141 fputs(_(" -T, --sched-runtime <ns> runtime parameter for DEADLINE\n"), out
);
142 fputs(_(" -P, --sched-period <ns> period parameter for DEADLINE\n"), out
);
143 fputs(_(" -D, --sched-deadline <ns> deadline parameter for DEADLINE\n"), out
);
145 fputs(USAGE_SEPARATOR
, out
);
146 fputs(_("Other options:\n"), out
);
147 fputs(_(" -a, --all-tasks operate on all the tasks (threads) for a given pid\n"), out
);
148 fputs(_(" -m, --max show min and max valid priorities\n"), out
);
149 fputs(_(" -p, --pid operate on existing given pid\n"), out
);
150 fputs(_(" -v, --verbose display status information\n"), out
);
152 fputs(USAGE_SEPARATOR
, out
);
153 fputs(USAGE_HELP
, out
);
154 fputs(USAGE_VERSION
, out
);
156 fprintf(out
, USAGE_MAN_TAIL("chrt(1)"));
160 static void show_sched_pid_info(struct chrt_ctl
*ctl
, pid_t pid
)
162 struct sched_param sp
;
165 /* don't display "pid 0" as that is confusing */
169 policy
= sched_getscheduler(pid
);
171 err(EXIT_FAILURE
, _("failed to get pid %d's policy"), pid
);
174 printf(_("pid %d's new scheduling policy: "), pid
);
176 printf(_("pid %d's current scheduling policy: "), pid
);
180 printf("SCHED_OTHER\n");
183 printf("SCHED_FIFO\n");
185 #ifdef SCHED_RESET_ON_FORK
186 case SCHED_FIFO
| SCHED_RESET_ON_FORK
:
187 printf("SCHED_FIFO|SCHED_RESET_ON_FORK\n");
192 printf("SCHED_IDLE\n");
196 printf("SCHED_RR\n");
198 #ifdef SCHED_RESET_ON_FORK
199 case SCHED_RR
| SCHED_RESET_ON_FORK
:
200 printf("SCHED_RR|SCHED_RESET_ON_FORK\n");
205 printf("SCHED_BATCH\n");
208 #ifdef SCHED_DEADLINE
210 printf("SCHED_DEADLINE\n");
214 warnx(_("unknown scheduling policy"));
217 if (sched_getparam(pid
, &sp
))
218 err(EXIT_FAILURE
, _("failed to get pid %d's attributes"), pid
);
221 printf(_("pid %d's new scheduling priority: %d\n"),
222 pid
, sp
.sched_priority
);
224 printf(_("pid %d's current scheduling priority: %d\n"),
225 pid
, sp
.sched_priority
);
229 static void show_sched_info(struct chrt_ctl
*ctl
)
231 if (ctl
->all_tasks
) {
233 struct proc_tasks
*ts
= proc_open_tasks(ctl
->pid
);
236 err(EXIT_FAILURE
, _("cannot obtain the list of tasks"));
238 while (!proc_next_tid(ts
, &tid
))
239 show_sched_pid_info(ctl
, tid
);
241 proc_close_tasks(ts
);
243 show_sched_pid_info(ctl
, ctl
->pid
);
246 static void show_min_max(void)
259 #ifdef SCHED_DEADLINE
263 const char *names
[] = {
273 #ifdef SCHED_DEADLINE
278 for (i
= 0; i
< ARRAY_SIZE(policies
); i
++) {
279 int max
= sched_get_priority_max(policies
[i
]);
280 int min
= sched_get_priority_min(policies
[i
]);
282 if (max
>= 0 && min
>= 0)
283 printf(_("SCHED_%s min/max priority\t: %d/%d\n"),
286 printf(_("SCHED_%s not supported?\n"), names
[i
]);
290 #ifndef HAVE_SCHED_SETATTR
291 static int set_sched_one(struct chrt_ctl
*ctl
, pid_t pid
)
293 struct sched_param sp
= { .sched_priority
= ctl
->priority
};
294 int policy
= ctl
->policy
;
296 # ifdef SCHED_RESET_ON_FORK
297 if (ctl
->reset_on_fork
)
298 policy
|= SCHED_RESET_ON_FORK
;
300 return sched_setscheduler(pid
, policy
, &sp
);
303 #else /* !HAVE_SCHED_SETATTR */
304 static int set_sched_one(struct chrt_ctl
*ctl
, pid_t pid
)
306 /* use main() to check if the setting makes sense */
307 struct sched_attr sa
= {
308 .sched_policy
= ctl
->policy
,
309 .sched_priority
= ctl
->priority
,
310 .sched_runtime
= ctl
->runtime
,
311 .sched_period
= ctl
->period
,
312 .sched_deadline
= ctl
->deadline
314 # ifdef SCHED_RESET_ON_FORK
315 if (ctl
->reset_on_fork
)
316 sa
.sched_flags
|= SCHED_RESET_ON_FORK
;
318 return sched_setattr(pid
, &sa
, 0);
320 #endif /* HAVE_SCHED_SETATTR */
322 static void set_sched(struct chrt_ctl
*ctl
)
324 if (ctl
->all_tasks
) {
326 struct proc_tasks
*ts
= proc_open_tasks(ctl
->pid
);
329 err(EXIT_FAILURE
, _("cannot obtain the list of tasks"));
331 while (!proc_next_tid(ts
, &tid
))
332 if (set_sched_one(ctl
, tid
) == -1)
333 err(EXIT_FAILURE
, _("failed to set tid %d's policy"), tid
);
335 proc_close_tasks(ts
);
337 } else if (set_sched_one(ctl
, ctl
->pid
) == -1)
338 err(EXIT_FAILURE
, _("failed to set pid %d's policy"), ctl
->pid
);
343 int main(int argc
, char **argv
)
345 struct chrt_ctl _ctl
= { .pid
= -1 }, *ctl
= &_ctl
;
348 static const struct option longopts
[] = {
349 { "all-tasks", no_argument
, NULL
, 'a' },
350 { "batch", no_argument
, NULL
, 'b' },
351 { "deadline", no_argument
, NULL
, 'd' },
352 { "fifo", no_argument
, NULL
, 'f' },
353 { "idle", no_argument
, NULL
, 'i' },
354 { "pid", no_argument
, NULL
, 'p' },
355 { "help", no_argument
, NULL
, 'h' },
356 { "max", no_argument
, NULL
, 'm' },
357 { "other", no_argument
, NULL
, 'o' },
358 { "rr", no_argument
, NULL
, 'r' },
359 { "sched-runtime", required_argument
, NULL
, 'T' },
360 { "sched-period", required_argument
, NULL
, 'P' },
361 { "sched-deadline", required_argument
, NULL
, 'D' },
362 { "reset-on-fork", no_argument
, NULL
, 'R' },
363 { "verbose", no_argument
, NULL
, 'v' },
364 { "version", no_argument
, NULL
, 'V' },
365 { NULL
, no_argument
, NULL
, 0 }
368 setlocale(LC_ALL
, "");
369 bindtextdomain(PACKAGE
, LOCALEDIR
);
371 atexit(close_stdout
);
373 while((c
= getopt_long(argc
, argv
, "+abdDfiphmoPTrRvV", longopts
, NULL
)) != -1)
375 int ret
= EXIT_FAILURE
;
383 ctl
->policy
= SCHED_BATCH
;
388 #ifdef SCHED_DEADLINE
389 ctl
->policy
= SCHED_DEADLINE
;
393 ctl
->policy
= SCHED_FIFO
;
396 ctl
->reset_on_fork
= 1;
400 ctl
->policy
= SCHED_IDLE
;
407 ctl
->policy
= SCHED_OTHER
;
411 ctl
->pid
= strtos32_or_err(argv
[argc
- 1], _("invalid PID argument"));
414 ctl
->policy
= SCHED_RR
;
420 ctl
->runtime
= strtou64_or_err(optarg
, _("invalid runtime argument"));
423 ctl
->period
= strtou64_or_err(optarg
, _("invalid period argument"));
426 ctl
->deadline
= strtou64_or_err(optarg
, _("invalid deadline argument"));
429 printf(UTIL_LINUX_VERSION
);
439 if (((ctl
->pid
> -1) && argc
- optind
< 1) ||
440 ((ctl
->pid
== -1) && argc
- optind
< 2))
441 show_usage(EXIT_FAILURE
);
443 if ((ctl
->pid
> -1) && (ctl
->verbose
|| argc
- optind
== 1)) {
444 show_sched_info(ctl
);
445 if (argc
- optind
== 1)
450 ctl
->priority
= strtos32_or_err(argv
[optind
], _("invalid priority argument"));
452 #ifdef SCHED_RESET_ON_FORK
453 if (ctl
->reset_on_fork
&& ctl
->policy
!= SCHED_FIFO
&& ctl
->policy
!= SCHED_RR
)
454 errx(EXIT_FAILURE
, _("--reset-on-fork option is supported for "
455 "SCHED_FIFO and SCHED_RR policies only"));
457 #ifdef SCHED_DEADLINE
458 if ((ctl
->runtime
|| ctl
->deadline
|| ctl
->period
) && ctl
->policy
!= SCHED_DEADLINE
)
459 errx(EXIT_FAILURE
, _("--sched-{runtime,deadline,period} options "
460 "are supported for SCHED_DEADLINE only"));
461 if (ctl
->policy
== SCHED_DEADLINE
) {
462 /* The basic rule is runtime <= deadline <= period, so we can
463 * make deadline and runtime optional on command line. Note we
464 * don't check any values or set any defaults, it's kernel
467 if (ctl
->deadline
== 0)
468 ctl
->deadline
= ctl
->period
;
469 if (ctl
->runtime
== 0)
470 ctl
->runtime
= ctl
->deadline
;
473 if (ctl
->runtime
|| ctl
->deadline
|| ctl
->period
)
474 errx(EXIT_FAILURE
, _("SCHED_DEADLINE is unsupported"));
482 show_sched_info(ctl
);
486 execvp(argv
[0], argv
);
487 err(EXIT_FAILURE
, _("failed to execute %s"), argv
[0]);