diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/freezer.c | 9 | ||||
| -rw-r--r-- | kernel/power/process.c | 6 | 
2 files changed, 13 insertions, 2 deletions
diff --git a/kernel/freezer.c b/kernel/freezer.c index bd1d42b17cb..66ecd2ead21 100644 --- a/kernel/freezer.c +++ b/kernel/freezer.c @@ -104,8 +104,13 @@ bool freeze_task(struct task_struct *p, bool sig_only)  	}  	if (should_send_signal(p)) { -		if (!signal_pending(p)) -			fake_signal_wake_up(p); +		fake_signal_wake_up(p); +		/* +		 * fake_signal_wake_up() goes through p's scheduler +		 * lock and guarantees that TASK_STOPPED/TRACED -> +		 * TASK_RUNNING transition can't race with task state +		 * testing in try_to_freeze_tasks(). +		 */  	} else if (sig_only) {  		return false;  	} else { diff --git a/kernel/power/process.c b/kernel/power/process.c index e50b4c1b2a0..eb2c88a9e56 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -64,6 +64,12 @@ static int try_to_freeze_tasks(bool sig_only)  			 * perturb a task in TASK_STOPPED or TASK_TRACED.  			 * It is "frozen enough".  If the task does wake  			 * up, it will immediately call try_to_freeze. +			 * +			 * Because freeze_task() goes through p's +			 * scheduler lock after setting TIF_FREEZE, it's +			 * guaranteed that either we see TASK_RUNNING or +			 * try_to_stop() after schedule() in ptrace/signal +			 * stop sees TIF_FREEZE.  			 */  			if (!task_is_stopped_or_traced(p) &&  			    !freezer_should_skip(p))  |