diff options
| author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2019-02-26 12:31:10 +0100 |
|---|---|---|
| committer | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2019-02-26 13:05:47 +0100 |
| commit | d70f218ee02d6fc3832274653aa6c6e98dd9aa43 (patch) | |
| tree | 396e79f6948d59179212e8c2964bf464e12ec838 | |
| parent | 1c258d06c549932d8d4dbdf77570f0e8e92627e2 (diff) | |
hrtimer: cpu_chill(): save task state in ->saved_state()
In the previous change I saved the current task state on stack. This was
bad because while the task is scheduled-out it might receive a wake-up.
The wake up changes the task state and we must not destroy it.
Save the task-state in ->saved_state under a PI-lock to unsure that
state changes during are not missed while the task temporary scheduled
out.
Reported-by: Mike Galbraith <efault@gmx.de>
Tested-by: Mike Galbraith <efault@gmx.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
| -rw-r--r-- | kernel/time/hrtimer.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 6f2736ec4b8e..e1040b80362c 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -1900,20 +1900,28 @@ COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp, */ void cpu_chill(void) { - ktime_t chill_time; unsigned int freeze_flag = current->flags & PF_NOFREEZE; - long saved_state; + struct task_struct *self = current; + ktime_t chill_time; - saved_state = current->state; - chill_time = ktime_set(0, NSEC_PER_MSEC); + raw_spin_lock_irq(&self->pi_lock); + self->saved_state = self->state; __set_current_state_no_track(TASK_UNINTERRUPTIBLE); + raw_spin_unlock_irq(&self->pi_lock); + + chill_time = ktime_set(0, NSEC_PER_MSEC); + current->flags |= PF_NOFREEZE; sleeping_lock_inc(); schedule_hrtimeout(&chill_time, HRTIMER_MODE_REL_HARD); sleeping_lock_dec(); if (!freeze_flag) current->flags &= ~PF_NOFREEZE; - __set_current_state_no_track(saved_state); + + raw_spin_lock_irq(&self->pi_lock); + __set_current_state_no_track(self->saved_state); + self->saved_state = TASK_RUNNING; + raw_spin_unlock_irq(&self->pi_lock); } EXPORT_SYMBOL(cpu_chill); #endif |
