Commit 776969f0 authored by Andrew Morton's avatar Andrew Morton Committed by Paul Mackerras

[PATCH] Keep interrupts enabled in exit path

We are leaving local interrupts disabled coming out of exit_notify().

But we are about to call wait_task_inactive() which spins, waiting for
another CPU to end a task.  If that CPU has issued smp_call_function() to
this CPU, deadlock.

So the patch enables interrupts again before returning from exit_notify().

Also, exit_notify() returns with preemption disabled, so there is no
need to perform another preempt_disable() in do_exit().
parent 3b6244e1
......@@ -674,13 +674,19 @@ static void exit_notify(struct task_struct *tsk)
tsk->state = TASK_ZOMBIE;
/*
* No need to unlock IRQs, we'll schedule() immediately
* anyway. In the preemption case this also makes it
* impossible for the task to get runnable again (thus
* the "_raw_" unlock - to make sure we don't try to
* preempt here).
* In the preemption case it must be impossible for the task
* to get runnable again, so use "_raw_" unlock to keep
* preempt_count elevated until we schedule().
*
* To avoid deadlock on SMP, interrupts must be unmasked. If we
* don't, subsequently called functions (e.g, wait_task_inactive()
* via release_task()) will spin, with interrupt flags
* unwittingly blocked, until the other task sleeps. That task
* may itself be waiting for smp_call_function() to answer and
* complete, and with interrupts blocked that will never happen.
*/
_raw_write_unlock(&tasklist_lock);
local_irq_enable();
}
NORET_TYPE void do_exit(long code)
......@@ -727,7 +733,6 @@ NORET_TYPE void do_exit(long code)
tsk->exit_code = code;
exit_notify(tsk);
preempt_disable();
if (tsk->exit_signal == -1)
release_task(tsk);
......
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