diff options
| -rw-r--r-- | include/linux/freezer.h | 10 | ||||
| -rw-r--r-- | kernel/power/process.c | 12 |
2 files changed, 21 insertions, 1 deletions
diff --git a/include/linux/freezer.h b/include/linux/freezer.h index 5e75e26d4787..db5423eae24d 100644 --- a/include/linux/freezer.h +++ b/include/linux/freezer.h | |||
| @@ -37,14 +37,24 @@ static inline void do_not_freeze(struct task_struct *p) | |||
| 37 | 37 | ||
| 38 | /* | 38 | /* |
| 39 | * Wake up a frozen process | 39 | * Wake up a frozen process |
| 40 | * | ||
| 41 | * task_lock() is taken to prevent the race with refrigerator() which may | ||
| 42 | * occur if the freezing of tasks fails. Namely, without the lock, if the | ||
| 43 | * freezing of tasks failed, thaw_tasks() might have run before a task in | ||
| 44 | * refrigerator() could call frozen_process(), in which case the task would be | ||
| 45 | * frozen and no one would thaw it. | ||
| 40 | */ | 46 | */ |
| 41 | static inline int thaw_process(struct task_struct *p) | 47 | static inline int thaw_process(struct task_struct *p) |
| 42 | { | 48 | { |
| 49 | task_lock(p); | ||
| 43 | if (frozen(p)) { | 50 | if (frozen(p)) { |
| 44 | p->flags &= ~PF_FROZEN; | 51 | p->flags &= ~PF_FROZEN; |
| 52 | task_unlock(p); | ||
| 45 | wake_up_process(p); | 53 | wake_up_process(p); |
| 46 | return 1; | 54 | return 1; |
| 47 | } | 55 | } |
| 56 | clear_tsk_thread_flag(p, TIF_FREEZE); | ||
| 57 | task_unlock(p); | ||
| 48 | return 0; | 58 | return 0; |
| 49 | } | 59 | } |
| 50 | 60 | ||
diff --git a/kernel/power/process.c b/kernel/power/process.c index 088419387388..02e490e311eb 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c | |||
| @@ -37,10 +37,18 @@ void refrigerator(void) | |||
| 37 | /* Hmm, should we be allowed to suspend when there are realtime | 37 | /* Hmm, should we be allowed to suspend when there are realtime |
| 38 | processes around? */ | 38 | processes around? */ |
| 39 | long save; | 39 | long save; |
| 40 | |||
| 41 | task_lock(current); | ||
| 42 | if (freezing(current)) { | ||
| 43 | frozen_process(current); | ||
| 44 | task_unlock(current); | ||
| 45 | } else { | ||
| 46 | task_unlock(current); | ||
| 47 | return; | ||
| 48 | } | ||
| 40 | save = current->state; | 49 | save = current->state; |
| 41 | pr_debug("%s entered refrigerator\n", current->comm); | 50 | pr_debug("%s entered refrigerator\n", current->comm); |
| 42 | 51 | ||
| 43 | frozen_process(current); | ||
| 44 | spin_lock_irq(¤t->sighand->siglock); | 52 | spin_lock_irq(¤t->sighand->siglock); |
| 45 | recalc_sigpending(); /* We sent fake signal, clean it up */ | 53 | recalc_sigpending(); /* We sent fake signal, clean it up */ |
| 46 | spin_unlock_irq(¤t->sighand->siglock); | 54 | spin_unlock_irq(¤t->sighand->siglock); |
| @@ -152,10 +160,12 @@ static unsigned int try_to_freeze_tasks(int freeze_user_space) | |||
| 152 | if (is_user_space(p) == !freeze_user_space) | 160 | if (is_user_space(p) == !freeze_user_space) |
| 153 | continue; | 161 | continue; |
| 154 | 162 | ||
| 163 | task_lock(p); | ||
| 155 | if (freezeable(p) && !frozen(p)) | 164 | if (freezeable(p) && !frozen(p)) |
| 156 | printk(KERN_ERR " %s\n", p->comm); | 165 | printk(KERN_ERR " %s\n", p->comm); |
| 157 | 166 | ||
| 158 | cancel_freezing(p); | 167 | cancel_freezing(p); |
| 168 | task_unlock(p); | ||
| 159 | } while_each_thread(g, p); | 169 | } while_each_thread(g, p); |
| 160 | read_unlock(&tasklist_lock); | 170 | read_unlock(&tasklist_lock); |
| 161 | } | 171 | } |
