---
 kernel/sched.c     |   48 +++++++++++++++++++++++-------------------------
 kernel/workqueue.c |    2 --
 2 files changed, 23 insertions(+), 27 deletions(-)

Index: linux-2.6.21-rc3-rsdl/kernel/sched.c
===================================================================
--- linux-2.6.21-rc3-rsdl.orig/kernel/sched.c	2007-03-11 15:04:09.000000000 +1100
+++ linux-2.6.21-rc3-rsdl/kernel/sched.c	2007-03-11 15:05:37.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.28
+ *		RSDL v0.29
  */
 
 #include <linux/mm.h>
@@ -91,12 +91,14 @@ unsigned long long __attribute__((weak))
 /*
  * Preemption needs to take into account that a low priority task can be
  * at a higher prio due to list merging. Its priority is artificially
- * elevated and it should be preempted if anything higher priority wakes up.
+ * elevated and it should be preempted if anything higher priority wakes up
+ * provided it is not a realtime comparison.
  */
 #define TASK_PREEMPTS_CURR(p, curr) \
 	(((p)->prio < (curr)->prio) || (((p)->prio == (curr)->prio) && \
 		((p)->static_prio < (curr)->static_prio && \
-			((curr)->static_prio > (curr)->prio))))
+			((curr)->static_prio > (curr)->prio)) && \
+				!rt_task(p)))
 
 /*
  * This is the time all tasks within the same priority round robin.
@@ -2032,10 +2034,6 @@ static void pull_task(struct rq *src_rq,
 	enqueue_task(p, this_rq);
 	p->timestamp = (p->timestamp - src_rq->most_recent_timestamp)
 				+ this_rq->most_recent_timestamp;
-	/*
-	 * Note that idle threads have a prio of MAX_PRIO, for this test
-	 * to be always true for them.
-	 */
 	try_preempt(p, this_rq);
 }
 
@@ -3096,9 +3094,19 @@ static inline void major_prio_rotation(s
  */
 static inline void rotate_runqueue_priority(struct rq *rq)
 {
-	int new_prio_level, remaining_quota = rq_quota(rq, rq->prio_level);
-	struct prio_array *array = rq->active;
+	int new_prio_level, remaining_quota;
+	struct prio_array *array;
+
+	/*
+	 * Make sure we don't have tasks still on the active array that
+	 * haven't run due to not preempting a lower priority task. This can
+	 * happen on list merging or smp balancing.
+	 */
+	if (unlikely(sched_find_first_bit(rq->dyn_bitmap) < rq->prio_level))
+		return;
 
+	remaining_quota = rq_quota(rq, rq->prio_level);
+	array = rq->active;
 	if (rq->prio_level > MAX_PRIO - 2) {
 		/* Major rotation required */
 		struct prio_array *new_queue = rq->expired;
@@ -4424,29 +4432,19 @@ asmlinkage long sys_sched_getaffinity(pi
  * sys_sched_yield - yield the current processor to other threads.
  *
  * This function yields the current CPU by moving the calling thread
- * to the expired array.
+ * to the end of its current priority queue. If there are no other
+ * threads running on this cpu this function will return.
  */
 asmlinkage long sys_sched_yield(void)
 {
 	struct rq *rq = this_rq_lock();
 	struct task_struct *p = current;
-	struct prio_array *old_array = p->array;
-	int old_prio = p->prio;
 
 	schedstat_inc(rq, yld_cnt);
-	/*
-	 * We implement yielding by moving the task into the expired
-	 * queue.
-	 *
-	 * (special rule: RT tasks will just roundrobin in the active
-	 *  array.)
-	 */
-	if (!rt_task(p)) {
-		p->array = rq->expired;
-		p->prio = p->static_prio;
-		bitmap_zero(p->bitmap, PRIO_RANGE);
-	}
-	requeue_task(p, rq, old_array, old_prio);
+	if (rq->nr_running == 1)
+		schedstat_inc(rq, yld_both_empty);
+	else
+		list_move_tail(&p->run_list, p->array->queue + p->prio);
 
 	/*
 	 * Since we are going to call schedule() anyway, there's
Index: linux-2.6.21-rc3-rsdl/kernel/workqueue.c
===================================================================
--- linux-2.6.21-rc3-rsdl.orig/kernel/workqueue.c	2007-03-11 15:04:09.000000000 +1100
+++ linux-2.6.21-rc3-rsdl/kernel/workqueue.c	2007-03-11 15:05:25.000000000 +1100
@@ -355,8 +355,6 @@ static int worker_thread(void *__cwq)
 	if (!cwq->freezeable)
 		current->flags |= PF_NOFREEZE;
 
-	set_user_nice(current, -5);
-
 	/* Block and flush all signals */
 	sigfillset(&blocked);
 	sigprocmask(SIG_BLOCK, &blocked, NULL);
