From: Davidlohr Bueso <dave@xxxxxxx> Date: Mon, 9 May 2011 12:19:06 -0400 Add a new '-a' option to view/modify the CPU affinity for an entire group of threads belonging to a given PID. We also add a new print_affinity() to simply and reuse code. Signed-off-by: Davidlohr Bueso <dave@xxxxxxx> Tested-by: Jonathan Gonzalez <zeus@xxxxxxx> --- schedutils/taskset.1 | 3 ++ schedutils/taskset.c | 75 ++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 64 insertions(+), 14 deletions(-) diff --git a/schedutils/taskset.1 b/schedutils/taskset.1 index f374b62..4aa5e2c 100644 --- a/schedutils/taskset.1 +++ b/schedutils/taskset.1 @@ -72,6 +72,9 @@ returns, it is guaranteed that the given program has been scheduled to a legal CPU. .SH OPTIONS .TP +.BR \-a ,\ \-\-all-tasks +set or retrieve the CPU affinity of all the tasks (threads) for a given PID. +.TP .BR \-p ,\ \-\-pid operate on an existing PID and not launch a new task .TP diff --git a/schedutils/taskset.c b/schedutils/taskset.c index f34bc93..96276b3 100644 --- a/schedutils/taskset.c +++ b/schedutils/taskset.c @@ -28,6 +28,7 @@ #include "cpuset.h" #include "nls.h" #include "strutils.h" +#include "procutils.h" #include "xalloc.h" #include "c.h" @@ -39,6 +40,7 @@ static void __attribute__((__noreturn__)) usage(FILE *out) fprintf(out, _( "Options:\n" + " -a, --all-tasks propagate changes to all the tasks for a given pid\n" " -p, --pid operate on existing given pid\n" " -c, --cpu-list display and specify cpus in list format\n" " -h, --help display this help\n" @@ -62,16 +64,34 @@ static void __attribute__((__noreturn__)) usage(FILE *out) exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); } +static void print_affinity(char *state, int c_opt, pid_t pid, char *buf, size_t buflen, + cpu_set_t *set, size_t setsize) +{ + char *cpuset, *str; + + if (c_opt) { + cpuset = cpulist_create(buf, buflen, set, setsize); + str = "list"; + } else { + cpuset = cpumask_create(buf, buflen, set, setsize); + str = "mask"; + } + + printf(_("pid %d's %s affinity %s: %s\n"), pid, state, str, cpuset); + +} + int main(int argc, char *argv[]) { cpu_set_t *new_set, *cur_set; pid_t pid = 0; - int opt, c_opt = 0, rc; + int opt, c_opt = 0, rc, all_tasks = 0; char *buf; unsigned int ncpus; size_t new_setsize, cur_setsize, cur_nbits, buflen; static const struct option longopts[] = { + { "all-tasks", 0, NULL, 'a' }, { "pid", 0, NULL, 'p' }, { "cpu-list", 0, NULL, 'c' }, { "help", 0, NULL, 'h' }, @@ -83,8 +103,11 @@ int main(int argc, char *argv[]) bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - while ((opt = getopt_long(argc, argv, "+pchV", longopts, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "+apchV", longopts, NULL)) != -1) { switch (opt) { + case 'a': + all_tasks = 1; + break; case 'p': pid = strtol_or_err(argv[argc - 1], _("failed to parse pid")); break; @@ -136,12 +159,18 @@ int main(int argc, char *argv[]) if (sched_getaffinity(pid, cur_setsize, cur_set) < 0) err(EXIT_FAILURE, _("failed to get pid %d's affinity"), pid); - if (c_opt) - printf(_("pid %d's current affinity list: %s\n"), pid, - cpulist_create(buf, buflen, cur_set, cur_setsize)); + if (all_tasks) { + pid_t tid; + struct proc_tasks *ts = proc_open_tasks(pid); + + if (!ts) + err(EXIT_FAILURE, "cannot obtain the list of tasks"); + while (!proc_next_tid(ts, &tid)) + print_affinity("current", c_opt, tid, buf, buflen, cur_set, cur_setsize); + proc_close_tasks(ts); + } else - printf(_("pid %d's current affinity mask: %s\n"), pid, - cpumask_create(buf, buflen, cur_set, cur_setsize)); + print_affinity("current", c_opt, pid, buf, buflen, cur_set, cur_setsize); if (argc - optind == 1) return EXIT_SUCCESS; @@ -155,19 +184,37 @@ int main(int argc, char *argv[]) c_opt ? _("CPU list") : _("CPU mask"), argv[optind]); - if (sched_setaffinity(pid, new_setsize, new_set) < 0) - err(EXIT_FAILURE, _("failed to set pid %d's affinity"), pid); + if (all_tasks) { + pid_t tid; + struct proc_tasks *ts = proc_open_tasks(pid); + + if (!ts) + err(EXIT_FAILURE, "cannot obtain the list of tasks"); + while (!proc_next_tid(ts, &tid)) + if (sched_setaffinity(tid, new_setsize, new_set) < 0) + err(EXIT_FAILURE, _("failed to set tid %d's affinity"), tid); + proc_close_tasks(ts); + } + else + if (sched_setaffinity(pid, new_setsize, new_set) < 0) + err(EXIT_FAILURE, _("failed to set pid %d's affinity"), pid); if (sched_getaffinity(pid, cur_setsize, cur_set) < 0) err(EXIT_FAILURE, _("failed to get pid %d's affinity"), pid); if (pid) { - if (c_opt) - printf(_("pid %d's new affinity list: %s\n"), pid, - cpulist_create(buf, buflen, cur_set, cur_setsize)); + if (all_tasks) { + pid_t tid; + struct proc_tasks *ts = proc_open_tasks(pid); + + if (!ts) + err(EXIT_FAILURE, "cannot obtain the list of tasks"); + while (!proc_next_tid(ts, &tid)) + print_affinity("new", c_opt, tid, buf, buflen, cur_set, cur_setsize); + proc_close_tasks(ts); + } else - printf(_("pid %d's new affinity mask: %s\n"), pid, - cpumask_create(buf, buflen, cur_set, cur_setsize)); + print_affinity("new", c_opt, pid, buf, buflen, cur_set, cur_setsize); } free(buf); -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe util-linux" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html