1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36#include <sched.h>
37#include "libbb.h"
38#ifndef SCHED_IDLE
39# define SCHED_IDLE 5
40#endif
41
42
43
44
45
46#if defined(__linux__) && defined(__NEED_fsblkcnt_t) && defined(__NEED_fsfilcnt_t)
47# define LIBC_IS_MUSL 1
48# include <sys/syscall.h>
49#else
50# define LIBC_IS_MUSL 0
51#endif
52
53static const char *policy_name(int pol)
54{
55 if (pol > 6)
56 return utoa(pol);
57 return nth_string(
58 "OTHER" "\0"
59 "FIFO" "\0"
60 "RR" "\0"
61 "BATCH" "\0"
62 "ISO" "\0"
63 "IDLE" "\0"
64 "DEADLINE",
65 pol
66 );
67}
68
69static void show_min_max(int pol)
70{
71 const char *fmt = "SCHED_%s min/max priority\t: %u/%u\n";
72 int max, min;
73
74 max = sched_get_priority_max(pol);
75 min = sched_get_priority_min(pol);
76 if ((max|min) < 0)
77 fmt = "SCHED_%s not supported\n";
78 printf(fmt, policy_name(pol), min, max);
79}
80
81#define OPT_m (1<<0)
82#define OPT_p (1<<1)
83#define OPT_r (1<<2)
84#define OPT_f (1<<3)
85#define OPT_o (1<<4)
86#define OPT_b (1<<5)
87#define OPT_i (1<<6)
88
89int chrt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
90int chrt_main(int argc UNUSED_PARAM, char **argv)
91{
92 pid_t pid = 0;
93 unsigned opt;
94 struct sched_param sp;
95 char *pid_str;
96 char *priority = NULL;
97 const char *current_new;
98 int policy = SCHED_RR;
99 int ret;
100
101 opt = getopt32(argv, "^"
102 "+" "mprfobi"
103 "\0"
104
105 "r--fobi:f--robi:o--rfbi:b--rfoi:i--rfob"
106 );
107 if (opt & OPT_m) {
108 show_min_max(SCHED_OTHER);
109 show_min_max(SCHED_FIFO);
110 show_min_max(SCHED_RR);
111 show_min_max(SCHED_BATCH);
112 show_min_max(SCHED_IDLE);
113 fflush_stdout_and_exit(EXIT_SUCCESS);
114 }
115
116
117 if (opt & OPT_f)
118 policy = SCHED_FIFO;
119 if (opt & OPT_o)
120 policy = SCHED_OTHER;
121 if (opt & OPT_b)
122 policy = SCHED_BATCH;
123 if (opt & OPT_i)
124 policy = SCHED_IDLE;
125
126 argv += optind;
127 if (!argv[0])
128 bb_show_usage();
129 if (opt & OPT_p) {
130 pid_str = *argv++;
131 if (*argv) {
132 priority = pid_str;
133 pid_str = *argv;
134 }
135
136 pid = xatoul_range(pid_str, 1, ((unsigned)(pid_t)ULONG_MAX) >> 1);
137 } else {
138 priority = *argv++;
139 if (!*argv)
140 bb_show_usage();
141 }
142
143 current_new = "current\0new";
144 if (opt & OPT_p) {
145 int pol;
146 print_rt_info:
147#if LIBC_IS_MUSL
148
149
150
151
152 pol = syscall(SYS_sched_getscheduler, pid);
153#else
154 pol = sched_getscheduler(pid);
155#endif
156 if (pol < 0)
157 bb_perror_msg_and_die("can't %cet pid %u's policy", 'g', (int)pid);
158#ifdef SCHED_RESET_ON_FORK
159
160
161
162
163
164
165
166
167 pol &= ~SCHED_RESET_ON_FORK;
168#endif
169 printf("pid %u's %s scheduling policy: SCHED_%s\n",
170 pid, current_new, policy_name(pol)
171 );
172#if LIBC_IS_MUSL
173 ret = syscall(SYS_sched_getparam, pid, &sp);
174#else
175 ret = sched_getparam(pid, &sp);
176#endif
177 if (ret)
178 bb_perror_msg_and_die("can't get pid %u's attributes", (int)pid);
179 printf("pid %u's %s scheduling priority: %d\n",
180 (int)pid, current_new, sp.sched_priority
181 );
182 if (!*argv) {
183
184
185
186 return EXIT_SUCCESS;
187 }
188 *argv = NULL;
189 current_new += 8;
190 }
191
192 sp.sched_priority = xstrtou_range(priority, 0,
193 sched_get_priority_min(policy), sched_get_priority_max(policy)
194 );
195
196#if LIBC_IS_MUSL
197 ret = syscall(SYS_sched_setscheduler, pid, policy, &sp);
198#else
199 ret = sched_setscheduler(pid, policy, &sp);
200#endif
201 if (ret)
202 bb_perror_msg_and_die("can't %cet pid %u's policy", 's', (int)pid);
203
204 if (!argv[0])
205 goto print_rt_info;
206
207 BB_EXECVP_or_die(argv);
208}
209