1/* vi: set sw=4 ts=4: */ 2/* 3 * taskset - retrieve or set a processes' CPU affinity 4 * Copyright (c) 2006 Bernhard Fischer 5 * 6 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 7 */ 8 9#include <sched.h> 10#include <getopt.h> /* optind */ 11#include "libbb.h" 12 13#if ENABLE_FEATURE_TASKSET_FANCY 14#define TASKSET_PRINTF_MASK "%s" 15#define from_cpuset(x) __from_cpuset(&x) 16/* craft a string from the mask */ 17static char *__from_cpuset(cpu_set_t *mask) 18{ 19 int i; 20 char *ret = 0, *str = xzalloc(9); 21 22 for (i = CPU_SETSIZE - 4; i >= 0; i -= 4) { 23 char val = 0; 24 int off; 25 for (off = 0; off <= 3; ++off) 26 if (CPU_ISSET(i+off, mask)) 27 val |= 1<<off; 28 29 if (!ret && val) 30 ret = str; 31 *str++ = (val-'0'<=9) ? (val+48) : (val+87); 32 } 33 return ret; 34} 35#else 36#define TASKSET_PRINTF_MASK "%x" 37/* (void*) cast is for battling gcc: */ 38/* "dereferencing type-punned pointer will break strict-aliasing rules" */ 39#define from_cpuset(mask) (*(unsigned*)(void*)&(mask)) 40#endif 41 42#define OPT_p 1 43 44int taskset_main(int argc, char** argv); 45int taskset_main(int argc, char** argv) 46{ 47 cpu_set_t mask, new_mask; 48 pid_t pid = 0; 49 unsigned opt; 50 const char *state = "current\0new"; 51 char *p_opt = NULL, *aff = NULL; 52 53 opt = getopt32(argv, "+p:", &p_opt); 54 55 if (opt & OPT_p) { 56 if (argc == optind+1) { /* -p <aff> <pid> */ 57 aff = p_opt; 58 p_opt = argv[optind]; 59 } 60 argv += optind; /* me -p <arg> */ 61 pid = xatoul_range(p_opt, 1, ULONG_MAX); /* -p <pid> */ 62 } else 63 aff = *++argv; /* <aff> <cmd...> */ 64 if (aff) { 65 unsigned i = 0; 66 unsigned long l = xstrtol_range(aff, 0, 1, LONG_MAX); 67 68 CPU_ZERO(&new_mask); 69 while (i < CPU_SETSIZE && l >= (1<<i)) { 70 if ((1<<i) & l) 71 CPU_SET(i, &new_mask); 72 ++i; 73 } 74 } 75 76 if (opt & OPT_p) { 77 print_aff: 78 if (sched_getaffinity(pid, sizeof(mask), &mask) < 0) 79 bb_perror_msg_and_die("failed to %cet pid %d's affinity", 'g', pid); 80 printf("pid %d's %s affinity mask: "TASKSET_PRINTF_MASK"\n", 81 pid, state, from_cpuset(mask)); 82 if (!*argv) /* no new affinity given or we did print already, done. */ 83 return EXIT_SUCCESS; 84 } 85 86 if (sched_setaffinity(pid, sizeof(new_mask), &new_mask)) 87 bb_perror_msg_and_die("failed to %cet pid %d's affinity", 's', pid); 88 if (opt & OPT_p) { 89 state += 8; 90 ++argv; 91 goto print_aff; 92 } 93 ++argv; 94 BB_EXECVP(*argv, argv); 95 bb_perror_msg_and_die("%s", *argv); 96} 97#undef OPT_p 98#undef TASKSET_PRINTF_MASK 99#undef from_cpuset 100