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