busybox/miscutils/chrt.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * chrt - manipulate real-time attributes of a process
   4 * Copyright (c) 2006-2007 Bernhard Reutner-Fischer
   5 *
   6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
   7 */
   8
   9//usage:#define chrt_trivial_usage
  10//usage:       "[-prfom] [PRIO] [PID | PROG ARGS]"
  11//usage:#define chrt_full_usage "\n\n"
  12//usage:       "Change scheduling priority and class for a process\n"
  13//usage:     "\n        -p      Operate on PID"
  14//usage:     "\n        -r      Set SCHED_RR class"
  15//usage:     "\n        -f      Set SCHED_FIFO class"
  16//usage:     "\n        -o      Set SCHED_OTHER class"
  17//usage:     "\n        -m      Show min/max priorities"
  18//usage:
  19//usage:#define chrt_example_usage
  20//usage:       "$ chrt -r 4 sleep 900; x=$!\n"
  21//usage:       "$ chrt -f -p 3 $x\n"
  22//usage:       "You need CAP_SYS_NICE privileges to set scheduling attributes of a process"
  23
  24#include <sched.h>
  25#include "libbb.h"
  26#ifndef _POSIX_PRIORITY_SCHEDULING
  27#warning your system may be foobared
  28#endif
  29
  30static const struct {
  31        int policy;
  32        char name[sizeof("SCHED_OTHER")];
  33} policies[] = {
  34        {SCHED_OTHER, "SCHED_OTHER"},
  35        {SCHED_FIFO, "SCHED_FIFO"},
  36        {SCHED_RR, "SCHED_RR"}
  37};
  38
  39//TODO: add
  40// -b, SCHED_BATCH
  41// -i, SCHED_IDLE
  42
  43static void show_min_max(int pol)
  44{
  45        const char *fmt = "%s min/max priority\t: %u/%u\n";
  46        int max, min;
  47
  48        max = sched_get_priority_max(pol);
  49        min = sched_get_priority_min(pol);
  50        if ((max|min) < 0)
  51                fmt = "%s not supported\n";
  52        printf(fmt, policies[pol].name, min, max);
  53}
  54
  55#define OPT_m (1<<0)
  56#define OPT_p (1<<1)
  57#define OPT_r (1<<2)
  58#define OPT_f (1<<3)
  59#define OPT_o (1<<4)
  60
  61int chrt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  62int chrt_main(int argc UNUSED_PARAM, char **argv)
  63{
  64        pid_t pid = 0;
  65        unsigned opt;
  66        struct sched_param sp;
  67        char *pid_str;
  68        char *priority = priority; /* for compiler */
  69        const char *current_new;
  70        int policy = SCHED_RR;
  71
  72        /* only one policy accepted */
  73        opt_complementary = "r--fo:f--ro:o--rf";
  74        opt = getopt32(argv, "+mprfo");
  75        if (opt & OPT_m) { /* print min/max and exit */
  76                show_min_max(SCHED_FIFO);
  77                show_min_max(SCHED_RR);
  78                show_min_max(SCHED_OTHER);
  79                fflush_stdout_and_exit(EXIT_SUCCESS);
  80        }
  81        if (opt & OPT_r)
  82                policy = SCHED_RR;
  83        if (opt & OPT_f)
  84                policy = SCHED_FIFO;
  85        if (opt & OPT_o)
  86                policy = SCHED_OTHER;
  87
  88        argv += optind;
  89        if (!argv[0])
  90                bb_show_usage();
  91        if (opt & OPT_p) {
  92                pid_str = *argv++;
  93                if (*argv) { /* "-p <priority> <pid> [...]" */
  94                        priority = pid_str;
  95                        pid_str = *argv;
  96                }
  97                /* else "-p <pid>", and *argv == NULL */
  98                pid = xatoul_range(pid_str, 1, ((unsigned)(pid_t)ULONG_MAX) >> 1);
  99        } else {
 100                priority = *argv++;
 101                if (!*argv)
 102                        bb_show_usage();
 103        }
 104
 105        current_new = "current\0new";
 106        if (opt & OPT_p) {
 107                int pol;
 108 print_rt_info:
 109                pol = sched_getscheduler(pid);
 110                if (pol < 0)
 111                        bb_perror_msg_and_die("can't %cet pid %d's policy", 'g', (int)pid);
 112                printf("pid %d's %s scheduling policy: %s\n",
 113                                pid, current_new, policies[pol].name);
 114                if (sched_getparam(pid, &sp))
 115                        bb_perror_msg_and_die("can't get pid %d's attributes", (int)pid);
 116                printf("pid %d's %s scheduling priority: %d\n",
 117                                (int)pid, current_new, sp.sched_priority);
 118                if (!*argv) {
 119                        /* Either it was just "-p <pid>",
 120                         * or it was "-p <priority> <pid>" and we came here
 121                         * for the second time (see goto below) */
 122                        return EXIT_SUCCESS;
 123                }
 124                *argv = NULL;
 125                current_new += 8;
 126        }
 127
 128        /* from the manpage of sched_getscheduler:
 129        [...] sched_priority can have a value in the range 0 to 99.
 130        [...] SCHED_OTHER or SCHED_BATCH must be assigned static priority 0.
 131        [...] SCHED_FIFO or SCHED_RR can have static priority in 1..99 range.
 132        */
 133        sp.sched_priority = xstrtou_range(priority, 0, policy != SCHED_OTHER ? 1 : 0, 99);
 134
 135        if (sched_setscheduler(pid, policy, &sp) < 0)
 136                bb_perror_msg_and_die("can't %cet pid %d's policy", 's', (int)pid);
 137
 138        if (!argv[0]) /* "-p <priority> <pid> [...]" */
 139                goto print_rt_info;
 140
 141        BB_EXECVP_or_die(argv);
 142}
 143