From: Robert Love <rml@tech9.net>

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

_