aboutsummaryrefslogtreecommitdiff
path: root/toys/pending/chrt.c
blob: d2b73a42a36a0a6991707c95192f82ef58f734f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/* chrt.c - Get/set real-time (scheduling) attributes
 *
 * Copyright 2016 The Android Open Source Project

USE_CHRT(NEWTOY(chrt, "mp#bfiorR[!bfior]", TOYFLAG_USR|TOYFLAG_SBIN))

config CHRT
  bool "chrt"
  default n
  help
    usage: chrt [-m] [-p PID] [POLICY PRIO] [COMMAND [ARGS...]]

    Get/set a process' real-time (scheduling) attributes.

    -p	Apply to given pid
    -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
*/

#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] : "???";
}

void chrt_main(void)
{
  int policy = SCHED_RR;
  struct sched_param p;

  // 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));
    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));

    if (sched_getparam(TT.pid, &p)) perror_exit("sched_getparam");
    printf("pid %ld's current scheduling priority: %d\n",
           TT.pid, p.sched_priority);

    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.optflags&FLAG_R) policy |= 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, policy, &p)) perror_exit("sched_setscheduler");

  if (*(toys.optargs+1)) {
    toys.stacktop = 0;
    xexec(++toys.optargs);
  }
}