[PATCH 2/2] taskset: make threads aware

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux