From 2208b4afe74cbf398fbed88834b0308e3a86847a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 23 May 2007 13:57:24 -0700 Subject: [PATCH] --- yaml --- r: 56862 b: refs/heads/master c: 33e1c288da62a6a5aa9077a6b7bfa690b1b02cf4 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/include/linux/freezer.h | 10 ++++++++++ trunk/kernel/power/process.c | 12 +++++++++++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index d6fdf842e1df..4c224c98905a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 585a2858b970cb6e2e5ca4877eefd18b4dba8ed4 +refs/heads/master: 33e1c288da62a6a5aa9077a6b7bfa690b1b02cf4 diff --git a/trunk/include/linux/freezer.h b/trunk/include/linux/freezer.h index 5e75e26d4787..db5423eae24d 100644 --- a/trunk/include/linux/freezer.h +++ b/trunk/include/linux/freezer.h @@ -37,14 +37,24 @@ static inline void do_not_freeze(struct task_struct *p) /* * Wake up a frozen process + * + * task_lock() is taken to prevent the race with refrigerator() which may + * occur if the freezing of tasks fails. Namely, without the lock, if the + * freezing of tasks failed, thaw_tasks() might have run before a task in + * refrigerator() could call frozen_process(), in which case the task would be + * frozen and no one would thaw it. */ static inline int thaw_process(struct task_struct *p) { + task_lock(p); if (frozen(p)) { p->flags &= ~PF_FROZEN; + task_unlock(p); wake_up_process(p); return 1; } + clear_tsk_thread_flag(p, TIF_FREEZE); + task_unlock(p); return 0; } diff --git a/trunk/kernel/power/process.c b/trunk/kernel/power/process.c index 088419387388..02e490e311eb 100644 --- a/trunk/kernel/power/process.c +++ b/trunk/kernel/power/process.c @@ -37,10 +37,18 @@ void refrigerator(void) /* Hmm, should we be allowed to suspend when there are realtime processes around? */ long save; + + task_lock(current); + if (freezing(current)) { + frozen_process(current); + task_unlock(current); + } else { + task_unlock(current); + return; + } save = current->state; pr_debug("%s entered refrigerator\n", current->comm); - frozen_process(current); spin_lock_irq(¤t->sighand->siglock); recalc_sigpending(); /* We sent fake signal, clean it up */ spin_unlock_irq(¤t->sighand->siglock); @@ -152,10 +160,12 @@ static unsigned int try_to_freeze_tasks(int freeze_user_space) if (is_user_space(p) == !freeze_user_space) continue; + task_lock(p); if (freezeable(p) && !frozen(p)) printk(KERN_ERR " %s\n", p->comm); cancel_freezing(p); + task_unlock(p); } while_each_thread(g, p); read_unlock(&tasklist_lock); }