From ee69001bba01bf731346da1eb479ffa1c4b91d80 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 11 Dec 2021 13:18:21 -0600 Subject: [PATCH] Cleanup uclampset. --- toys/pending/uclampset.c | 103 ++++++++++++++------------------------- 1 file changed, 37 insertions(+), 66 deletions(-) diff --git a/toys/pending/uclampset.c b/toys/pending/uclampset.c index e59f0d33..2f8b1e1e 100644 --- a/toys/pending/uclampset.c +++ b/toys/pending/uclampset.c @@ -1,24 +1,25 @@ -/* uclampset.c - Set/get processes' utilization clamping attributes. +/* uclampset.c - The quota version of "nice". * * Copyright 2021 The Android Open Source Project * - * No standard. See https://man7.org/linux/man-pages/man1/uclampset.1.html + * See https://man7.org/linux/man-pages/man1/uclampset.1.html -USE_TASKSET(NEWTOY(uclampset, "p#am#M#R", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT)) +USE_UCLAMPSET(NEWTOY(uclampset, "p#am#<-1>1024M#<-1>1024R", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT)) config UCLAMPSET bool "uclampset" - default y + default n help - usage: uclampset [-p PID] [-m MIN] [-M MAX] [CMD [ARG...]] + usage: uclampset [-m MIN] [-M MAX] {-p PID | COMMAND...} - Set/get utilization clamping attributes for new or existing processes. + Set or query process utilization limits ranging from 0 to 1024, or -1 to + reset to system default. With no arguments, prints current values. - -a Apply to all the tasks/threads for the given PID - -m MIN Set the minimum - -M MAX Set the maximum - -p PID Apply to PID rather than launching a command - -R Set SCHED_FLAG_RESET_ON_FORK + -m MIN Reserve at least this much CPU utilization for task + -M MAX Limit task to at most this much CPU utilization + -p PID Apply to PID rather than new COMMAND + -R Reset child processes to default values on fork + -a Apply to all threads for the given PID */ #define FOR_uclampset @@ -26,53 +27,32 @@ config UCLAMPSET GLOBALS( long M, m, p; - - int set; ) +// Added to 5.3 kernel (commit a509a7cd7974): too new to rely on headers #include -// The uclamp flags and fields in struct sched_attr were added to the kernel -// in 2019, so we can't rely on the headers yet. +#ifndef SCHED_FLAG_RESET_ON_FORK #define SCHED_FLAG_RESET_ON_FORK 0x01 #define SCHED_FLAG_KEEP_POLICY 0x08 #define SCHED_FLAG_KEEP_PARAMS 0x10 #define SCHED_FLAG_UTIL_CLAMP_MIN 0x20 #define SCHED_FLAG_UTIL_CLAMP_MAX 0x40 -#define sched_getattr(pid, attr) \ - syscall(__NR_sched_getattr, pid, attr, sizeof(struct sched_attr_v2), 0) -#define sched_setattr(pid, attr, flags) \ - syscall(__NR_sched_setattr, pid, attr, flags) -struct sched_attr_v2 { - unsigned size; - unsigned sched_policy; - unsigned long long sched_flags; - int sched_nice; - unsigned sched_priority; - unsigned long long sched_runtime; - unsigned long long sched_deadline; - unsigned long long sched_period; - // These fields aren't in v1 of the struct. - unsigned sched_util_min; - unsigned sched_util_max; -}; +#endif static void do_uclampset(pid_t pid) { - struct sched_attr_v2 *sa = (struct sched_attr_v2 *)toybuf; + unsigned *sa = (void *)toybuf; // sa[12] is min, sa[13] is max + char *comm, buf[32]; - if (TT.set) { - if (sched_setattr(pid, sa, 0)) perror_exit("sched_setattr for pid %d", pid); + if (FLAG(R)|FLAG(m)|FLAG(M)) { + if (syscall(__NR_sched_setattr, pid, sa, 0)) + perror_exit("sched_setattr for pid %d", pid); } else { - char path[33], *comm; - size_t len; - - if (sched_getattr(pid, sa)) perror_exit("sched_getattr for pid %d", pid); - sprintf(path, "/proc/%u/comm", pid); - comm = xreadfile(path, 0, 0); - len = strlen(comm); - if (comm[len-1] == '\n') comm[len-1] = 0; - printf("%s (%d) util_clamp: min: %u max: %u\n", comm, pid, - sa->sched_util_min, sa->sched_util_max); + sprintf(buf, "/proc/%u/comm", pid); + comm = chomp(xreadfile(buf, 0, 0)); + if (syscall(__NR_sched_getattr, pid, sa, *sa, 0)) + perror_exit("sched_getattr for pid %d", pid); + printf("%s (%d) util_clamp: min: %u max: %u\n", comm, pid, sa[12], sa[13]); free(comm); } } @@ -87,33 +67,24 @@ static int task_callback(struct dirtree *new) void uclampset_main(void) { - struct sched_attr_v2* sa = (struct sched_attr_v2 *)toybuf; - - memset(sa, 0, sizeof(*sa)); - sa->size = sizeof(*sa); - sa->sched_flags = SCHED_FLAG_KEEP_POLICY | SCHED_FLAG_KEEP_PARAMS; - if (FLAG(R)) { - sa->sched_flags |= SCHED_FLAG_RESET_ON_FORK; - TT.set = 1; - } - if (FLAG(m)) { - sa->sched_flags |= SCHED_FLAG_UTIL_CLAMP_MIN; - sa->sched_util_min = TT.m; - TT.set = 1; - } - if (FLAG(M)) { - sa->sched_flags |= SCHED_FLAG_UTIL_CLAMP_MAX; - sa->sched_util_max = TT.M; - TT.set = 1; - } + unsigned *sa = (void *)toybuf; + long long *flags = (void *)(sa+2); + char buf[32]; + + sa[0] = 14*4; // size + sa[12] = TT.m; + sa[13] = TT.M; + *flags = SCHED_FLAG_KEEP_POLICY | SCHED_FLAG_KEEP_PARAMS; + if (FLAG(R)) *flags |= SCHED_FLAG_RESET_ON_FORK; + if (FLAG(m)) *flags |= SCHED_FLAG_UTIL_CLAMP_MIN; + if (FLAG(M)) *flags |= SCHED_FLAG_UTIL_CLAMP_MAX; if (!FLAG(p)) { if (toys.optc < 1) error_exit("Need -p PID or CMD [ARG...]"); do_uclampset(getpid()); xexec(toys.optargs); } else if (FLAG(a)) { - char buf[33]; - sprintf(buf, "/proc/%ld/task/", TT.p); + sprintf(buf, "/proc/%lu/task", TT.p); dirtree_read(buf, task_callback); } else do_uclampset(TT.p); } -- 2.39.2