*chrt* [options] [_priority_] _command_ [_argument_...]
-*chrt --pid* [options] [_priority_] _PID_
+*chrt --pid* [options] [_priority_] _PID_[:_inode_]
== DESCRIPTION
-*chrt* sets or retrieves the real-time scheduling attributes of an existing _PID_, or runs _command_ with the given attributes.
+*chrt* sets or retrieves the real-time scheduling attributes of an existing _PID_[:_inode_], or runs _command_ with the given attributes.
+The _inode_ uniquely identifies the process identity in the pidfs. To retrieve a process's inode number you can use the *getino*(1) utility.
== POLICY OPTIONS
//TRANSLATORS: Keep {colon} untranslated
You can also retrieve the real-time attributes of an existing task{colon}::
____
-*chrt --pid* _PID_
+*chrt --pid* _PID_[:_inode_]
____
//TRANSLATORS: Keep {colon} untranslated
Or set them{colon}::
____
-*chrt --pid* _policy-option priority PID_
+*chrt --pid* _policy-option_ _priority_ _PID_[:_inode_]
____
For example, to set the scheduling policy to *SCHED_RR* (round-robin) and the priority to *30* for process *1234*{colon}::
____
____
Reset priorities to default for a process{colon}::
____
-*chrt --pid -o 0* _PID_
+*chrt --pid -o 0* _PID_[:_inode_]
____
Set a custom slice of 1 ms for a *SCHED_OTHER* task (priority is optional for policies other than *SCHED_FIFO* and *SCHED_RR*){colon}::
____
-*chrt --pid -o -T 1000000* _PID_
+*chrt --pid -o -T 1000000* _PID_[:_inode_]
____
See *sched*(7) for a detailed discussion of the different scheduler classes and how they interact.
*nice*(1),
*renice*(1),
*taskset*(1),
-*sched*(7)
+*sched*(7),
+*getino*(1)
See *sched_setscheduler*(2) for a description of the Linux scheduling scheme.
#include "strutils.h"
#include "procfs.h"
#include "sched_attr.h"
-
+#include "pidutils.h"
+#include "pidfd-utils.h"
/* control struct */
struct chrt_ctl {
- pid_t pid;
- int policy; /* SCHED_* */
- int priority;
+ pid_t pid;
+ uint64_t pidfd_ino;
+ int pidfd;
+ int policy; /* SCHED_* */
+ int priority;
uint64_t runtime; /* --sched-* options */
uint64_t deadline;
unsigned int all_tasks : 1, /* all threads of the PID */
reset_on_fork : 1, /* SCHED_RESET_ON_FORK or SCHED_FLAG_RESET_ON_FORK */
altered : 1, /* sched_set**() used */
- verbose : 1; /* verbose output */
+ verbose : 1, /* verbose output */
+ parse_pid : 1; /* expect a PID as last command line argument */
};
static void __attribute__((__noreturn__)) usage(void)
{
FILE *out = stdout;
+ char *pid_arg = NULL;
+
+#ifdef USE_PIDFD_INO_SUPPORT
+ pid_arg = "PID[:inode]";
+#else
+ pid_arg = "PID";
+#endif
+
fputs(_("Show or change the real-time scheduling attributes of a process.\n"), out);
fputs(USAGE_SEPARATOR, out);
- fputs(_("Set policy:\n"
+ fprintf(out, _("Set policy:\n"
" chrt [options] [<priority>] <command> [<argument>...]\n"
- " chrt --pid <policy-option> [options] [<priority>] <PID>\n"), out);
+ " chrt --pid <policy-option> [options] [<priority>] <%s>\n"), pid_arg);
fputs(USAGE_SEPARATOR, out);
- fputs(_("Get policy:\n"
- " chrt --pid <PID>\n"), out);
+ fprintf(out, _("Get policy:\n"
+ " chrt --pid <%s>\n"), pid_arg);
fputs(USAGE_SEPARATOR, out);
fputs(_("Policy options:\n"), out);
int main(int argc, char **argv)
{
- struct chrt_ctl _ctl = { .pid = -1, .policy = SCHED_RR }, *ctl = &_ctl;
+ struct chrt_ctl _ctl = {
+ .parse_pid = 0,
+ .pid = 0,
+ .pidfd_ino = 0,
+ .pidfd = -1,
+ .policy = SCHED_RR
+ }, *ctl = &_ctl;
int c;
bool policy_given = false, need_prio = false;
policy_given = true;
break;
case 'p':
- ctl->pid = 0; /* indicate that a PID is expected */
+ ctl->parse_pid = 1; /* indicate that a PID is expected */
break;
case 'r':
ctl->policy = SCHED_RR;
}
/* If option --pid was given, parse the very last argument as a PID. */
- if (ctl->pid == 0) {
+ if (ctl->parse_pid) {
errno = 0;
- /* strtopid_or_err() is not suitable here, as 0 can be passed. */
- ctl->pid = strtos32_or_err(argv[argc - 1], _("invalid PID argument"));
+ ul_parse_pid_str_or_err(argv[argc - 1], &ctl->pid, &ctl->pidfd_ino, UL_PID_ZERO);
+ if (ctl->pidfd_ino > 0)
+ ctl->pidfd = ul_get_valid_pidfd_or_err(ctl->pid, ctl->pidfd_ino);
/* If no policy nor priority was given, show current settings. */
if (!policy_given && argc - optind == 1) {
if (ctl->policy == SCHED_RR)
need_prio = true;
- if (ctl->pid > -1 && ctl->verbose)
+ if (ctl->parse_pid && ctl->verbose)
show_sched_info(ctl);
- if (argc - optind > 1 && (ctl->pid > -1 || isdigit_string(argv[optind]))) {
+ if (argc - optind > 1 && (ctl->parse_pid || isdigit_string(argv[optind]))) {
errno = 0;
ctl->priority = strtos32_or_err(argv[optind], _("invalid priority argument"));
-
optind++;
- } else if (need_prio && ctl->pid == -1 && isdigit_string(argv[optind]))
+ } else if (need_prio && !ctl->parse_pid && isdigit_string(argv[optind])) {
errx(EXIT_FAILURE, _("no command or priority specified"));
- else if (need_prio)
+ } else if (need_prio) {
errx(EXIT_FAILURE, _("policy %s requires a priority argument"),
get_policy_name(ctl->policy));
- else
+ } else {
ctl->priority = 0;
+ }
if (ctl->runtime && !supports_runtime_param(ctl->policy))
errx(EXIT_FAILURE, _("--sched-runtime option is supported for %s"),
if (ctl->deadline || ctl->period)
errx(EXIT_FAILURE, _("SCHED_DEADLINE is unsupported"));
#endif
- if (ctl->pid == -1)
- ctl->pid = 0;
if (ctl->priority < sched_get_priority_min(ctl->policy) ||
- sched_get_priority_max(ctl->policy) < ctl->priority)
+ sched_get_priority_max(ctl->policy) < ctl->priority)
errx(EXIT_FAILURE,
- _("unsupported priority value for the policy: %d: see --max for valid range"),
- ctl->priority);
+ _("unsupported priority value for the policy: %d: see --max for valid range"),
+ ctl->priority);
set_sched(ctl);
if (ctl->verbose)
show_sched_info(ctl);
- if (!ctl->pid) {
+ if (ctl->pidfd >= 0)
+ close(ctl->pidfd);
+
+ if (!ctl->parse_pid) {
argv += optind;
if (argv[0] && strcmp(argv[0], "--") == 0)