busybox/util-linux/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//config:config CHRT
   9//config:       bool "chrt (4.7 kb)"
  10//config:       default y
  11//config:       help
  12//config:       Manipulate real-time attributes of a process.
  13//config:       This requires sched_{g,s}etparam support in your libc.
  14
  15//applet:IF_CHRT(APPLET_NOEXEC(chrt, chrt, BB_DIR_USR_BIN, BB_SUID_DROP, chrt))
  16
  17//kbuild:lib-$(CONFIG_CHRT) += chrt.o
  18
  19//usage:#define chrt_trivial_usage
  20//usage:       "[-prfombi] [PRIO] [PID | PROG ARGS]"
  21//usage:#define chrt_full_usage "\n\n"
  22//usage:       "Change scheduling priority and class for a process\n"
  23//usage:     "\n        -p      Operate on PID"
  24//usage:     "\n        -r      Set SCHED_RR class"
  25//usage:     "\n        -f      Set SCHED_FIFO class"
  26//usage:     "\n        -o      Set SCHED_OTHER class"
  27//usage:     "\n        -b      Set SCHED_BATCH class"
  28//usage:     "\n        -i      Set SCHED_IDLE class"
  29//usage:     "\n        -m      Show min/max priorities"
  30//usage:
  31//usage:#define chrt_example_usage
  32//usage:       "$ chrt -r 4 sleep 900; x=$!\n"
  33//usage:       "$ chrt -f -p 3 $x\n"
  34//usage:       "You need CAP_SYS_NICE privileges to set scheduling attributes of a process"
  35
  36#include <sched.h>
  37#include "libbb.h"
  38#ifndef SCHED_IDLE
  39# define SCHED_IDLE 5
  40#endif
  41
  42static const struct {
  43        char name[sizeof("SCHED_OTHER")];
  44} policies[] = {
  45        { "SCHED_OTHER" }, /* 0:SCHED_OTHER */
  46        { "SCHED_FIFO" },  /* 1:SCHED_FIFO */
  47        { "SCHED_RR" },    /* 2:SCHED_RR */
  48        { "SCHED_BATCH" }, /* 3:SCHED_BATCH */
  49        { "" },            /* 4:SCHED_ISO */
  50        { "SCHED_IDLE" },  /* 5:SCHED_IDLE */
  51        /* 6:SCHED_DEADLINE */
  52};
  53
  54static void show_min_max(int pol)
  55{
  56        const char *fmt = "%s min/max priority\t: %u/%u\n";
  57        int max, min;
  58
  59        max = sched_get_priority_max(pol);
  60        min = sched_get_priority_min(pol);
  61        if ((max|min) < 0)
  62                fmt = "%s not supported\n";
  63        printf(fmt, policies[pol].name, min, max);
  64}
  65
  66#define OPT_m (1<<0)
  67#define OPT_p (1<<1)
  68#define OPT_r (1<<2)
  69#define OPT_f (1<<3)
  70#define OPT_o (1<<4)
  71#define OPT_b (1<<5)
  72#define OPT_i (1<<6)
  73
  74int chrt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  75int chrt_main(int argc UNUSED_PARAM, char **argv)
  76{
  77        pid_t pid = 0;
  78        unsigned opt;
  79        struct sched_param sp;
  80        char *pid_str;
  81        char *priority = priority; /* for compiler */
  82        const char *current_new;
  83        int policy = SCHED_RR;
  84
  85        opt = getopt32(argv, "^"
  86                        "+" "mprfobi"
  87                        "\0"
  88                        /* only one policy accepted: */
  89                        "r--fobi:f--robi:o--rfbi:b--rfoi:i--rfob"
  90        );
  91        if (opt & OPT_m) { /* print min/max and exit */
  92                show_min_max(SCHED_OTHER);
  93                show_min_max(SCHED_FIFO);
  94                show_min_max(SCHED_RR);
  95                show_min_max(SCHED_BATCH);
  96                show_min_max(SCHED_IDLE);
  97                fflush_stdout_and_exit(EXIT_SUCCESS);
  98        }
  99        //if (opt & OPT_r)
 100        //      policy = SCHED_RR; - default, already set
 101        if (opt & OPT_f)
 102                policy = SCHED_FIFO;
 103        if (opt & OPT_o)
 104                policy = SCHED_OTHER;
 105        if (opt & OPT_b)
 106                policy = SCHED_BATCH;
 107        if (opt & OPT_i)
 108                policy = SCHED_IDLE;
 109
 110        argv += optind;
 111        if (!argv[0])
 112                bb_show_usage();
 113        if (opt & OPT_p) {
 114                pid_str = *argv++;
 115                if (*argv) { /* "-p <priority> <pid> [...]" */
 116                        priority = pid_str;
 117                        pid_str = *argv;
 118                }
 119                /* else "-p <pid>", and *argv == NULL */
 120                pid = xatoul_range(pid_str, 1, ((unsigned)(pid_t)ULONG_MAX) >> 1);
 121        } else {
 122                priority = *argv++;
 123                if (!*argv)
 124                        bb_show_usage();
 125        }
 126
 127        current_new = "current\0new";
 128        if (opt & OPT_p) {
 129                int pol;
 130 print_rt_info:
 131                pol = sched_getscheduler(pid);
 132                if (pol < 0)
 133                        bb_perror_msg_and_die("can't %cet pid %d's policy", 'g', (int)pid);
 134                printf("pid %d's %s scheduling policy: %s\n",
 135                                pid, current_new, policies[pol].name);
 136                if (sched_getparam(pid, &sp))
 137                        bb_perror_msg_and_die("can't get pid %d's attributes", (int)pid);
 138                printf("pid %d's %s scheduling priority: %d\n",
 139                                (int)pid, current_new, sp.sched_priority);
 140                if (!*argv) {
 141                        /* Either it was just "-p <pid>",
 142                         * or it was "-p <priority> <pid>" and we came here
 143                         * for the second time (see goto below) */
 144                        return EXIT_SUCCESS;
 145                }
 146                *argv = NULL;
 147                current_new += 8;
 148        }
 149
 150        sp.sched_priority = xstrtou_range(priority, 0,
 151                sched_get_priority_min(policy), sched_get_priority_max(policy)
 152        );
 153
 154        if (sched_setscheduler(pid, policy, &sp) < 0)
 155                bb_perror_msg_and_die("can't %cet pid %d's policy", 's', (int)pid);
 156
 157        if (!argv[0]) /* "-p <priority> <pid> [...]" */
 158                goto print_rt_info;
 159
 160        BB_EXECVP_or_die(argv);
 161}
 162