--- 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 @@ -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);