1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- /* uclampset.c - The quota version of "nice".
- *
- * Copyright 2021 The Android Open Source Project
- *
- * See https://man7.org/linux/man-pages/man1/uclampset.1.html
- USE_UCLAMPSET(NEWTOY(uclampset, "p#am#<-1>1024M#<-1>1024R", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
- config UCLAMPSET
- bool "uclampset"
- default y
- help
- usage: uclampset [-m MIN] [-M MAX] {-p PID | COMMAND...}
- Set or query process utilization limits ranging from 0 to 1024, or -1 to
- reset to system default. With no arguments, prints current values.
- -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
- #include "toys.h"
- GLOBALS(
- long M, m, p;
- )
- // Added to 5.3 kernel (commit a509a7cd7974): too new to rely on headers
- #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
- #endif
- static void do_uclampset(pid_t pid)
- {
- unsigned *sa = (void *)toybuf; // sa[12] is min, sa[13] is max
- char *comm, buf[32];
- if (FLAG(R)|FLAG(m)|FLAG(M)) {
- if (syscall(__NR_sched_setattr, pid, sa, 0))
- perror_exit("sched_setattr for pid %d", pid);
- } else {
- 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);
- }
- }
- static int task_callback(struct dirtree *new)
- {
- if (!new->parent) return DIRTREE_RECURSE;
- if (isdigit(*new->name)) do_uclampset(atoi(new->name));
- return 0;
- }
- void uclampset_main(void)
- {
- 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)) {
- sprintf(buf, "/proc/%lu/task", TT.p);
- dirtree_read(buf, task_callback);
- } else do_uclampset(TT.p);
- }
|