The patch below adds support to filter foreach on task states. I've
found [foreach state=D bt] and [foreach state=R bt] useful; the former
allows to emulate the show-blocked-tasks Magic SysRq.
Rabin
diff --git a/defs.h b/defs.h
index 2e7f6bd..dc12844 100755
--- a/defs.h
+++ b/defs.h
@@ -974,6 +974,7 @@ extern struct machdep_table *machdep;
#define FOREACH_F_FLAG (0x400000)
#define FOREACH_x_FLAG (0x800000)
#define FOREACH_d_FLAG (0x1000000)
+#define FOREACH_STATE (0x2000000)
struct foreach_data {
ulong flags;
@@ -982,6 +983,7 @@ struct foreach_data {
char *comm_array[MAX_FOREACH_COMMS];
ulong pid_array[MAX_FOREACH_PIDS];
ulong arg_array[MAX_FOREACH_ARGS];
+ ulong state;
char *reference;
int keys;
int pids;
diff --git a/help.c b/help.c
index adaaea7..dedf479 100755
--- a/help.c
+++ b/help.c
@@ -736,7 +736,9 @@ char *help_foreach[] = {
" precede the name string with a \"\\\".",
" user perform the command(s) on all user (non-kernel) threads.",
" kernel perform the command(s) on all kernel threads.",
-" active perform the command(s) on the active thread on each CPU.\n",
+" active perform the command(s) on the active thread on each CPU.",
+" state=? perform the command(s) on all tasks in the specified state.",
+" (? is one of R, S, D, T, Z, X, W)\n",
" If none of the task-identifying arguments above are entered, the command",
" will be performed on all tasks.\n",
" command select one or more of the following commands to be run on the
tasks",
@@ -793,6 +795,9 @@ char *help_foreach[] = {
" Display the open files for all tasks:\n",
" %s> foreach files",
" ...\n",
+" Display the stack traces for all blocked (TASK_UNINTERRUPTIBLE) tasks:\n",
+" %s> foreach state=D bt",
+" ...\n",
NULL
};
diff --git a/task.c b/task.c
index 433a043..de033c3 100755
--- a/task.c
+++ b/task.c
@@ -5061,6 +5061,35 @@ cmd_foreach(void)
continue;
}
+ if (STRNEQ(args[optind], "state=")) {
+ const char *p = args[optind] + strlen("state=");
+ ulong state = 0;
+
+ if (STREQ(p, "R"))
+ state = _RUNNING_;
+ else if (STREQ(p, "S"))
+ state = _INTERRUPTIBLE_;
+ else if (STREQ(p, "D"))
+ state = _UNINTERRUPTIBLE_;
+ else if (STREQ(p, "T"))
+ state = _STOPPED_;
+ else if (STREQ(p, "Z"))
+ state = _ZOMBIE_;
+ else if (STREQ(p, "X"))
+ state = _DEAD_;
+ else if (STREQ(p, "W"))
+ state = _SWAPPING_;
+ else if (*p)
+ error(FATAL, "invalid state: %s\n", p);
+ else
+ error(FATAL, "no state specified\n");
+
+ fd->flags |= FOREACH_STATE;
+ fd->state = state;
+ optind++;
+ continue;
+ }
+
/*
* Select only user threads.
*/
@@ -5322,6 +5351,9 @@ foreach(struct foreach_data *fd)
if ((fd->flags & FOREACH_KERNEL) && !is_kernel_thread(tc->task))
continue;
+ if ((fd->flags & FOREACH_STATE) && task_state(tc->task) !=
fd->state)
+ continue;
+
if (specified) {
for (j = 0; j < fd->tasks; j++)
if (fd->task_array[j] == tc->task)
--
1.7.9.1