diff -urN linux-2.4.19-pre7-ac2/kernel/sched.c linux/kernel/sched.c
--- linux-2.4.19-pre7-ac2/kernel/sched.c	Fri Apr 19 21:00:42 2002
+++ linux/kernel/sched.c	Fri Apr 19 21:03:31 2002
@@ -125,8 +125,6 @@
 
 struct prio_array {
 	int nr_active;
-	spinlock_t *lock;
-	runqueue_t *rq;
 	unsigned long bitmap[BITMAP_SIZE];
 	list_t queue[MAX_PRIO];
 };
@@ -140,6 +138,7 @@
  */
 struct runqueue {
 	spinlock_t lock;
+	spinlock_t frozen;
 	unsigned long nr_running, nr_switches, expired_timestamp;
 	task_t *curr, *idle;
 	prio_array_t *active, *expired, arrays[2];
@@ -346,7 +345,10 @@
 
 void wake_up_forked_process(task_t * p)
 {
-	runqueue_t *rq = this_rq();
+	runqueue_t *rq;
+
+	rq = this_rq();
+	spin_lock_irq(&rq->lock);
 
 	p->state = TASK_RUNNING;
 	if (!rt_task(p)) {
@@ -359,7 +361,6 @@
 		p->sleep_avg = p->sleep_avg * CHILD_PENALTY / 100;
 		p->prio = effective_prio(p);
 	}
-	spin_lock_irq(&rq->lock);
 	p->cpu = smp_processor_id();
 	activate_task(p, rq);
 	spin_unlock_irq(&rq->lock);
@@ -393,7 +394,7 @@
 #if CONFIG_SMP
 asmlinkage void schedule_tail(task_t *prev)
 {
-	spin_unlock_irq(&this_rq()->lock);
+	spin_unlock_irq(&this_rq()->frozen);
 }
 #endif
 
@@ -802,16 +803,21 @@
 	if (likely(prev != next)) {
 		rq->nr_switches++;
 		rq->curr = next;
+		spin_lock(&rq->frozen);
+		spin_unlock(&rq->lock);
+		
 		context_switch(prev, next);
 		/*
 		 * The runqueue pointer might be from another CPU
 		 * if the new task was last running on a different
 		 * CPU - thus re-load it.
 		 */
-		barrier();
+		mb();
 		rq = this_rq();
+		spin_unlock_irq(&rq->frozen);
+	} else {
+		spin_unlock_irq(&rq->lock);
 	}
-	spin_unlock_irq(&rq->lock);
 
 	reacquire_kernel_lock(current);
 	return;
@@ -1399,7 +1403,7 @@
 
 void init_idle(task_t *idle, int cpu)
 {
-	runqueue_t *idle_rq = cpu_rq(cpu), *rq = idle->array->rq;
+	runqueue_t *idle_rq = cpu_rq(cpu), *rq = cpu_rq(idle->cpu);
 	unsigned long flags;
 
 	__save_flags(flags);
@@ -1482,14 +1488,13 @@
 		runqueue_t *rq = cpu_rq(i);
 		prio_array_t *array;
 
-		rq->active = rq->arrays + 0;
+		rq->active = rq->arrays;
 		rq->expired = rq->arrays + 1;
 		spin_lock_init(&rq->lock);
+		spin_lock_init(&rq->frozen);
 
 		for (j = 0; j < 2; j++) {
 			array = rq->arrays + j;
-			array->rq = rq;
-			array->lock = &rq->lock;
 			for (k = 0; k < MAX_PRIO; k++) {
 				INIT_LIST_HEAD(array->queue + k);
 				__clear_bit(k, array->bitmap);
