Index: linux-2.6.12-rc6-ck2/include/linux/init_task.h
===================================================================
--- linux-2.6.12-rc6-ck2.orig/include/linux/init_task.h	2005-06-07 21:23:26.000000000 +1000
+++ linux-2.6.12-rc6-ck2/include/linux/init_task.h	2005-06-11 22:18:44.000000000 +1000
@@ -74,8 +74,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.12-rc6-ck2/include/linux/sched.h
===================================================================
--- linux-2.6.12-rc6-ck2.orig/include/linux/sched.h	2005-06-11 22:18:44.000000000 +1000
+++ linux-2.6.12-rc6-ck2/include/linux/sched.h	2005-06-11 22:18:44.000000000 +1000
@@ -133,9 +133,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)
@@ -402,9 +403,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.12-rc6-ck2/kernel/power/process.c
===================================================================
--- linux-2.6.12-rc6-ck2.orig/kernel/power/process.c	2004-12-25 10:14:51.000000000 +1100
+++ linux-2.6.12-rc6-ck2/kernel/power/process.c	2005-06-11 22:18:44.000000000 +1000
@@ -68,6 +68,13 @@ int freeze_processes(void)
 		read_lock(&tasklist_lock);
 		do_each_thread(g, p) {
 			unsigned long flags;
+			if (batch_task(p))
+				p->flags |= PF_NONSLEEP;
+				/*
+				 * This will make batch tasks scheduler as
+				 * SCHED_NORMAL to hopefully allow them to be
+				 * frozen.
+				 */
 			if (!freezeable(p))
 				continue;
 			if ((p->flags & PF_FROZEN) ||
Index: linux-2.6.12-rc6-ck2/kernel/sched.c
===================================================================
--- linux-2.6.12-rc6-ck2.orig/kernel/sched.c	2005-06-11 22:18:44.000000000 +1000
+++ linux-2.6.12-rc6-ck2/kernel/sched.c	2005-06-11 22:18:44.000000000 +1000
@@ -585,6 +585,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_NONSLEEP)) {
+			/*
+			 * If batch is waking up from in kernel activity
+			 * 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);
@@ -595,13 +606,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;
 }
 
@@ -2148,7 +2159,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);
@@ -2397,6 +2408,8 @@ static inline int dependent_sleeper(int 
 			if (((smt_curr->slice * (100 - sd->per_cpu_gain) /
 				100) > slice(p)))
 					ret = 1;
+		if (batch_task(p) && !batch_task(smt_curr))
+			ret = 1;
 
 check_smt_task:
 		if ((!smt_curr->mm && smt_curr != smt_rq->idle) ||
@@ -2407,6 +2420,11 @@ check_smt_task:
 			continue;
 		}
 
+		if (batch_task(smt_curr) && !batch_task(p)) {
+			resched_task(smt_curr);
+			continue;
+		}
+
 		/*
 		 * Reschedule a lower priority task on the SMT sibling,
 		 * or wake it up if it has been put to sleep for priority
@@ -3059,8 +3077,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);
@@ -3234,6 +3253,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;
@@ -3527,9 +3552,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) {
@@ -3675,6 +3700,7 @@ asmlinkage long sys_sched_get_priority_m
 		ret = MAX_USER_RT_PRIO-1;
 		break;
 	case SCHED_NORMAL:
+	case SCHED_BATCH:
 		ret = 0;
 		break;
 	}
@@ -3698,6 +3724,7 @@ asmlinkage long sys_sched_get_priority_m
 		ret = 1;
 		break;
 	case SCHED_NORMAL:
+	case SCHED_BATCH:
 		ret = 0;
 	}
 	return ret;

