Commit e9a1648b authored by David S. Miller's avatar David S. Miller

Fix scheduler deadlock on some platforms.

Some platforms need to grab mm->page_table_lock during switch_mm().
On the other hand code like swap_out() in mm/vmscan.c needs to hold
mm->page_table_lock during wakeups which needs to grab the runqueue
lock.  This creates a conflict and the resolution chosen here is to
not hold the runqueue lock during context_switch().

The implementation is specifically a "frozen" state implemented as a
spinlock, which is held around the context_switch() call.  This allows
the runqueue lock to be dropped during this time yet prevent another cpu
from running the "not switched away from yet" task.
parent 50b1b006
......@@ -140,6 +140,7 @@ struct prio_array {
*/
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];
......@@ -400,7 +401,7 @@ void sched_exit(task_t * p)
#if CONFIG_SMP || CONFIG_PREEMPT
asmlinkage void schedule_tail(void)
{
spin_unlock_irq(&this_rq()->lock);
spin_unlock_irq(&this_rq()->frozen);
}
#endif
......@@ -808,16 +809,22 @@ asmlinkage void schedule(void)
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);
preempt_enable_no_resched();
......@@ -1463,6 +1470,7 @@ void __init sched_init(void)
rq->active = rq->arrays;
rq->expired = rq->arrays + 1;
spin_lock_init(&rq->lock);
spin_lock_init(&rq->frozen);
INIT_LIST_HEAD(&rq->migration_queue);
for (j = 0; j < 2; j++) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment