chrt.c 2.9 KB

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