diff -ru sched-2.5.59-03/kernel/sched.c sched-2.5.59-04/kernel/sched.c --- sched-2.5.59-03/kernel/sched.c Tue Feb 4 00:31:43 2003 +++ sched-2.5.59-04/kernel/sched.c Tue Feb 4 00:40:20 2003 @@ -151,6 +151,7 @@ unsigned long nr_running, nr_switches, expired_timestamp, nr_uninterruptible; task_t *curr, *idle; + struct mm_struct *prev_mm; prio_array_t *active, *expired, arrays[2]; int prev_nr_running[NR_CPUS]; #ifdef CONFIG_NUMA @@ -560,7 +561,7 @@ * context_switch - switch to the new MM and the new * thread's register state. */ -static inline task_t * context_switch(task_t *prev, task_t *next) +static inline task_t * context_switch(runqueue_t *rq, task_t *prev, task_t *next) { struct mm_struct *mm = next->mm; struct mm_struct *oldmm = prev->active_mm; @@ -574,7 +575,7 @@ if (unlikely(!prev->mm)) { prev->active_mm = NULL; - mmdrop(oldmm); + rq->prev_mm = oldmm; } /* Here we just switch the register state and the stack. */ @@ -1213,14 +1214,19 @@ RCU_qsctr(prev->thread_info->cpu)++; if (likely(prev != next)) { + struct mm_struct *prev_mm; rq->nr_switches++; rq->curr = next; prepare_arch_switch(rq, next); - prev = context_switch(prev, next); + prev = context_switch(rq, prev, next); barrier(); rq = this_rq(); + prev_mm = rq->prev_mm; + rq->prev_mm = NULL; finish_arch_switch(rq, prev); + if (prev_mm) + mmdrop(prev_mm); } else spin_unlock_irq(&rq->lock);