From: Robert Love Basically, the problem is that setscheduler() does not set need_resched when needed. There are two basic cases where this is needed: - the task is running, but now it is no longer the highest priority task on the rq - the task is not running, but now it is the highest priority task on the rq In either case, we need to set need_resched to invoke the scheduler. kernel/sched.c | 15 ++++++++++++++- 1 files changed, 14 insertions(+), 1 deletion(-) diff -puN kernel/sched.c~setscheduler-fix kernel/sched.c --- 25/kernel/sched.c~setscheduler-fix 2003-06-19 21:03:12.000000000 -0700 +++ 25-akpm/kernel/sched.c 2003-06-19 21:03:12.000000000 -0700 @@ -1698,6 +1698,7 @@ static int setscheduler(pid_t pid, int p { struct sched_param lp; int retval = -EINVAL; + int oldprio; prio_array_t *array; unsigned long flags; runqueue_t *rq; @@ -1764,12 +1765,24 @@ static int setscheduler(pid_t pid, int p retval = 0; p->policy = policy; p->rt_priority = lp.sched_priority; + oldprio = p->prio; if (policy != SCHED_NORMAL) p->prio = MAX_USER_RT_PRIO-1 - p->rt_priority; else p->prio = p->static_prio; - if (array) + if (array) { __activate_task(p, task_rq(p)); + /* + * Reschedule if we are currently running on this runqueue and + * our priority decreased, or if we are not currently running on + * this runqueue and our priority is higher than the current's + */ + if (rq->curr == p) { + if (p->prio > oldprio) + resched_task(rq->curr); + } else if (p->prio < rq->curr->prio) + resched_task(rq->curr); + } out_unlock: task_rq_unlock(rq, &flags); _