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 tarball for details. 7 */ 8#include <sched.h> 9#include "libbb.h" 10#ifndef _POSIX_PRIORITY_SCHEDULING 11#warning your system may be foobared 12#endif 13 14static const struct { 15 int policy; 16 char name[sizeof("SCHED_OTHER")]; 17} policies[] = { 18 {SCHED_OTHER, "SCHED_OTHER"}, 19 {SCHED_FIFO, "SCHED_FIFO"}, 20 {SCHED_RR, "SCHED_RR"} 21}; 22 23//TODO: add 24// -b, SCHED_BATCH 25// -i, SCHED_IDLE 26 27static void show_min_max(int pol) 28{ 29 const char *fmt = "%s min/max priority\t: %u/%u\n"; 30 int max, min; 31 32 max = sched_get_priority_max(pol); 33 min = sched_get_priority_min(pol); 34 if ((max|min) < 0) 35 fmt = "%s not supported\n"; 36 printf(fmt, policies[pol].name, min, max); 37} 38 39#define OPT_m (1<<0) 40#define OPT_p (1<<1) 41#define OPT_r (1<<2) 42#define OPT_f (1<<3) 43#define OPT_o (1<<4) 44 45int chrt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 46int chrt_main(int argc UNUSED_PARAM, char **argv) 47{ 48 pid_t pid = 0; 49 unsigned opt; 50 struct sched_param sp; 51 char *pid_str; 52 char *priority = priority; /* for compiler */ 53 const char *current_new; 54 int policy = SCHED_RR; 55 56 /* at least 1 arg; only one policy accepted */ 57 opt_complementary = "-1:r--fo:f--ro:r--fo"; 58 opt = getopt32(argv, "+mprfo"); 59 if (opt & OPT_r) 60 policy = SCHED_RR; 61 if (opt & OPT_f) 62 policy = SCHED_FIFO; 63 if (opt & OPT_o) 64 policy = SCHED_OTHER; 65 if (opt & OPT_m) { /* print min/max */ 66 show_min_max(SCHED_FIFO); 67 show_min_max(SCHED_RR); 68 show_min_max(SCHED_OTHER); 69 fflush_stdout_and_exit(EXIT_SUCCESS); 70 } 71 72 argv += optind; 73 if (opt & OPT_p) { 74 pid_str = *argv++; 75 if (*argv) { /* "-p <priority> <pid> [...]" */ 76 priority = pid_str; 77 pid_str = *argv; 78 } 79 /* else "-p <pid>", and *argv == NULL */ 80 pid = xatoul_range(pid_str, 1, ((unsigned)(pid_t)ULONG_MAX) >> 1); 81 } else { 82 priority = *argv++; 83 if (!*argv) 84 bb_show_usage(); 85 } 86 87 current_new = "current\0new"; 88 if (opt & OPT_p) { 89 int pol; 90 print_rt_info: 91 pol = sched_getscheduler(pid); 92 if (pol < 0) 93 bb_perror_msg_and_die("can't %cet pid %d's policy", 'g', pid); 94 printf("pid %d's %s scheduling policy: %s\n", 95 pid, current_new, policies[pol].name); 96 if (sched_getparam(pid, &sp)) 97 bb_perror_msg_and_die("can't get pid %d's attributes", pid); 98 printf("pid %d's %s scheduling priority: %d\n", 99 pid, current_new, sp.sched_priority); 100 if (!*argv) { 101 /* Either it was just "-p <pid>", 102 * or it was "-p <priority> <pid>" and we came here 103 * for the second time (see goto below) */ 104 return EXIT_SUCCESS; 105 } 106 *argv = NULL; 107 current_new += 8; 108 } 109 110 /* from the manpage of sched_getscheduler: 111 [...] sched_priority can have a value in the range 0 to 99. 112 [...] SCHED_OTHER or SCHED_BATCH must be assigned static priority 0. 113 [...] SCHED_FIFO or SCHED_RR can have static priority in 1..99 range. 114 */ 115 sp.sched_priority = xstrtou_range(priority, 0, policy != SCHED_OTHER ? 1 : 0, 99); 116 117 if (sched_setscheduler(pid, policy, &sp) < 0) 118 bb_perror_msg_and_die("can't %cet pid %d's policy", 's', pid); 119 120 if (!argv[0]) /* "-p <priority> <pid> [...]" */ 121 goto print_rt_info; 122 123 BB_EXECVP_or_die(argv); 124} 125