xref: /aosp_15_r20/external/toybox/toys/other/chrt.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1 /* chrt.c - Get/set real-time (scheduling) attributes
2  *
3  * Copyright 2016 The Android Open Source Project
4  *
5  * Note: -ibrfo flags sorted to match SCHED positions for highest_bit()
6 
7 USE_CHRT(NEWTOY(chrt, "^mp#<0iRbrfo[!ibrfo]", TOYFLAG_USR|TOYFLAG_BIN))
8 
9 config CHRT
10   bool "chrt"
11   default y
12   help
13     usage: chrt [-Rmofrbi] {-p PID [PRIORITY] | [PRIORITY COMMAND...]}
14 
15     Get/set a process' real-time scheduling policy and priority.
16 
17     -p	Set/query given pid (instead of running COMMAND)
18     -R	Set SCHED_RESET_ON_FORK
19     -m	Show min/max priorities available
20 
21     Set policy (default -r):
22 
23       -o  SCHED_OTHER    -f  SCHED_FIFO    -r  SCHED_RR
24       -b  SCHED_BATCH    -i  SCHED_IDLE
25 */
26 
27 #define FOR_chrt
28 #include "toys.h"
29 
30 GLOBALS(
31   long p;
32 )
33 
34 #ifndef _POSIX_PRIORITY_SCHEDULING
35 // musl-libc intentionally broke sched_get_priority_min() and friends in
36 // commit 1e21e78bf7a5 because its maintainer didn't like those Linux
37 // system calls, so work around it here.
38 #define sched_get_priority_min(policy) \
39   (int)syscall(SYS_sched_get_priority_min, (int)policy)
40 #define sched_get_priority_max(policy) \
41   (int)syscall(SYS_sched_get_priority_max, (int)policy)
42 #define sched_getparam(pid, param) \
43   syscall(SYS_sched_getparam, (pid_t)pid, (void *)param)
44 #define sched_getscheduler(pid) \
45   syscall(SYS_sched_getscheduler, (pid_t)pid)
46 #define sched_setscheduler(pid, scheduler, param) \
47   syscall(SYS_sched_setscheduler, (pid_t)pid, (int)scheduler, (void *)param)
48 #endif
49 
50 static char *polnames[] = {
51   "SCHED_OTHER", "SCHED_FIFO", "SCHED_RR", "SCHED_BATCH", 0, "SCHED_IDLE",
52   "SCHED_DEADLINE"
53 };
54 
chrt_main(void)55 void chrt_main(void)
56 {
57   int pol, pri;
58 
59   // Show min/maxes?
60   if (FLAG(m)) {
61     for (pol = 0; pol<ARRAY_LEN(polnames); pol++) if (polnames[pol])
62       printf("%s min/max priority\t: %d/%d\n", polnames[pol],
63         sched_get_priority_min(pol), sched_get_priority_max(pol));
64 
65     return;
66   }
67 
68   // Query when -p without priority.
69   if (toys.optflags==FLAG_p && !*toys.optargs) {
70     char *s = "???", *R = "";
71 
72     if (-1==(pol = sched_getscheduler(TT.p))) perror_exit("pid %ld", TT.p);
73     if (pol & SCHED_RESET_ON_FORK) R = "|SCHED_RESET_ON_FORK";
74     if ((pol &= ~SCHED_RESET_ON_FORK)<ARRAY_LEN(polnames)) s = polnames[pol];
75     printf("pid %ld's current scheduling policy: %s%s\n", TT.p, s, R);
76 
77     if (sched_getparam(TT.p, (void *)&pri)) perror_exit("sched_getparam");
78     printf("pid %ld's current scheduling priority: %d\n", TT.p, pri);
79 
80     return;
81   }
82 
83   if (!*toys.optargs) help_exit("no PRIORITY");
84   if (!toys.optargs[1] == !FLAG(p)) help_exit("need 1 of -p or COMMAND");
85 
86   // Set policy and priority
87   if (-1==(pol = highest_bit(toys.optflags&(FLAG_p-1)))) pol = SCHED_RR;
88   pri = atolx_range(*toys.optargs, sched_get_priority_min(pol),
89     sched_get_priority_max(pol));
90   if (FLAG(R)) pol |= SCHED_RESET_ON_FORK;
91 
92   if (sched_setscheduler(TT.p, pol, (void *)&pri))
93     perror_exit("sched_setscheduler");
94 
95   if (*(toys.optargs+1)) xexec(toys.optargs+1);
96 }
97