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#define FOR_uclampset
26#include "toys.h"
27
28GLOBALS(
29 long M, m, p;
30)
31
32
33#ifndef SCHED_FLAG_RESET_ON_FORK
34#define SCHED_FLAG_RESET_ON_FORK 0x01
35#define SCHED_FLAG_KEEP_POLICY 0x08
36#define SCHED_FLAG_KEEP_PARAMS 0x10
37#define SCHED_FLAG_UTIL_CLAMP_MIN 0x20
38#define SCHED_FLAG_UTIL_CLAMP_MAX 0x40
39#endif
40
41static void do_uclampset(pid_t pid)
42{
43 unsigned *sa = (void *)toybuf;
44 char *comm, buf[32];
45
46 if (FLAG(R)|FLAG(m)|FLAG(M)) {
47 if (syscall(__NR_sched_setattr, pid, sa, 0))
48 perror_exit("sched_setattr for pid %d", pid);
49 } else {
50 sprintf(buf, "/proc/%u/comm", pid);
51 comm = chomp(xreadfile(buf, 0, 0));
52 if (syscall(__NR_sched_getattr, pid, sa, *sa, 0))
53 perror_exit("sched_getattr for pid %d", pid);
54 printf("%s (%d) util_clamp: min: %u max: %u\n", comm, pid, sa[12], sa[13]);
55 free(comm);
56 }
57}
58
59static int task_callback(struct dirtree *new)
60{
61 if (!new->parent) return DIRTREE_RECURSE;
62 if (isdigit(*new->name)) do_uclampset(atoi(new->name));
63
64 return 0;
65}
66
67void uclampset_main(void)
68{
69 unsigned *sa = (void *)toybuf;
70 long long *flags = (void *)(sa+2);
71 char buf[32];
72
73 sa[0] = 14*4;
74 sa[12] = TT.m;
75 sa[13] = TT.M;
76 *flags = SCHED_FLAG_KEEP_POLICY | SCHED_FLAG_KEEP_PARAMS;
77 if (FLAG(R)) *flags |= SCHED_FLAG_RESET_ON_FORK;
78 if (FLAG(m)) *flags |= SCHED_FLAG_UTIL_CLAMP_MIN;
79 if (FLAG(M)) *flags |= SCHED_FLAG_UTIL_CLAMP_MAX;
80
81 if (!FLAG(p)) {
82 if (toys.optc < 1) error_exit("Need -p PID or CMD [ARG...]");
83 do_uclampset(getpid());
84 xexec(toys.optargs);
85 } else if (FLAG(a)) {
86 sprintf(buf, "/proc/%lu/task", TT.p);
87 dirtree_read(buf, task_callback);
88 } else do_uclampset(TT.p);
89}
90