taskset.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /* taskset.c - Retrieve or set the CPU affinity of a process.
  2. *
  3. * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
  4. USE_TASKSET(NEWTOY(taskset, "<1^pa", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
  5. USE_NPROC(NEWTOY(nproc, "(all)", TOYFLAG_USR|TOYFLAG_BIN))
  6. config NPROC
  7. bool "nproc"
  8. default y
  9. help
  10. usage: nproc [--all]
  11. Print number of processors.
  12. --all Show all processors, not just ones this task can run on
  13. config TASKSET
  14. bool "taskset"
  15. default y
  16. help
  17. usage: taskset [-ap] [mask] [PID | cmd [args...]]
  18. Launch a new task which may only run on certain processors, or change
  19. the processor affinity of an existing PID.
  20. Mask is a hex string where each bit represents a processor the process
  21. is allowed to run on. PID without a mask displays existing affinity.
  22. -p Set/get the affinity of given PID instead of a new command
  23. -a Set/get the affinity of all threads of the PID
  24. */
  25. #define FOR_taskset
  26. #include "toys.h"
  27. #define sched_setaffinity(pid, size, cpuset) \
  28. syscall(__NR_sched_setaffinity, (pid_t)pid, (size_t)size, (void *)cpuset)
  29. #define sched_getaffinity(pid, size, cpuset) \
  30. syscall(__NR_sched_getaffinity, (pid_t)pid, (size_t)size, (void *)cpuset)
  31. // mask is an array of long, which makes the layout a bit weird on big
  32. // endian systems but as long as it's consistent...
  33. static void do_taskset(pid_t pid, int quiet)
  34. {
  35. unsigned long *mask = (unsigned long *)toybuf;
  36. char *s = *toys.optargs, *failed = "failed to %s %d's affinity";
  37. int i, j, k;
  38. for (i=0; ; i++) {
  39. if (!quiet) {
  40. int j = sizeof(toybuf), flag = 0;
  41. if (-1 == sched_getaffinity(pid, sizeof(toybuf), (void *)mask))
  42. perror_exit(failed, "get", pid);
  43. printf("pid %d's %s affinity mask: ", pid, i ? "new" : "current");
  44. while (j--) {
  45. int x = 255 & (mask[j/sizeof(long)] >> (8*(j&(sizeof(long)-1))));
  46. if (flag) printf("%02x", x);
  47. else if (x) {
  48. flag++;
  49. printf("%x", x);
  50. }
  51. }
  52. putchar('\n');
  53. }
  54. if (i || toys.optc < 2) return;
  55. memset(toybuf, 0, sizeof(toybuf));
  56. k = strlen(s = *toys.optargs);
  57. s += k;
  58. for (j = 0; j<k; j++) {
  59. unsigned long digit = *(--s) - '0';
  60. if (digit > 9) digit = 10 + tolower(*s)-'a';
  61. if (digit > 15) error_exit("bad mask '%s'", *toys.optargs);
  62. mask[j/(2*sizeof(long))] |= digit << 4*(j&((2*sizeof(long))-1));
  63. }
  64. if (-1 == sched_setaffinity(pid, sizeof(toybuf), (void *)mask))
  65. perror_exit(failed, "set", pid);
  66. }
  67. }
  68. static int task_callback(struct dirtree *new)
  69. {
  70. if (!new->parent) return DIRTREE_RECURSE;
  71. if (isdigit(*new->name)) do_taskset(atoi(new->name), 0);
  72. return 0;
  73. }
  74. void taskset_main(void)
  75. {
  76. if (!(toys.optflags & FLAG_p)) {
  77. if (toys.optc < 2) error_exit("Needs 2 args");
  78. do_taskset(getpid(), 1);
  79. xexec(toys.optargs+1);
  80. } else {
  81. char *c;
  82. pid_t pid = strtol(toys.optargs[toys.optc-1], &c, 10);
  83. if (*c) error_exit("Not int %s", toys.optargs[1]);
  84. if (toys.optflags & FLAG_a) {
  85. char buf[33];
  86. sprintf(buf, "/proc/%ld/task/", (long)pid);
  87. dirtree_read(buf, task_callback);
  88. } else do_taskset(pid, 0);
  89. }
  90. }
  91. void nproc_main(void)
  92. {
  93. unsigned i, j, nproc = 0;
  94. // This can only detect 32768 processors. Call getaffinity and count bits.
  95. if (!toys.optflags && -1!=sched_getaffinity(getpid(), 4096, toybuf)) {
  96. for (i = 0; i<4096; i++)
  97. if (toybuf[i]) for (j=0; j<8; j++) if (toybuf[i]&(1<<j)) nproc++;
  98. }
  99. // If getaffinity failed or --all, count cpu entries in proc
  100. if (!nproc) nproc = sysconf(_SC_NPROCESSORS_CONF);
  101. xprintf("%u\n", nproc);
  102. }