Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 280370
b: refs/heads/master
c: 6907483
h: refs/heads/master
v: v3
  • Loading branch information
Tejun Heo committed Nov 21, 2011
1 parent fce6bd1 commit 1456026
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 21 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0c9af09262864a2744091ee94c98c4a8fd60c98b
refs/heads/master: 6907483b4e803a20f0b48cc9afa3817420ce61c5
2 changes: 1 addition & 1 deletion trunk/kernel/cgroup_freezer.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ static void update_if_frozen(struct cgroup *cgroup,
cgroup_iter_start(cgroup, &it);
while ((task = cgroup_iter_next(cgroup, &it))) {
ntotal++;
if (frozen(task))
if (freezing(task) && frozen(task))
nfrozen++;
}

Expand Down
42 changes: 24 additions & 18 deletions trunk/kernel/freezer.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,19 @@ bool __refrigerator(bool check_kthr_stop)
bool was_frozen = false;
long save;

/*
* Enter FROZEN. If NOFREEZE, schedule immediate thawing by
* clearing freezing.
*/
spin_lock_irq(&freezer_lock);
repeat:
if (!freezing(current)) {
spin_unlock_irq(&freezer_lock);
return was_frozen;
}
if (!(current->flags & PF_NOFREEZE))
current->flags |= PF_FROZEN;
clear_freeze_flag(current);
if (current->flags & PF_NOFREEZE)
clear_freeze_flag(current);
current->flags |= PF_FROZEN;
spin_unlock_irq(&freezer_lock);

save = current->state;
Expand All @@ -44,7 +49,7 @@ bool __refrigerator(bool check_kthr_stop)

for (;;) {
set_current_state(TASK_UNINTERRUPTIBLE);
if (!frozen(current) ||
if (!freezing(current) ||
(check_kthr_stop && kthread_should_stop()))
break;
was_frozen = true;
Expand All @@ -54,6 +59,13 @@ bool __refrigerator(bool check_kthr_stop)
/* Remove the accounting blocker */
current->flags &= ~PF_FREEZING;

/* leave FROZEN */
spin_lock_irq(&freezer_lock);
if (freezing(current))
goto repeat;
current->flags &= ~PF_FROZEN;
spin_unlock_irq(&freezer_lock);

pr_debug("%s left refrigerator\n", current->comm);

/*
Expand Down Expand Up @@ -137,25 +149,19 @@ void cancel_freezing(struct task_struct *p)
spin_unlock_irqrestore(&freezer_lock, flags);
}

/*
* Wake up a frozen task
*
* task_lock() is needed 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.
*/
void __thaw_task(struct task_struct *p)
{
unsigned long flags;

/*
* Clear freezing and kick @p if FROZEN. Clearing is guaranteed to
* be visible to @p as waking up implies wmb. Waking up inside
* freezer_lock also prevents wakeups from leaking outside
* refrigerator.
*/
spin_lock_irqsave(&freezer_lock, flags);
if (frozen(p)) {
p->flags &= ~PF_FROZEN;
clear_freeze_flag(p);
if (frozen(p))
wake_up_process(p);
} else {
clear_freeze_flag(p);
}
spin_unlock_irqrestore(&freezer_lock, flags);
}
3 changes: 2 additions & 1 deletion trunk/kernel/power/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ static int try_to_freeze_tasks(bool sig_only)

read_lock(&tasklist_lock);
do_each_thread(g, p) {
if (!wakeup && freezing(p) && !freezer_should_skip(p))
if (!wakeup && !freezer_should_skip(p) &&
freezing(p) && !frozen(p))
sched_show_task(p);
cancel_freezing(p);
} while_each_thread(g, p);
Expand Down

0 comments on commit 1456026

Please sign in to comment.