• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /* chrt.c - Get/set real-time (scheduling) attributes
2   *
3   * Copyright 2016 The Android Open Source Project
4   *
5   * Note: -ibrfo flags sorted to match SCHED positions for highest_bit()
6  
7  USE_CHRT(NEWTOY(chrt, "^mp#<0iRbrfo[!ibrfo]", TOYFLAG_USR|TOYFLAG_BIN))
8  
9  config CHRT
10    bool "chrt"
11    default y
12    help
13      usage: chrt [-Rmofrbi] {-p PID [PRIORITY] | [PRIORITY COMMAND...]}
14  
15      Get/set a process' real-time scheduling policy and priority.
16  
17      -p	Set/query given pid (instead of running COMMAND)
18      -R	Set SCHED_RESET_ON_FORK
19      -m	Show min/max priorities available
20  
21      Set policy (default -r):
22  
23        -o  SCHED_OTHER    -f  SCHED_FIFO    -r  SCHED_RR
24        -b  SCHED_BATCH    -i  SCHED_IDLE
25  */
26  
27  #define FOR_chrt
28  #include "toys.h"
29  
30  GLOBALS(
31    long p;
32  )
33  
34  #ifndef _POSIX_PRIORITY_SCHEDULING
35  // musl-libc intentionally broke sched_get_priority_min() and friends in
36  // commit 1e21e78bf7a5 because its maintainer didn't like those Linux
37  // system calls, so work around it here.
38  #include <sys/syscall.h>
39  #define sched_get_priority_min(policy) \
40    (int)syscall(SYS_sched_get_priority_min, (int)policy)
41  #define sched_get_priority_max(policy) \
42    (int)syscall(SYS_sched_get_priority_max, (int)policy)
43  #define sched_getparam(pid, param) \
44    syscall(SYS_sched_getparam, (pid_t)pid, (void *)param)
45  #define sched_getscheduler(pid) \
46    syscall(SYS_sched_getscheduler, (pid_t)pid)
47  #define sched_setscheduler(pid, scheduler, param) \
48    syscall(SYS_sched_setscheduler, (pid_t)pid, (int)scheduler, (void *)param)
49  #endif
50  
51  char *polnames[] = {
52    "SCHED_OTHER", "SCHED_FIFO", "SCHED_RR", "SCHED_BATCH", 0, "SCHED_IDLE",
53    "SCHED_DEADLINE"
54  };
55  
chrt_main(void)56  void chrt_main(void)
57  {
58    int pol, pri;
59  
60    // Show min/maxes?
61    if (toys.optflags&FLAG_m) {
62      for (pol = 0; pol<ARRAY_LEN(polnames); pol++) if (polnames[pol])
63        printf("%s min/max priority\t: %d/%d\n", polnames[pol],
64          sched_get_priority_min(pol), sched_get_priority_max(pol));
65  
66      return;
67    }
68  
69    // Query when -p without priority.
70    if (toys.optflags==FLAG_p && !*toys.optargs) {
71      char *s = "???", *R = "";
72  
73      if (-1==(pol = sched_getscheduler(TT.p))) perror_exit("pid %ld", TT.p);
74      if (pol & SCHED_RESET_ON_FORK) R = "|SCHED_RESET_ON_FORK";
75      if ((pol &= ~SCHED_RESET_ON_FORK)<ARRAY_LEN(polnames)) s = polnames[pol];
76      printf("pid %ld's current scheduling policy: %s%s\n", TT.p, s, R);
77  
78      if (sched_getparam(TT.p, (void *)&pri)) perror_exit("sched_getparam");
79      printf("pid %ld's current scheduling priority: %d\n", TT.p, pri);
80  
81      return;
82    }
83  
84    if (!*toys.optargs) help_exit("no PRIORITY");
85    if (!toys.optargs[1] == !(toys.optflags&FLAG_p))
86      help_exit("need 1 of -p or COMMAND");
87  
88    // Set policy and priority
89    if (-1==(pol = highest_bit(toys.optflags&0x2f))) pol = SCHED_RR;
90    pri = atolx_range(*toys.optargs, sched_get_priority_min(pol),
91      sched_get_priority_max(pol));
92    if (toys.optflags&FLAG_R) pol |= SCHED_RESET_ON_FORK;
93  
94    if (sched_setscheduler(TT.p, pol, (void *)&pri))
95      perror_exit("sched_setscheduler");
96  
97    if (*(toys.optargs+1)) xexec(toys.optargs+1);
98  }
99