---
 kernel/sched.c |   61 ++++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 43 insertions(+), 18 deletions(-)

Index: linux-2.6.21-rc3-rsdl/kernel/sched.c
===================================================================
--- linux-2.6.21-rc3-rsdl.orig/kernel/sched.c	2007-03-09 01:06:08.000000000 +1100
+++ linux-2.6.21-rc3-rsdl/kernel/sched.c	2007-03-10 18:47:38.000000000 +1100
@@ -17,7 +17,7 @@
  *  2003-09-03	Interactivity tuning by Con Kolivas.
  *  2004-04-02	Scheduler domains code by Nick Piggin
  *  2007-03-02	Rotating Staircase deadline scheduling policy by Con Kolivas
- *		RSDL v0.27
+ *		RSDL v0.28
  */
 
 #include <linux/mm.h>
@@ -681,6 +681,15 @@ static inline void task_new_array(struct
 	p->rotation = rq->prio_rotation;
 }
 
+static inline void queue_expired(struct task_struct *p, struct rq *rq)
+{
+	p->prio = p->normal_prio = p->static_prio;
+	p->array = rq->expired;
+	bitmap_zero(p->bitmap, PRIO_RANGE);
+	p->rotation = rq->prio_rotation;
+	p->time_slice = p->quota;
+}
+
 #define rq_quota(rq, prio)	((rq)->prio_quota[USER_PRIO(prio)])
 /*
  * recalc_task_prio determines what prio a non rt_task will be
@@ -698,9 +707,15 @@ static void recalc_task_prio(struct task
 	struct prio_array *array = rq->active;
 	int queue_prio, search_prio;
 
-	if (p->rotation == rq->prio_rotation && p->array == array) {
-		if (p->time_slice && rq_quota(rq, p->prio))
+	if (p->rotation == rq->prio_rotation) {
+		if (p->array == array) {
+			if (p->time_slice && rq_quota(rq, p->prio))
+				return;
+		} else if (p->array == rq->expired) {
+			queue_expired(p, rq);
 			return;
+		} else
+			task_new_array(p, rq);
 	} else
 		task_new_array(p, rq);
 	search_prio = p->static_prio;
@@ -716,11 +731,10 @@ static void recalc_task_prio(struct task
 	queue_prio = SCHED_PRIO(find_next_zero_bit(p->bitmap, PRIO_RANGE,
 		     USER_PRIO(search_prio)));
 	if (queue_prio == MAX_PRIO) {
-		queue_prio = p->static_prio;
-		array = rq->expired;
-		bitmap_zero(p->bitmap, PRIO_RANGE);
-	} else
-		rq_quota(rq, queue_prio) += p->quota;
+		queue_expired(p, rq);
+		return;
+	}
+	rq_quota(rq, queue_prio) += p->quota;
 	p->prio = p->normal_prio = queue_prio;
 	p->array = array;
 	set_task_entitlement(p);
@@ -1329,12 +1343,23 @@ static inline int wake_idle(int cpu, str
 }
 #endif
 
+/*
+ * We need to have a special definition for an idle runqueue when testing
+ * for preemption on CONFIG_HOTPLUG_CPU as the idle task may be scheduled as
+ * a realtime task in sched_idle_next.
+ */
+#ifdef CONFIG_HOTPLUG_CPU
+#define rq_idle(rq)	((rq)->curr == (rq)->idle && !rt_task((rq)->curr))
+#else
+#define rq_idle(rq)	((rq)->curr == (rq)->idle)
+#endif
+
 static inline int task_preempts_curr(struct task_struct *p, struct rq *rq)
 {
 	struct task_struct *curr = rq->curr;
 
 	return ((p->array == task_rq(p)->active &&
-		TASK_PREEMPTS_CURR(p, curr)) || curr == rq->idle);
+		TASK_PREEMPTS_CURR(p, curr)) || rq_idle(rq));
 }
 
 static inline void try_preempt(struct task_struct *p, struct rq *rq)
@@ -1512,7 +1537,7 @@ int fastcall wake_up_state(struct task_s
 	return try_to_wake_up(p, state, 0);
 }
 
-static void task_expired_entitlement(struct rq *rq, struct task_struct *p);
+static void task_running_tick(struct rq *rq, struct task_struct *p);
 /*
  * Perform scheduler related setup for a newly forked process p.
  * p is forked by current.
@@ -1573,10 +1598,8 @@ void fastcall sched_fork(struct task_str
 		 * left from its timeslice. Taking the runqueue lock is not
 		 * a problem.
 		 */
-		struct rq *rq = __task_rq_lock(current);
-
-		task_expired_entitlement(rq, current);
-		__task_rq_unlock(rq);
+		current->time_slice = 1;
+		task_running_tick(cpu_rq(cpu), current);
 	}
 	local_irq_enable();
 out:
@@ -3222,8 +3245,9 @@ static noinline int rq_bitmap_error(stru
 	struct list_head *queue;
 	int idx, test_idx;
 
-	if (!bitmap_error++)
-		printk(KERN_ERR "Scheduler bitmap error - bitmap being reconstructed..\n");
+	printk(KERN_ERR
+	       "SCHEDULER BITMAP ERROR %d - attempting to reconstruct...\n",
+	       ++bitmap_error);
 	for (test_idx = MAX_RT_PRIO ; test_idx < MAX_DYN_PRIO ; test_idx++) {
 		if (test_idx < MAX_PRIO) {
 			idx = test_idx;
@@ -3240,6 +3264,7 @@ static noinline int rq_bitmap_error(stru
 		}
 	}
 	idx = find_next_bit(rq->dyn_bitmap, MAX_DYN_PRIO, MAX_RT_PRIO);
+	/* We hit a real bug. There is no way out of this */
 	BUG_ON(idx == MAX_DYN_PRIO);
 	return idx;
 }
@@ -4763,7 +4788,7 @@ void __cpuinit init_idle(struct task_str
 	bitmap_zero(idle->bitmap, PRIO_RANGE + 1);
 	idle->timestamp = sched_clock();
 	idle->array = NULL;
-	idle->prio = idle->normal_prio = MAX_PRIO;
+	idle->prio = idle->normal_prio = NICE_TO_PRIO(0);
 	idle->state = TASK_RUNNING;
 	idle->cpus_allowed = cpumask_of_cpu(cpu);
 	set_task_cpu(idle, cpu);
@@ -5182,7 +5207,7 @@ migration_call(struct notifier_block *nf
 		/* Idle task back to normal (off runqueue, low prio) */
 		rq = task_rq_lock(rq->idle, &flags);
 		deactivate_task(rq->idle, rq);
-		rq->idle->static_prio = MAX_PRIO;
+		rq->idle->static_prio = NICE_TO_PRIO(0);
 		__setscheduler(rq->idle, SCHED_NORMAL, 0);
 		migrate_dead_tasks(cpu);
 		task_rq_unlock(rq, &flags);
