Index: linux-2.6.11-rc3-ck1/include/linux/init_task.h
===================================================================
--- linux-2.6.11-rc3-ck1.orig/include/linux/init_task.h	2005-02-03 21:41:29.000000000 +1100
+++ linux-2.6.11-rc3-ck1/include/linux/init_task.h	2005-02-03 21:44:42.536794631 +1100
@@ -73,8 +73,8 @@ extern struct group_info init_groups;
 	.usage		= ATOMIC_INIT(2),				\
 	.flags		= 0,						\
 	.lock_depth	= -1,						\
-	.prio		= MAX_PRIO-20,					\
-	.static_prio	= MAX_PRIO-20,					\
+	.prio		= MAX_PRIO-21,					\
+	.static_prio	= MAX_PRIO-21,					\
 	.policy		= SCHED_NORMAL,					\
 	.cpus_allowed	= CPU_MASK_ALL,					\
 	.mm		= NULL,						\
Index: linux-2.6.11-rc3-ck1/include/linux/sched.h
===================================================================
--- linux-2.6.11-rc3-ck1.orig/include/linux/sched.h	2005-02-03 21:44:33.574258306 +1100
+++ linux-2.6.11-rc3-ck1/include/linux/sched.h	2005-02-03 21:44:42.537794467 +1100
@@ -130,9 +130,10 @@ extern unsigned long nr_iowait(void);
 #define SCHED_NORMAL		0
 #define SCHED_FIFO		1
 #define SCHED_RR		2
+#define SCHED_BATCH		3
 
 #define SCHED_MIN		0
-#define SCHED_MAX		2
+#define SCHED_MAX		3
 
 #define SCHED_RANGE(policy)	((policy) >= SCHED_MIN && \
 					(policy) <= SCHED_MAX)
@@ -365,9 +366,10 @@ struct signal_struct {
 #define MAX_USER_RT_PRIO	100
 #define MAX_RT_PRIO		MAX_USER_RT_PRIO
 
-#define MAX_PRIO		(MAX_RT_PRIO + 40)
+#define MAX_PRIO		(MAX_RT_PRIO + 41)
 
 #define rt_task(p)		(unlikely((p)->prio < MAX_RT_PRIO))
+#define batch_task(p)		((p)->policy == SCHED_BATCH)
 
 /*
  * Some day this will be a full-fledged user tracking system..
Index: linux-2.6.11-rc3-ck1/kernel/power/process.c
===================================================================
--- linux-2.6.11-rc3-ck1.orig/kernel/power/process.c	2004-12-25 10:14:51.000000000 +1100
+++ linux-2.6.11-rc3-ck1/kernel/power/process.c	2005-02-03 21:44:42.538794304 +1100
@@ -68,6 +68,12 @@ int freeze_processes(void)
 		read_lock(&tasklist_lock);
 		do_each_thread(g, p) {
 			unsigned long flags;
+			if (batch_task(p))
+				p->flags |= PF_UISLEEP;
+				/*
+				 * This will make batch tasks scheduler as
+				 * SCHED_NORMAL to allow them to be frozen.
+				 */
 			if (!freezeable(p))
 				continue;
 			if ((p->flags & PF_FROZEN) ||
Index: linux-2.6.11-rc3-ck1/kernel/sched.c
===================================================================
--- linux-2.6.11-rc3-ck1.orig/kernel/sched.c	2005-02-03 21:44:33.576257979 +1100
+++ linux-2.6.11-rc3-ck1/kernel/sched.c	2005-02-03 21:44:42.540793977 +1100
@@ -608,6 +608,17 @@ static int effective_prio(task_t *p)
 	unsigned int best_burst, rr;
 	if (rt_task(p))
 		return p->prio;
+	if (batch_task(p)) {
+		if (unlikely(p->flags & PF_UISLEEP)) {
+			/*
+			 * If batch is waking up from uninterruptible sleep
+			 * reschedule at a normal priority to begin with.
+			 */
+			p->flags |= PF_YIELDED;
+			return MAX_PRIO - 2;
+		}
+		return MAX_PRIO - 1;
+	}
 
 	best_burst = burst(p);
 	full_slice = slice(p);
@@ -618,13 +629,13 @@ static int effective_prio(task_t *p)
 	first_slice = rr;
 	if (sched_interactive && !sched_compute && p->mm)
 		first_slice *= (p->burst + 1);
-	prio = MAX_PRIO - 1 - best_burst;
+	prio = MAX_PRIO - 2 - best_burst;
 
 	if (used_slice < first_slice)
 		return prio;
 	prio += 1 + (used_slice - first_slice) / rr;
-	if (prio >= MAX_PRIO - 1)
-		prio = MAX_PRIO - 1;
+	if (prio >= MAX_PRIO - 2)
+		prio = MAX_PRIO - 2;
 	return prio;
 }
 
@@ -2188,7 +2199,7 @@ void account_user_time(struct task_struc
 
 	/* Add user time to cpustat. */
 	tmp = cputime_to_cputime64(cputime);
-	if (TASK_NICE(p) > 0)
+	if (TASK_NICE(p) > 0 || batch_task(p))
 		cpustat->nice = cputime64_add(cpustat->nice, tmp);
 	else
 		cpustat->user = cputime64_add(cpustat->user, tmp);
@@ -2412,8 +2423,9 @@ static int dependent_sleeper(int this_cp
 		 * physical cpu's resources. -ck
 		 */
 		if (((smt_curr->slice * (100 - sd->per_cpu_gain) / 100) >
-			slice(p) || rt_task(smt_curr)) &&
-			p->mm && smt_curr->mm && !rt_task(p))
+			slice(p) || rt_task(smt_curr) || batch_task(p)) &&
+			p->mm && smt_curr->mm && !rt_task(p) &&
+			!batch_task(smt_curr))
 				ret = 1;
 
 		/*
@@ -2422,8 +2434,9 @@ static int dependent_sleeper(int this_cp
 		 * reasons.
 		 */
 		if ((((p->slice * (100 - sd->per_cpu_gain) / 100) > 
-			slice(smt_curr) || rt_task(p)) && 
-			smt_curr->mm && p->mm && !rt_task(smt_curr)) ||
+			slice(smt_curr) || rt_task(p) || batch_task(smt_curr)) && 
+			smt_curr->mm && p->mm && !rt_task(smt_curr) &&
+			!batch_task(p)) ||
 			(smt_curr == smt_rq->idle && smt_rq->nr_running))
 				resched_task(smt_curr);
 	}
@@ -3059,8 +3072,9 @@ void set_user_nice(task_t *p, long nice)
 		 * If the task increased its priority or is running and
 		 * lowered its priority, then reschedule its CPU:
 		 */
-		if (delta < 0 || (delta > 0 && task_running(rq, p)))
-			resched_task(rq->curr);
+		if (delta < 0 || ((delta > 0 || batch_task(p)) &&
+			task_running(rq, p)))
+				resched_task(rq->curr);
 	}
 out_unlock:
 	task_rq_unlock(rq, &flags);
@@ -3220,6 +3234,12 @@ recheck:
 	    !capable(CAP_SYS_NICE))
 		return -EPERM;
 
+	if (!(p->mm) && policy == SCHED_BATCH)
+		/*
+		 * Don't allow kernel threads to be SCHED_BATCH.
+		 */
+		return -EINVAL;
+
 	retval = security_task_setscheduler(p, policy, param);
 	if (retval)
 		return retval;
@@ -3510,9 +3530,9 @@ asmlinkage long sys_sched_yield(void)
 	schedstat_inc(rq, yld_cnt);
 	current->slice = slice(current);
 	current->time_slice = rr_interval(current);
-	if (likely(!rt_task(current))) {
+	if (likely(!rt_task(current) && !batch_task(current))) {
 		current->flags |= PF_YIELDED;
-		newprio = MAX_PRIO - 1;
+		newprio = MAX_PRIO - 2;
 	}
 
 	if (newprio != current->prio) {
@@ -3661,6 +3681,7 @@ asmlinkage long sys_sched_get_priority_m
 		ret = MAX_USER_RT_PRIO-1;
 		break;
 	case SCHED_NORMAL:
+	case SCHED_BATCH:
 		ret = 0;
 		break;
 	}
@@ -3684,6 +3705,7 @@ asmlinkage long sys_sched_get_priority_m
 		ret = 1;
 		break;
 	case SCHED_NORMAL:
+	case SCHED_BATCH:
 		ret = 0;
 	}
 	return ret;

