diff options
-rw-r--r-- | lib/lib.c | 10 | ||||
-rw-r--r-- | lib/lib.h | 1 | ||||
-rw-r--r-- | lib/portability.h | 10 | ||||
-rw-r--r-- | toys/pending/chrt.c | 91 |
4 files changed, 58 insertions, 54 deletions
@@ -512,6 +512,16 @@ void msleep(long miliseconds) nanosleep(&ts, &ts); } +// return 1<<x of highest bit set +int highest_bit(unsigned long l) +{ + int i; + + for (i = 0; l; i++) l >>= 1; + + return i-1; +} + // Inefficient, but deals with unaligned access int64_t peek_le(void *ptr, unsigned size) { @@ -192,6 +192,7 @@ struct string_list **splitpath(char *path, struct string_list **list); char *readfileat(int dirfd, char *name, char *buf, off_t *len); char *readfile(char *name, char *buf, off_t len); void msleep(long miliseconds); +int highest_bit(unsigned long l); int64_t peek_le(void *ptr, unsigned size); int64_t peek_be(void *ptr, unsigned size); int64_t peek(void *ptr, unsigned size); diff --git a/lib/portability.h b/lib/portability.h index 01c77c67..e62de139 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -45,9 +45,13 @@ #define RLIMIT_RTTIME 15 #endif +// Introduced in Linux 3.1 #ifndef SEEK_DATA #define SEEK_DATA 3 #endif +#ifndef SEEK_HOLE +#define SEEK_HOLE 4 +#endif // We don't define GNU_dammit because we're not part of the gnu project, and // don't want to get any FSF on us. Unfortunately glibc (gnu libc) @@ -199,18 +203,18 @@ static inline void endutxent(void) {;} #ifndef O_NOFOLLOW #define O_NOFOLLOW 0 #endif - #ifndef O_NOATIME #define O_NOATIME 01000000 #endif - #ifndef O_CLOEXEC #define O_CLOEXEC 02000000 #endif - #ifndef O_PATH #define O_PATH 010000000 #endif +#ifndef SCHED_RESET_ON_FORK +#define SCHED_RESET_ON_FORK (1<<30) +#endif // Glibc won't give you linux-kernel constants unless you say "no, a BUD lite" // even though linux has nothing to do with the FSF and never has. diff --git a/toys/pending/chrt.c b/toys/pending/chrt.c index d2b73a42..01076b93 100644 --- a/toys/pending/chrt.c +++ b/toys/pending/chrt.c @@ -1,92 +1,81 @@ /* chrt.c - Get/set real-time (scheduling) attributes * * Copyright 2016 The Android Open Source Project + * + * Note: -ibrfo flags sorted to match SCHED positions for highest_bit() -USE_CHRT(NEWTOY(chrt, "mp#bfiorR[!bfior]", TOYFLAG_USR|TOYFLAG_SBIN)) +USE_CHRT(NEWTOY(chrt, "^mp#<0iRbrfo[!ibrfo]", TOYFLAG_USR|TOYFLAG_SBIN)) config CHRT bool "chrt" default n help - usage: chrt [-m] [-p PID] [POLICY PRIO] [COMMAND [ARGS...]] + usage: chrt [-Rmofrbi] {-p PID [PRIORITY] | [PRIORITY COMMAND...]} - Get/set a process' real-time (scheduling) attributes. + Get/set a process' real-time scheduling policy and priority. - -p Apply to given pid + -p Set/query given pid (instead of running COMMAND) -R Set SCHED_RESET_ON_FORK -m Show min/max priorities available - Policies: - -b SCHED_BATCH -f SCHED_FIFO -i SCHED_IDLE - -o SCHED_OTHER -r SCHED_RR + Set policy (default -r): + + -o SCHED_OTHER -f SCHED_FIFO -r SCHED_RR + -b SCHED_BATCH -i SCHED_IDLE */ #define FOR_chrt #include "toys.h" -#include <linux/sched.h> - GLOBALS( long pid; ) -static char *policy_name(int policy) { - char *policy_names[] = { "SCHED_OTHER", "SCHED_FIFO", "SCHED_RR", - "SCHED_BATCH", "4", "SCHED_IDLE", "SCHED_DEADLINE" }; - - return policy < ARRAY_LEN(policy_names) ? policy_names[policy] : "???"; -} +char *polnames[] = { + "SCHED_OTHER", "SCHED_FIFO", "SCHED_RR", "SCHED_BATCH", 0, "SCHED_IDLE", + "SCHED_DEADLINE" +}; void chrt_main(void) { - int policy = SCHED_RR; - struct sched_param p; + int pol, pri; // Show min/maxes? if (toys.optflags&FLAG_m) { - for (policy = SCHED_OTHER; policy <= SCHED_IDLE; ++policy) - if (policy != 4) // There's an unused hole in the priorities. - printf("%s min/max priority\t: %d/%d\n", policy_name(policy), - sched_get_priority_min(policy), sched_get_priority_max(policy)); + for (pol = 0; pol<ARRAY_LEN(polnames); pol++) if (polnames[pol]) + printf("%s min/max priority\t: %d/%d\n", polnames[pol], + sched_get_priority_min(pol), sched_get_priority_max(pol)); + return; } - // If we have a pid but no command or policy, we're just querying. - if (TT.pid && !*(toys.optargs+1) && - !(toys.optflags&(FLAG_b|FLAG_f|FLAG_i|FLAG_o|FLAG_r))) { - policy = sched_getscheduler(TT.pid); - if (policy == -1) perror_exit("sched_getscheduler"); - policy &= ~SCHED_RESET_ON_FORK; - printf("pid %ld's current scheduling policy: %s\n", - TT.pid, policy_name(policy)); + // Query when -p without priority. + if (toys.optflags==FLAG_p && !*toys.optargs) { + char *s = "???", *R = ""; + + if (-1==(pol = sched_getscheduler(TT.pid))) perror_exit("pid %ld", TT.pid); + if (pol & SCHED_RESET_ON_FORK) R = "|SCHED_RESET_ON_FORK"; + if ((pol &= ~SCHED_RESET_ON_FORK)<ARRAY_LEN(polnames)) s = polnames[pol]; + printf("pid %ld's current scheduling policy: %s%s\n", TT.pid, s, R); - if (sched_getparam(TT.pid, &p)) perror_exit("sched_getparam"); - printf("pid %ld's current scheduling priority: %d\n", - TT.pid, p.sched_priority); + if (sched_getparam(TT.pid, (void *)&pri)) perror_exit("sched_getparam"); + printf("pid %ld's current scheduling priority: %d\n", TT.pid, pri); return; } - // Did we get a meaningful combination of arguments? - if (!*toys.optargs) help_exit("missing priority"); - if (TT.pid && *(toys.optargs+1)) help_exit("-p and command"); - if (!TT.pid && !*(toys.optargs+1)) help_exit("missing command"); - - // Translate into policy and priority. - if (toys.optflags&FLAG_b) policy = SCHED_BATCH; - else if (toys.optflags&FLAG_f) policy = SCHED_FIFO; - else if (toys.optflags&FLAG_i) policy = SCHED_IDLE; - else if (toys.optflags&FLAG_o) policy = SCHED_OTHER; + if (!*toys.optargs) help_exit("no PRIORITY"); + if (!toys.optargs[1] == !(toys.optflags&FLAG_p)) + help_exit("need 1 of -p or COMMAND"); - if (toys.optflags&FLAG_R) policy |= SCHED_RESET_ON_FORK; + // Set policy and priority + if (-1==(pol = highest_bit(toys.optflags&0x2f))) pol = SCHED_RR; + pri = atolx_range(*toys.optargs, sched_get_priority_min(pol), + sched_get_priority_max(pol)); + if (toys.optflags&FLAG_R) pol |= SCHED_RESET_ON_FORK; - p.sched_priority = atolx_range(*toys.optargs, sched_get_priority_min(policy), - sched_get_priority_max(policy)); + if (sched_setscheduler(TT.pid, pol, (void *)&pri)) + perror_exit("sched_setscheduler"); - if (sched_setscheduler(TT.pid, policy, &p)) perror_exit("sched_setscheduler"); - - if (*(toys.optargs+1)) { - toys.stacktop = 0; - xexec(++toys.optargs); - } + if (*(toys.optargs+1)) xexec(++toys.optargs); } |