This patch introduces -y option for ps builtin to filter
tasks by scheduling policy. Applicable to both standalone
ps invocation as well as via foreach.

Signed-off-by: Oleksandr Natalenko <[email protected]>
---
 defs.h | 12 ++++++++++
 help.c |  7 ++++--
 task.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 98 insertions(+), 7 deletions(-)

diff --git a/defs.h b/defs.h
index 7768895..fee15b2 100644
--- a/defs.h
+++ b/defs.h
@@ -1139,6 +1139,7 @@ extern struct machdep_table *machdep;
 #define FOREACH_a_FLAG   (0x4000000)
 #define FOREACH_G_FLAG   (0x8000000)
 #define FOREACH_F_FLAG2 (0x10000000)
+#define FOREACH_y_FLAG  (0x20000000)
 
 #define FOREACH_PS_EXCLUSIVE \
   
(FOREACH_g_FLAG|FOREACH_a_FLAG|FOREACH_t_FLAG|FOREACH_c_FLAG|FOREACH_p_FLAG|FOREACH_l_FLAG|FOREACH_r_FLAG|FOREACH_m_FLAG)
@@ -1162,6 +1163,7 @@ struct foreach_data {
        int comms;
        int args;
        int regexs;
+       int policy;
 };
 
 struct reference {       
@@ -1201,6 +1203,7 @@ struct offset_table {                    /* stash of 
commonly-used offsets */
        long task_struct_pidhash_next;
        long task_struct_next_run;
        long task_struct_flags;
+       long task_struct_policy;
        long task_struct_sig;
        long task_struct_signal;
        long task_struct_blocked;
@@ -4570,6 +4573,13 @@ enum type_code {
  */
 #define PF_EXITING 0x00000004  /* getting shut down */
 #define PF_KTHREAD 0x00200000  /* I am a kernel thread */
+#define SCHED_NORMAL   0
+#define SCHED_FIFO     1
+#define SCHED_RR       2
+#define SCHED_BATCH    3
+#define SCHED_ISO      4
+#define SCHED_IDLE     5
+#define SCHED_DEADLINE 6
 
 extern long _ZOMBIE_;
 #define IS_ZOMBIE(task)   (task_state(task) & _ZOMBIE_)
@@ -4597,6 +4607,7 @@ extern long _ZOMBIE_;
 #define PS_NO_HEADER  (0x10000)
 #define PS_MSECS      (0x20000)
 #define PS_SUMMARY    (0x40000)
+#define PS_POLICY     (0x80000)
 
 #define PS_EXCLUSIVE 
(PS_TGID_LIST|PS_ARGV_ENVP|PS_TIMES|PS_CHILD_LIST|PS_PPID_LIST|PS_LAST_RUN|PS_RLIMIT|PS_MSECS|PS_SUMMARY)
 
@@ -4614,6 +4625,7 @@ struct psinfo {
        } regex_data[MAX_PS_ARGS];
        int regexs;
        ulong *cpus;
+       int policy;
 };
 
 #define IS_A_NUMBER(X)      (decimal(X, 0) || hexadecimal(X, 0))
diff --git a/help.c b/help.c
index a9aab37..839cbf9 100644
--- a/help.c
+++ b/help.c
@@ -844,7 +844,7 @@ char *help_foreach[] = {
 "             net  run the \"net\" command  (optional flags: -s -S -R -d -x)",
 "             set  run the \"set\" command",
 "              ps  run the \"ps\" command  (optional flags: -G -s -p -c -t -l 
-a",
-"                  -g -r)",
+"                  -g -r -y)",
 "             sig  run the \"sig\" command (optional flag: -g)",
 "            vtop  run the \"vtop\" command  (optional flags: -c -u -k)\n",
 "     flag  Pass this optional flag to the command selected.",
@@ -1250,7 +1250,7 @@ NULL
 char *help_ps[] = {
 "ps",
 "display process status information",
-"[-k|-u|-G] [-s] [-p|-c|-t|-[l|m][-C cpu]|-a|-g|-r|-S]\n     [pid | task | 
command] ...",
+"[-k|-u|-G] [-s] [-p|-c|-t|-[l|m][-C cpu]|-a|-g|-r|-S|-y policy]\n     [pid | 
task | command] ...",
 "  This command displays process status for selected, or all, processes" ,
 "  in the system.  If no arguments are entered, the process data is",
 "  is displayed for all processes.  Specific processes may be selected",
@@ -1318,6 +1318,9 @@ char *help_ps[] = {
 "       -g  display tasks by thread group, of selected, or all, tasks.",
 "       -r  display resource limits (rlimits) of selected, or all, tasks.",
 "       -S  display a summary consisting of the number of tasks in a task 
state.",
+"-y policy  only show tasks with given scheduling policy. Policy can be:"
+"           NORMAL, FIFO, RR, BATCH, ISO, IDLE, DEADLINE. Multiple policies"
+"           can be specified by passing multiple -y parameters"
 "\nEXAMPLES",
 "  Show the process status of all current tasks:\n",
 "    %s> ps",
diff --git a/task.c b/task.c
index 2b12af0..5b94c06 100644
--- a/task.c
+++ b/task.c
@@ -109,6 +109,23 @@ static void show_ps_summary(ulong);
 static void irqstacks_init(void);
 static void parse_task_thread(int argcnt, char *arglist[], struct task_context 
*);
 static void stack_overflow_check_init(void);
+static int has_sched_policy(ulong task, ulong policy);
+static ulong task_policy(ulong task);
+static ulong sched_policy_from_str(char *policy_str);
+
+static struct sched_policy_info {
+       ulong value;
+       char *name;
+} sched_policy_info[] = {
+       { 1 << SCHED_NORMAL,    "NORMAL" },
+       { 1 << SCHED_FIFO,      "FIFO" },
+       { 1 << SCHED_RR,        "RR" },
+       { 1 << SCHED_BATCH,     "BATCH" },
+       { 1 << SCHED_ISO,       "ISO" },
+       { 1 << SCHED_IDLE,      "IDLE" },
+       { 1 << SCHED_DEADLINE,  "DEADLINE" },
+       { ULONG_MAX,            NULL }
+};
 
 /*
  *  Figure out how much space will be required to hold the task context
@@ -272,6 +289,7 @@ task_init(void)
        MEMBER_OFFSET_INIT(task_struct_active_mm, "task_struct", "active_mm");
        MEMBER_OFFSET_INIT(task_struct_next_run, "task_struct", "next_run");
        MEMBER_OFFSET_INIT(task_struct_flags, "task_struct", "flags");
+       MEMBER_OFFSET_INIT(task_struct_policy, "task_struct", "policy");
        MEMBER_SIZE_INIT(task_struct_flags, "task_struct", "flags");
         MEMBER_OFFSET_INIT(task_struct_pidhash_next,
                 "task_struct", "pidhash_next");
@@ -2974,7 +2992,7 @@ cmd_ps(void)
        cpuspec = NULL;
        flag = 0;
 
-        while ((c = getopt(argcnt, args, "SgstcpkuGlmarC:")) != EOF) {
+        while ((c = getopt(argcnt, args, "SgstcpkuGlmarC:y:")) != EOF) {
                 switch(c)
                {
                case 'k':
@@ -3075,6 +3093,11 @@ cmd_ps(void)
                        make_cpumask(cpuspec, psinfo.cpus, FAULT_ON_ERROR, 
NULL);
                        break;
 
+               case 'y':
+                       flag |= PS_POLICY;
+                       psinfo.policy |= sched_policy_from_str(optarg);
+                       break;
+
                default:
                        argerrs++;
                        break;
@@ -3218,6 +3241,8 @@ show_ps_data(ulong flag, struct task_context *tc, struct 
psinfo *psi)
                return;
        if ((flag & PS_KERNEL) && !is_kernel_thread(tc->task))
                return;
+       if ((flag & PS_POLICY) && !has_sched_policy(tc->task, psi->policy))
+               return;
        if (flag & PS_GROUP) {
                if (flag & (PS_LAST_RUN|PS_MSECS))
                        error(FATAL, "-G not supported with -%c option\n",
@@ -3336,7 +3361,7 @@ show_ps(ulong flag, struct psinfo *psi)
 
                tc = FIRST_CONTEXT();
                for (i = 0; i < RUNNING_TASKS(); i++, tc++)
-                       show_ps_data(flag, tc, NULL);
+                       show_ps_data(flag, tc, psi);
                
                return;
        }
@@ -3391,7 +3416,7 @@ show_ps(ulong flag, struct psinfo *psi)
                                if (flag & PS_TIMES) 
                                        show_task_times(tc, flag);
                                else
-                                       show_ps_data(flag, tc, NULL);
+                                       show_ps_data(flag, tc, psi);
                        }
                }
        }
@@ -3546,7 +3571,7 @@ show_milliseconds(struct task_context *tc, struct psinfo 
*psi)
        sprintf(format, "[%c%dll%c] ", '%', c, 
                pc->output_radix == 10 ? 'u' : 'x');
 
-       if (psi) {
+       if (psi && psi->cpus) {
                for (c = others = 0; c < kt->cpus; c++) {
                        if (!NUM_IN_BITMAP(psi->cpus, c))
                                continue;
@@ -5365,6 +5390,24 @@ task_flags(ulong task)
        return flags;
 }
 
+/*
+ * Return task's policy as bitmask bit.
+ */
+static ulong
+task_policy(ulong task)
+{
+       ulong policy = 0;
+
+       fill_task_struct(task);
+
+       if (!tt->last_task_read)
+               return policy;
+
+       policy = 1 << UINT(tt->task_struct + OFFSET(task_struct_policy));
+
+       return policy;
+}
+
 /*
  *  Return a task's tgid.
  */
@@ -5797,7 +5840,7 @@ cmd_foreach(void)
        BZERO(&foreach_data, sizeof(struct foreach_data));
        fd = &foreach_data;
 
-        while ((c = getopt(argcnt, args, "R:vomlgersStTpukcfFxhdaG")) != EOF) {
+        while ((c = getopt(argcnt, args, "R:vomlgersStTpukcfFxhdaGy:")) != 
EOF) {
                 switch(c)
                {
                case 'R':
@@ -5892,6 +5935,11 @@ cmd_foreach(void)
                        fd->flags |= FOREACH_G_FLAG;
                        break;
 
+               case 'y':
+                       fd->flags |= FOREACH_y_FLAG;
+                       fd->policy |= sched_policy_from_str(optarg);
+                       break;
+
                default:
                        argerrs++;
                        break;
@@ -6554,6 +6602,10 @@ foreach(struct foreach_data *fd)
                                        cmdflags |= PS_GROUP;
                                if (fd->flags & FOREACH_s_FLAG)
                                        cmdflags |= PS_KSTACKP;
+                               if (fd->flags & FOREACH_y_FLAG) {
+                                       cmdflags |= PS_POLICY;
+                                       psinfo.policy = fd->policy;
+                               }
                                /*
                                 * mutually exclusive flags
                                 */ 
@@ -7386,6 +7438,30 @@ is_kernel_thread(ulong task)
        return FALSE;
 }
 
+/*
+ * Checks if task policy corresponds to given mask.
+ */
+static int
+has_sched_policy(ulong task, ulong policy)
+{
+       return !!(task_policy(task) & policy);
+}
+
+/*
+ * Converts sched policy name into mask bit.
+ */
+static ulong
+sched_policy_from_str(char *policy_str)
+{
+       struct sched_policy_info *info = NULL;
+
+       for (info = sched_policy_info; info->name; info++)
+           if (strncmp(policy_str, info->name, strlen(info->name)) == 0)
+               return info->value;
+
+       return 1 << SCHED_NORMAL;
+}
+
 /*
  *  Gather an arry of pointers to the per-cpu idle tasks.  The tasklist
  *  argument must be at least the size of ulong[NR_CPUS].  There may be
-- 
2.14.2

--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to