Index: linux-2.6.9-rc4-mm1/include/linux/init_task.h
===================================================================
--- linux-2.6.9-rc4-mm1.orig/include/linux/init_task.h	2004-10-17 20:02:32.394280945 +1000
+++ linux-2.6.9-rc4-mm1/include/linux/init_task.h	2004-10-17 20:14:27.329142278 +1000
@@ -72,8 +72,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.9-rc4-mm1/include/linux/sched.h
===================================================================
--- linux-2.6.9-rc4-mm1.orig/include/linux/sched.h	2004-10-17 20:14:25.104488174 +1000
+++ linux-2.6.9-rc4-mm1/include/linux/sched.h	2004-10-17 20:14:27.330142123 +1000
@@ -128,9 +128,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)
@@ -350,9 +351,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.9-rc4-mm1/init/main.c
===================================================================
--- linux-2.6.9-rc4-mm1.orig/init/main.c	2004-10-17 20:02:32.392281256 +1000
+++ linux-2.6.9-rc4-mm1/init/main.c	2004-10-17 20:14:27.331141967 +1000
@@ -693,7 +693,7 @@ static inline void fixup_cpu_present_map
 static int init(void * unused)
 {
 	lock_kernel();
-	current->prio = MAX_PRIO - 1;
+	current->prio = MAX_PRIO - 2;
 	/*
 	 * Tell the world that we're going to be the grim
 	 * reaper of innocent orphaned children.
Index: linux-2.6.9-rc4-mm1/kernel/sched.c
===================================================================
--- linux-2.6.9-rc4-mm1.orig/kernel/sched.c	2004-10-17 20:14:25.106487864 +1000
+++ linux-2.6.9-rc4-mm1/kernel/sched.c	2004-10-17 20:14:27.333141656 +1000
@@ -54,7 +54,7 @@
 
 /*
  * Convert user-nice values [ -20 ... 0 ... 19 ]
- * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
+ * to static priority [ MAX_RT_PRIO..MAX_PRIO-2 ],
  * and back.
  */
 #define NICE_TO_PRIO(nice)	(MAX_RT_PRIO + (nice) + 20)
@@ -64,7 +64,7 @@
 /*
  * 'User priority' is the nice value converted to something we
  * can work with better when scaling various scheduler parameters,
- * it's a [ 0 ... 39 ] range.
+ * it's a [ 0 ... 40 ] range.
  */
 #define USER_PRIO(p)		((p)-MAX_RT_PRIO)
 #define TASK_USER_PRIO(p)	USER_PRIO((p)->static_prio)
@@ -565,6 +565,8 @@ static unsigned int rr_interval(task_t *
 
 	if (nice < 0 && !rt_task(p))
 		rr_interval += -(nice);
+	if (batch_task(p))
+		rr_interval *= 10;
 	return rr_interval;
 }
 
@@ -581,6 +583,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);
@@ -591,13 +604,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;
 }
 
@@ -2078,7 +2091,7 @@ void scheduler_tick(int user_ticks, int 
 		rebalance_tick(cpu, rq, SCHED_IDLE);
 		return;
 	}
-	if (TASK_NICE(p) > 0)
+	if (TASK_NICE(p) > 0 || batch_task(p))
 		cpustat->nice += user_ticks;
 	else
 		cpustat->user += user_ticks;
@@ -2216,8 +2229,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;
 
 		/*
@@ -2226,8 +2240,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);
 	}
@@ -2925,8 +2940,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);
@@ -3103,6 +3119,12 @@ static int setscheduler(pid_t pid, int p
 	    !capable(CAP_SYS_NICE))
 		goto out_unlock;
 
+	if (!(p->mm) && policy == SCHED_BATCH)
+		/*
+		 * Don't allow kernel threads to be SCHED_BATCH.
+		 */
+		goto out_unlock;
+
 	retval = security_task_setscheduler(p, policy, &lp);
 	if (retval)
 		goto out_unlock;
@@ -3371,9 +3393,9 @@ asmlinkage long sys_sched_yield(void)
 	dequeue_task(current, rq);
 	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;
-		current->prio = MAX_PRIO - 1;
+		current->prio = MAX_PRIO - 2;
 	}
 	enqueue_task(current, rq);
 
@@ -3517,6 +3539,7 @@ asmlinkage long sys_sched_get_priority_m
 		ret = MAX_USER_RT_PRIO-1;
 		break;
 	case SCHED_NORMAL:
+	case SCHED_BATCH:
 		ret = 0;
 		break;
 	}
@@ -3540,6 +3563,7 @@ asmlinkage long sys_sched_get_priority_m
 		ret = 1;
 		break;
 	case SCHED_NORMAL:
+	case SCHED_BATCH:
 		ret = 0;
 	}
 	return ret;

