mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 11:11:45 -04:00
sched/core: Introduce set_special_state()
Gaurav reported a perceived problem with TASK_PARKED, which turned out to be a broken wait-loop pattern in __kthread_parkme(), but the reported issue can (and does) in fact happen for states that do not do condition based sleeps. When the 'current->state = TASK_RUNNING' store of a previous (concurrent) try_to_wake_up() collides with the setting of a 'special' sleep state, we can loose the sleep state. Normal condition based wait-loops are immune to this problem, but for sleep states that are not condition based are subject to this problem. There already is a fix for TASK_DEAD. Abstract that and also apply it to TASK_STOPPED and TASK_TRACED, both of which are also without condition based wait-loop. Reported-by: Gaurav Kohli <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Oleg Nesterov <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Signed-off-by: Ingo Molnar <[email protected]>
This commit is contained in:
parent
85f1abe001
commit
b5bf9a90bb
4 changed files with 62 additions and 24 deletions
|
|
@ -1961,14 +1961,27 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
|
|||
return;
|
||||
}
|
||||
|
||||
set_special_state(TASK_TRACED);
|
||||
|
||||
/*
|
||||
* We're committing to trapping. TRACED should be visible before
|
||||
* TRAPPING is cleared; otherwise, the tracer might fail do_wait().
|
||||
* Also, transition to TRACED and updates to ->jobctl should be
|
||||
* atomic with respect to siglock and should be done after the arch
|
||||
* hook as siglock is released and regrabbed across it.
|
||||
*
|
||||
* TRACER TRACEE
|
||||
*
|
||||
* ptrace_attach()
|
||||
* [L] wait_on_bit(JOBCTL_TRAPPING) [S] set_special_state(TRACED)
|
||||
* do_wait()
|
||||
* set_current_state() smp_wmb();
|
||||
* ptrace_do_wait()
|
||||
* wait_task_stopped()
|
||||
* task_stopped_code()
|
||||
* [L] task_is_traced() [S] task_clear_jobctl_trapping();
|
||||
*/
|
||||
set_current_state(TASK_TRACED);
|
||||
smp_wmb();
|
||||
|
||||
current->last_siginfo = info;
|
||||
current->exit_code = exit_code;
|
||||
|
|
@ -2176,7 +2189,7 @@ static bool do_signal_stop(int signr)
|
|||
if (task_participate_group_stop(current))
|
||||
notify = CLD_STOPPED;
|
||||
|
||||
__set_current_state(TASK_STOPPED);
|
||||
set_special_state(TASK_STOPPED);
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in a new issue