diff --git a/defs.h b/defs.h index a942dbb..deabe91 100755 --- a/defs.h +++ b/defs.h @@ -47,6 +47,7 @@ #include #include #include /* backtrace() */ +#include #ifndef ATTRIBUTE_UNUSED #define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) @@ -977,6 +978,7 @@ extern struct machdep_table *machdep; #define FOREACH_F_FLAG (0x400000) #define FOREACH_x_FLAG (0x800000) #define FOREACH_d_FLAG (0x1000000) +#define FOREACH_E_FLAG (0x2000000) struct foreach_data { ulong flags; @@ -985,6 +987,7 @@ struct foreach_data { char *comm_array[MAX_FOREACH_COMMS]; ulong pid_array[MAX_FOREACH_PIDS]; ulong arg_array[MAX_FOREACH_ARGS]; + regex_t regex; char *reference; int keys; int pids; diff --git a/help.c b/help.c index f752283..03f8b84 100755 --- a/help.c +++ b/help.c @@ -725,7 +725,7 @@ NULL, char *help_foreach[] = { "foreach", "display command data for multiple tasks in the system", -"[[pid | taskp | name | [kernel | user]] ...] command [flag] [argument]", +"[[pid | taskp | name | [kernel | user]] ... | -E regex] command [flag] [argument]", " This command allows for a an examination of various kernel data associated", " with any, or all, tasks in the system, without having to set the context", " to each targeted task.\n", @@ -737,7 +737,10 @@ 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.", +" -E regex perform the command(s) on all commands whose names contains a match", +" to the given regex. regex is interpreted as an POSIX extended regular", +" expression.\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", @@ -794,6 +797,17 @@ char *help_foreach[] = { " Display the open files for all tasks:\n", " %s> foreach files", " ...\n", +" Display the state of tasks whose name contains a match to 'event.*':\n", +" %s> foreach -E 'event.*' task -R state", +" PID: 99 TASK: ffff8804750d5500 CPU: 0 COMMAND: \"events/0\"", +" state = 1,", +" ", +" PID: 100 TASK: ffff8804750d4ac0 CPU: 1 COMMAND: \"events/1\"", +" state = 1," +" ", +" PID: 101 TASK: ffff8804750d4080 CPU: 2 COMMAND: \"events/2\"", +" state = 1,", +" ...\n", NULL }; diff --git a/task.c b/task.c index fde86eb..b8b709d 100755 --- a/task.c +++ b/task.c @@ -4896,9 +4896,14 @@ cmd_foreach(void) BZERO(&foreach_data, sizeof(struct foreach_data)); fd = &foreach_data; - while ((c = getopt(argcnt, args, "R:vomlgersStTpukcfFxhd")) != EOF) { + while ((c = getopt(argcnt, args, "E:R:vomlgersStTpukcfFxhd")) != EOF) { switch(c) { + case 'E': + if (regcomp(&fd->regex, optarg, REG_EXTENDED|REG_NOSUB)) + error(FATAL, "invalid regular expression!\n"); + fd->flags |= FOREACH_E_FLAG; + break; case 'R': fd->reference = optarg; break; @@ -5021,6 +5026,9 @@ cmd_foreach(void) switch (str_to_context(args[optind], &value, &tc)) { case STR_PID: + if (fd->flags & FOREACH_E_FLAG) + error(FATAL, "'-E regex' and 'pid' " + "are mutually exclusive!\n"); if (p == MAX_FOREACH_PIDS) error(INFO, "too many pids specified!\n"); @@ -5033,6 +5041,9 @@ cmd_foreach(void) break; case STR_TASK: + if (fd->flags & FOREACH_E_FLAG) + error(FATAL, "'-E regex' and 'taskp' " + "are mutually exclusive!\n"); if (t == MAX_FOREACH_TASKS) error(INFO, "too many tasks specified!\n"); @@ -5053,6 +5064,9 @@ cmd_foreach(void) * Select all kernel threads. */ if (STREQ(args[optind], "kernel")) { + if (fd->flags & FOREACH_E_FLAG) + error(FATAL, "'-E regex' and 'kernel' " + "are mutually exclusive!\n"); if (fd->flags & FOREACH_USER) error(FATAL, "user and kernel are mutually exclusive!\n"); @@ -5065,6 +5079,9 @@ cmd_foreach(void) * Select only user threads. */ if (STREQ(args[optind], "user")) { + if (fd->flags & FOREACH_E_FLAG) + error(FATAL, "'-E regex' and 'user' " + "are mutually exclusive!\n"); if (fd->flags & FOREACH_KERNEL) error(FATAL, "user and kernel are mutually exclusive!\n"); @@ -5077,6 +5094,9 @@ cmd_foreach(void) * Select only active tasks (dumpfile only) */ if (STREQ(args[optind], "active")) { + if (fd->flags & FOREACH_E_FLAG) + error(FATAL, "'-E regex' and 'active' " + "are mutually exclusive!\n"); if (!DUMPFILE()) error(FATAL, "active option not allowed on live systems\n"); @@ -5092,6 +5112,9 @@ cmd_foreach(void) &args[optind][1] : args[optind]; if (comm_exists(p1)) { + if (fd->flags & FOREACH_E_FLAG) + error(FATAL, "'-E regex' and 'name' " + "are mutually exclusive!\n"); if (c == MAX_FOREACH_COMMS) error(INFO, "too many commands specified!\n"); else { @@ -5335,6 +5358,10 @@ foreach(struct foreach_data *fd) if (STREQ(fd->comm_array[j], tc->comm)) doit = TRUE; } + else if (fd->flags & FOREACH_E_FLAG) { + if (regexec(&fd->regex, tc->comm, 0, NULL, 0) == 0) + doit = TRUE; + } else doit = TRUE;