Index: linux-2.6.11-rc3-ck1/kernel/sched.c
===================================================================
--- linux-2.6.11-rc3-ck1.orig/kernel/sched.c	2005-02-03 22:46:49.000000000 +1100
+++ linux-2.6.11-rc3-ck1/kernel/sched.c	2005-02-03 22:49:09.000000000 +1100
@@ -533,9 +533,9 @@ static void dequeue_task(struct task_str
 }
 
 /*
- * SCHED_ISO tasks are queued on both runqueues. Their actual priority is
- * either better than SCHED_NORMAL if below starvation limits, or
- * their underlying SCHED_NORMAL dynamic priority.
+ * SCHED_ISO tasks are queued on both runqueues, but are only ever queued
+ * from the iso_queue if we are below starvation limits, or there are no
+ * SCHED_NORMAL tasks waiting.
  */
 static void enqueue_iso_task(struct task_struct *p, runqueue_t *rq)
 {
@@ -660,6 +660,8 @@ static int effective_prio(task_t *p)
 	unsigned int best_burst, rr;
 	if (rt_task(p))
 		return p->prio;
+	if (iso_task(p))
+		return ISO_PRIO;
 	if (batch_task(p)) {
 		if (unlikely(p->flags & PF_UISLEEP)) {
 			/*
@@ -1001,21 +1003,14 @@ static void preempt(task_t *p, runqueue_
 {
 	int p_prio = p->prio, curr_prio = rq->curr->prio;
 
-	if (!iso_task(p) && !iso_task(rq->curr))
-		goto out;
-	if (!rq->iso_refractory) {
-		if (iso_task(p)) {
-			if (iso_task(rq->curr)) {
-				p_prio = -p->rt_priority;
-				curr_prio = -rq->curr->rt_priority;
-				goto out;
-			}
-			p_prio = ISO_PRIO;
-		}
-		if (iso_task(rq->curr))
-			curr_prio = ISO_PRIO;
+	if (iso_task(p) && iso_task(rq->curr)) {
+		/*
+		 * If both p and rq->curr are SCHED_ISO tasks use their
+		 * rt_priority to determine who will preempt.
+		 */
+		p_prio = ISO_PRIO - p->rt_priority;
+		curr_prio = ISO_PRIO - rq->curr->rt_priority;
 	}
-out:
 	if (p_prio > curr_prio)
 		return;
 	if (p_prio == curr_prio &&
@@ -2167,7 +2162,6 @@ static int wake_priority_sleeper(runqueu
 {
 	int ret = 0;
 #ifdef CONFIG_SCHED_SMT
-	spin_lock(&rq->lock);
 	/*
 	 * If an SMT sibling task has been put to sleep for priority
 	 * reasons reschedule the idle task to see if it can now run.
@@ -2176,7 +2170,6 @@ static int wake_priority_sleeper(runqueu
 		resched_task(rq->idle);
 		ret = 1;
 	}
-	spin_unlock(&rq->lock);
 #endif
 	return ret;
 }
@@ -2340,27 +2333,23 @@ static void time_slice_expired(task_t *p
 	enqueue_task(p, rq);
 }
 
-static inline void inc_iso_ticks(runqueue_t *rq, task_t *p)
+static inline void inc_iso_ticks(runqueue_t *rq)
 {
-	if (rq->iso_ticks < (iso_period * HZ * 100 - 99))
+	if (rq->iso_ticks < iso_period * HZ * 100 - 99)
 		rq->iso_ticks += 100;
-	spin_lock(&rq->lock);
-	if (!rq->iso_refractory && (rq->iso_ticks /
-		((iso_period * HZ) + 1) > iso_cpu))
+	if (!rq->iso_refractory && rq->iso_ticks /
+		(iso_period * HZ + 1) > iso_cpu)
 			rq->iso_refractory = 1;
-	spin_unlock(&rq->lock);
 }
 
-static inline void dec_iso_ticks(runqueue_t *rq, task_t *p)
+static inline void dec_iso_ticks(runqueue_t *rq)
 {
 	if (rq->iso_ticks)
-		rq->iso_ticks = rq->iso_ticks * (iso_period * HZ - 1) /
-			(iso_period * HZ);
-	spin_lock(&rq->lock);
-	if (rq->iso_refractory && (rq->iso_ticks /
-		((iso_period * HZ) + 1) < (iso_cpu * 9 / 10)))
+		rq->iso_ticks = rq->iso_ticks / 100 * iso_period * HZ /
+			(iso_period * HZ + 1) * 100;
+	if (rq->iso_refractory && rq->iso_ticks /
+		(iso_period * HZ + 1) < iso_cpu * 9 / 10)
 			rq->iso_refractory = 0;
-	spin_unlock(&rq->lock);
 }
 
 /*
@@ -2374,6 +2363,7 @@ void scheduler_tick(void)
 	task_t *p = current;
 	unsigned long debit;
 
+	spin_lock(&rq->lock);
 	rq->timestamp_last_tick = sched_clock();
 
 	/*
@@ -2383,13 +2373,14 @@ void scheduler_tick(void)
 	 * tasks only.
 	 */
 	if (rt_task(p) || (iso_task(p) && !rq->iso_refractory))
-		inc_iso_ticks(rq, p);
+		inc_iso_ticks(rq);
 	else
-		dec_iso_ticks(rq, p);
+		dec_iso_ticks(rq);
 
 	if (p == rq->idle) {
 		if (wake_priority_sleeper(rq))
-			goto out;
+			goto out_unlock;
+		spin_unlock(&rq->lock);
 		rebalance_tick(cpu, rq, SCHED_IDLE);
 		return;
 	}
@@ -2397,15 +2388,14 @@ void scheduler_tick(void)
 	/* Task might have expired already, but not scheduled off yet */
 	if (unlikely(!task_queued(p))) {
 		set_tsk_need_resched(p);
-		goto out;
+		goto out_unlock;
 	}
 	/*
 	 * SCHED_FIFO tasks never run out of timeslice.
 	 */
 	if (unlikely(p->policy == SCHED_FIFO))
-		goto out;
+		goto out_unlock;
 
-	spin_lock(&rq->lock);
 	debit = ns_diff(rq->timestamp_last_tick, p->timestamp);
 	p->ns_debit += debit;
 	if (p->ns_debit < NSJIFFY)
@@ -2451,13 +2441,12 @@ sched_normal:
 		set_tsk_need_resched(p);
 out_unlock:
 	spin_unlock(&rq->lock);
-out:
 	rebalance_tick(cpu, rq, NOT_IDLE);
 }
 
 static inline int iso_ready(runqueue_t *rq)
 {
-	if (rq->iso_running && !rq->iso_refractory)
+	if (!rq->iso_refractory || rq->iso_running == rq->nr_running)
 		return 1;
 	return 0;
 }
@@ -2465,14 +2454,24 @@ static inline int iso_ready(runqueue_t *
 /* Find the next SCHED_ISO task */
 static task_t* find_iso(runqueue_t *rq)
 {
-	int idx = find_first_bit(rq->iso_bitmap, MAX_USER_RT_PRIO);
-	return list_entry(rq->iso_queue[idx].next, task_t, iso_list);
+	int idx;
+	if (!rq->iso_refractory || rq->iso_running == rq->nr_running) {
+		idx = find_first_bit(rq->iso_bitmap, MAX_USER_RT_PRIO);
+		return list_entry(rq->iso_queue[idx].next, task_t, iso_list);
+	}
+
+	/* 
+	 * We're in the refractory period and SCHED_NORMAL tasks are waiting.
+	 * Find the next SCHED_NORMAL task.
+	 */
+	idx = find_next_bit(rq->bitmap, MAX_PRIO, ISO_PRIO);
+	return list_entry(rq->queue[idx].next, task_t, run_list);
 }
 
 static inline task_t* find_next_task(runqueue_t *rq)
 {
 	int idx = sched_find_first_bit(rq->bitmap);
-	if (unlikely(iso_ready(rq) && idx > ISO_PRIO))
+	if (unlikely(idx == ISO_PRIO))
 		return find_iso(rq);
 	return list_entry(rq->queue[idx].next, task_t, run_list);
 }
