diff --git a/defs.h b/defs.h
index 76e5512..4b4e331 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 {       
@@ -1992,6 +1994,7 @@ struct offset_table {                    /* stash of commonly-used offsets */
 	long mod_arch_specific_num_orcs;
 	long mod_arch_specific_orc_unwind_ip;
 	long mod_arch_specific_orc_unwind;
+	long task_struct_policy;
 };
 
 struct size_table {         /* stash of commonly-used sizes */
@@ -2141,6 +2144,7 @@ struct size_table {         /* stash of commonly-used sizes */
 	long sk_buff_head_qlen;
 	long sk_buff_len;
 	long orc_entry;
+	long task_struct_policy;
 };
 
 struct array_table {
@@ -4576,6 +4580,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_)
@@ -4603,6 +4614,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)
 
@@ -4620,6 +4632,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))
@@ -4823,7 +4836,7 @@ char *strip_ending_char(char *, char);
 char *strip_beginning_char(char *, char);
 char *strip_comma(char *);
 char *strip_hex(char *);
-char *upper_case(char *, char *);
+char *upper_case(const char *, char *);
 char *first_nonspace(char *);
 char *first_space(char *);
 char *replace_string(char *, char *, char);
diff --git a/help.c b/help.c
index f9c5792..efa55e0 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|-y policy] [-s] [-p|-c|-t|-[l|m][-C cpu]|-a|-g|-r|-S]\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",
@@ -1267,6 +1267,16 @@ char *help_ps[] = {
 "        -k  restrict the output to only kernel threads.",
 "        -u  restrict the output to only user tasks.",
 "        -G  display only the thread group leader in a thread group.",
+" -y policy  restrict the output to tasks having a specified scheduling policy",
+"            expressed by its integer value or by its (case-insensitive) name;",
+"            multiple policies may be entered in a comma-separated list:",
+"              0 or NORMAL",
+"              1 or FIFO",
+"              2 or RR",
+"              3 or BATCH",
+"              4 or ISO",
+"              5 or IDLE",
+"              6 or DEADLINE",
 " ",
 "  The process identifier types may be mixed.  For each task, the following",
 "  items are displayed:",
diff --git a/symbols.c b/symbols.c
index b2f2796..f7599e8 100644
--- a/symbols.c
+++ b/symbols.c
@@ -8584,6 +8584,8 @@ dump_offset_table(char *spec, ulong makestruct)
                 OFFSET(task_struct_prio));
         fprintf(fp, "             task_struct_on_rq: %ld\n",
                 OFFSET(task_struct_on_rq));
+        fprintf(fp, "            task_struct_policy: %ld\n",
+                OFFSET(task_struct_policy));
 
 	fprintf(fp, "              thread_info_task: %ld\n",
                 OFFSET(thread_info_task));
@@ -10211,6 +10213,7 @@ dump_offset_table(char *spec, ulong makestruct)
         fprintf(fp, "                       pt_regs: %ld\n", SIZE(pt_regs));
         fprintf(fp, "                   task_struct: %ld\n", SIZE(task_struct));
         fprintf(fp, "             task_struct_flags: %ld\n", SIZE(task_struct_flags));
+        fprintf(fp, "            task_struct_policy: %ld\n", SIZE(task_struct_policy));
         fprintf(fp, "                   thread_info: %ld\n", SIZE(thread_info));
         fprintf(fp, "                 softirq_state: %ld\n", 
 		SIZE(softirq_state));
diff --git a/task.c b/task.c
index 362822c..ab33211 100644
--- a/task.c
+++ b/task.c
@@ -109,6 +109,24 @@ 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, ulong);
+static ulong task_policy(ulong);
+static ulong sched_policy_bit_from_str(const char *);
+static ulong make_sched_policy(const char *);
+
+static struct sched_policy_info {
+	ulong value;
+	char *name;
+} sched_policy_info[] = {
+	{ SCHED_NORMAL,		"NORMAL" },
+	{ SCHED_FIFO,		"FIFO" },
+	{ SCHED_RR,		"RR" },
+	{ SCHED_BATCH,		"BATCH" },
+	{ SCHED_ISO,		"ISO" },
+	{ SCHED_IDLE,		"IDLE" },
+	{ SCHED_DEADLINE,	"DEADLINE" },
+	{ ULONG_MAX,		NULL }
+};
 
 /*
  *  Figure out how much space will be required to hold the task context
@@ -273,6 +291,8 @@ task_init(void)
 	MEMBER_OFFSET_INIT(task_struct_next_run, "task_struct", "next_run");
 	MEMBER_OFFSET_INIT(task_struct_flags, "task_struct", "flags");
 	MEMBER_SIZE_INIT(task_struct_flags, "task_struct", "flags");
+	MEMBER_OFFSET_INIT(task_struct_policy, "task_struct", "policy");
+	MEMBER_SIZE_INIT(task_struct_policy, "task_struct", "policy");
         MEMBER_OFFSET_INIT(task_struct_pidhash_next,
                 "task_struct", "pidhash_next");
 	MEMBER_OFFSET_INIT(task_struct_pgrp, "task_struct", "pgrp");
@@ -2974,7 +2994,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 +3095,11 @@ cmd_ps(void)
 			make_cpumask(cpuspec, psinfo.cpus, FAULT_ON_ERROR, NULL);
 			break;
 
+		case 'y':
+			flag |= PS_POLICY;
+			psinfo.policy = make_sched_policy(optarg);
+			break;
+
 		default:
 			argerrs++;
 			break;
@@ -3218,6 +3243,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 +3363,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 +3418,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 +3573,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;
@@ -5366,6 +5393,27 @@ task_flags(ulong task)
 }
 
 /*
+ * 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;
+
+	if (SIZE(task_struct_policy) == sizeof(unsigned int))
+		policy = 1 << UINT(tt->task_struct + OFFSET(task_struct_policy));
+	else
+		policy = 1 << ULONG(tt->task_struct + OFFSET(task_struct_policy));
+
+	return policy;
+}
+
+/*
  *  Return a task's tgid.
  */
 ulong
@@ -5797,7 +5845,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 +5940,11 @@ cmd_foreach(void)
 			fd->flags |= FOREACH_G_FLAG;
 			break;
 
+		case 'y':
+			fd->flags |= FOREACH_y_FLAG;
+			fd->policy = make_sched_policy(optarg);
+			break;
+
 		default:
 			argerrs++;
 			break;
@@ -6554,6 +6607,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
 				 */ 
@@ -7389,6 +7446,70 @@ is_kernel_thread(ulong task)
 }
 
 /*
+ * 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_bit_from_str(const char *policy_str)
+{
+	struct sched_policy_info *info = NULL;
+	ulong policy = 0;
+	int found = 0;
+	char *upper = NULL;
+	char digit[2] = { 0, 0 };
+
+	upper = GETBUF(strlen(policy_str) + 1);
+	upper_case(policy_str, upper);
+	for (info = sched_policy_info; info->name; info++) {
+		snprintf(digit, sizeof digit, "%lu", info->value);
+		if (strncmp(upper, info->name, strlen(info->name)) == 0 ||
+			strncmp(upper, digit, sizeof digit) == 0) {
+			policy = 1 << info->value;
+			found = 1;
+			break;
+		}
+	}
+
+	FREEBUF(upper);
+
+	if (!found)
+		error(FATAL,
+			"%s: invalid scheduling policy\n", policy_str);
+
+	return policy;
+}
+
+/*
+ * Converts sched policy string set into bitmask.
+ */
+static ulong
+make_sched_policy(const char *policy_str)
+{
+	ulong policy = 0;
+	char *iter = NULL;
+	char *orig = NULL;
+	char *cur = NULL;
+
+	iter = STRDUPBUF(policy_str);
+	orig = iter;
+
+	while ((cur = strsep(&iter, ",")))
+		policy |= sched_policy_bit_from_str(cur);
+
+	FREEBUF(orig);
+
+	return policy;
+}
+
+/*
  *  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
  *  junk in everything after the first entry on a single CPU box, so the
diff --git a/tools.c b/tools.c
index 886d7fb..186b703 100644
--- a/tools.c
+++ b/tools.c
@@ -423,9 +423,10 @@ strip_hex(char *line)
  *  Turn a string into upper-case.
  */
 char *
-upper_case(char *s, char *buf)
+upper_case(const char *s, char *buf)
 {
-	char *p1, *p2;
+	const char *p1;
+	char *p2;
 
 	p1 = s;
 	p2 = buf;
