From: Tejun Heo <tj@kernel.org>
To: rjw@sisk.pl, menage@google.com, linux-kernel@vger.kernel.org
Cc: arnd@arndb.de, oleg@redhat.com, Tejun Heo <tj@kernel.org>
Subject: [PATCH 08/16] freezer: use dedicated lock instead of task_lock() + memory barrier
Date: Fri, 19 Aug 2011 16:16:14 +0200 [thread overview]
Message-ID: <1313763382-12341-9-git-send-email-tj@kernel.org> (raw)
In-Reply-To: <1313763382-12341-1-git-send-email-tj@kernel.org>
Freezer synchronizatino is needlessly complicated - it's by no means a
hot path and the priority is staying unintrusive and safe. This patch
makes it simply use a dedicated lock instead of piggy-backing on
task_lock() and playing with memory barriers.
On the failure path of try_to_freeze_tasks(), locking is moved from it
to cancel_freezing(). This makes the frozen() test racy but the race
here is a non-issue as the warning is printed for tasks which failed
to enter frozen for 20 seconds and race on PF_FROZEN at the last
moment doesn't change anything.
This simplifies freezer implementation and eases further changes
including some race fixes.
Signed-off-by: Tejun Heo <tj@kernel.org>
---
kernel/freezer.c | 82 +++++++++++++++++++++---------------------------
kernel/power/process.c | 2 -
2 files changed, 36 insertions(+), 48 deletions(-)
diff --git a/kernel/freezer.c b/kernel/freezer.c
index f5db7fd..c60082d 100644
--- a/kernel/freezer.c
+++ b/kernel/freezer.c
@@ -11,17 +11,8 @@
#include <linux/freezer.h>
#include <linux/kthread.h>
-/*
- * freezing is complete, mark current process as frozen
- */
-static inline void frozen_process(void)
-{
- if (!unlikely(current->flags & PF_NOFREEZE)) {
- current->flags |= PF_FROZEN;
- smp_wmb();
- }
- clear_freeze_flag(current);
-}
+/* protects freezing and frozen transitions */
+static DEFINE_SPINLOCK(freezer_lock);
/* Refrigerator is place where frozen processes are stored :-). */
bool __refrigerator(bool check_kthr_stop)
@@ -31,14 +22,16 @@ bool __refrigerator(bool check_kthr_stop)
bool was_frozen = false;
long save;
- task_lock(current);
- if (freezing(current)) {
- frozen_process();
- task_unlock(current);
- } else {
- task_unlock(current);
+ spin_lock_irq(&freezer_lock);
+ if (!freezing(current)) {
+ spin_unlock_irq(&freezer_lock);
return was_frozen;
}
+ if (!(current->flags & PF_NOFREEZE))
+ current->flags |= PF_FROZEN;
+ clear_freeze_flag(current);
+ spin_unlock_irq(&freezer_lock);
+
save = current->state;
pr_debug("%s entered refrigerator\n", current->comm);
@@ -99,21 +92,18 @@ static void fake_signal_wake_up(struct task_struct *p)
*/
bool freeze_task(struct task_struct *p, bool sig_only)
{
- /*
- * We first check if the task is freezing and next if it has already
- * been frozen to avoid the race with frozen_process() which first marks
- * the task as frozen and next clears its TIF_FREEZE.
- */
- if (!freezing(p)) {
- smp_rmb();
- if (frozen(p))
- return false;
-
- if (!sig_only || should_send_signal(p))
- set_freeze_flag(p);
- else
- return false;
- }
+ unsigned long flags;
+ bool ret = false;
+
+ spin_lock_irqsave(&freezer_lock, flags);
+
+ if (sig_only && !should_send_signal(p))
+ goto out_unlock;
+
+ if (frozen(p))
+ goto out_unlock;
+
+ set_freeze_flag(p);
if (should_send_signal(p)) {
fake_signal_wake_up(p);
@@ -123,26 +113,28 @@ bool freeze_task(struct task_struct *p, bool sig_only)
* TASK_RUNNING transition can't race with task state
* testing in try_to_freeze_tasks().
*/
- } else if (sig_only) {
- return false;
} else {
wake_up_state(p, TASK_INTERRUPTIBLE);
}
-
- return true;
+ ret = true;
+out_unlock:
+ spin_unlock_irqrestore(&freezer_lock, flags);
+ return ret;
}
void cancel_freezing(struct task_struct *p)
{
unsigned long flags;
+ spin_lock_irqsave(&freezer_lock, flags);
if (freezing(p)) {
pr_debug(" clean up: %s\n", p->comm);
clear_freeze_flag(p);
- spin_lock_irqsave(&p->sighand->siglock, flags);
+ spin_lock(&p->sighand->siglock);
recalc_sigpending_and_wake(p);
- spin_unlock_irqrestore(&p->sighand->siglock, flags);
+ spin_unlock(&p->sighand->siglock);
}
+ spin_unlock_irqrestore(&freezer_lock, flags);
}
/*
@@ -156,15 +148,13 @@ void cancel_freezing(struct task_struct *p)
*/
void __thaw_task(struct task_struct *p)
{
- bool was_frozen;
+ unsigned long flags;
- task_lock(p);
- if ((was_frozen = frozen(p)))
+ spin_lock_irqsave(&freezer_lock, flags);
+ if (frozen(p)) {
p->flags &= ~PF_FROZEN;
- else
- clear_freeze_flag(p);
- task_unlock(p);
-
- if (was_frozen)
wake_up_process(p);
+ } else
+ clear_freeze_flag(p);
+ spin_unlock_irqrestore(&freezer_lock, flags);
}
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 3eee548..96d138e 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -118,11 +118,9 @@ static int try_to_freeze_tasks(bool sig_only)
read_lock(&tasklist_lock);
do_each_thread(g, p) {
- task_lock(p);
if (!wakeup && freezing(p) && !freezer_should_skip(p))
sched_show_task(p);
cancel_freezing(p);
- task_unlock(p);
} while_each_thread(g, p);
read_unlock(&tasklist_lock);
} else {
--
1.7.6
next prev parent reply other threads:[~2011-08-19 14:16 UTC|newest]
Thread overview: 79+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-08-19 14:16 [PATCHSET] freezer: fix various bugs and simplify implementation Tejun Heo
2011-08-19 14:16 ` [PATCH 01/16] freezer: fix current->state restoration race in refrigerator() Tejun Heo
2011-08-19 15:52 ` Oleg Nesterov
2011-08-19 16:11 ` Tejun Heo
2011-08-19 21:08 ` Rafael J. Wysocki
2011-08-20 8:13 ` Tejun Heo
2011-08-19 14:16 ` [PATCH 02/16] freezer: don't unnecessarily set PF_NOFREEZE explicitly Tejun Heo
2011-08-19 16:43 ` Gustavo Padovan
2011-08-22 15:05 ` Samuel Ortiz
2011-08-19 14:16 ` [PATCH 03/16] freezer: unexport refrigerator() and update try_to_freeze() slightly Tejun Heo
2011-08-19 14:16 ` [PATCH 04/16] freezer: implement and use kthread_freezable_should_stop() Tejun Heo
2011-08-19 20:07 ` Henrique de Moraes Holschuh
2011-08-21 19:14 ` Oleg Nesterov
2011-08-22 9:53 ` Tejun Heo
2011-08-23 15:42 ` Oleg Nesterov
2011-08-19 14:16 ` [PATCH 05/16] freezer: rename thaw_process() to __thaw_task() and simplify the implementation Tejun Heo
2011-08-19 15:37 ` Paul Menage
2011-08-24 2:28 ` Matt Helsley
2011-08-19 14:16 ` [PATCH 06/16] freezer: make exiting tasks properly unfreezable Tejun Heo
2011-08-23 15:52 ` Oleg Nesterov
2011-08-23 19:44 ` Tejun Heo
2011-08-24 14:14 ` Oleg Nesterov
2011-08-25 15:59 ` Tejun Heo
2011-08-25 16:56 ` Oleg Nesterov
2011-08-25 21:01 ` Rafael J. Wysocki
2011-08-25 21:54 ` Tejun Heo
2011-08-26 21:09 ` Rafael J. Wysocki
2011-08-27 10:35 ` Tejun Heo
2011-08-27 10:51 ` Rafael J. Wysocki
2011-08-27 11:02 ` Tejun Heo
2011-08-27 12:22 ` Rafael J. Wysocki
2011-08-25 21:52 ` Tejun Heo
2011-08-24 22:34 ` Matt Helsley
2011-08-25 15:25 ` Oleg Nesterov
2011-08-25 16:11 ` Tejun Heo
2011-08-19 14:16 ` [PATCH 07/16] freezer: don't distinguish nosig tasks on thaw Tejun Heo
2011-08-19 21:14 ` Rafael J. Wysocki
2011-08-20 8:10 ` Tejun Heo
2011-08-20 8:39 ` Rafael J. Wysocki
2011-08-19 14:16 ` Tejun Heo [this message]
2011-08-28 17:51 ` [PATCH 08/16] freezer: use dedicated lock instead of task_lock() + memory barrier Oleg Nesterov
2011-08-28 18:21 ` Oleg Nesterov
2011-08-29 7:20 ` Tejun Heo
2011-08-19 14:16 ` [PATCH 09/16] freezer: make freezing indicate freeze condition in effect Tejun Heo
2011-08-28 17:56 ` Oleg Nesterov
2011-08-29 7:31 ` Tejun Heo
2011-08-29 17:44 ` Oleg Nesterov
2011-08-19 14:16 ` [PATCH 10/16] freezer: fix set_freezable[_with_signal]() race Tejun Heo
2011-08-28 18:01 ` Oleg Nesterov
2011-08-29 7:38 ` Tejun Heo
2011-08-19 14:16 ` [PATCH 11/16] freezer: kill PF_FREEZING Tejun Heo
2011-08-19 14:16 ` [PATCH 12/16] freezer: clean up freeze_processes() failure path Tejun Heo
2011-08-28 18:09 ` Oleg Nesterov
2011-08-29 7:28 ` Tejun Heo
2011-08-29 7:40 ` Rafael J. Wysocki
2011-08-19 14:16 ` [PATCH 13/16] cgroup_freezer: prepare for removal of TIF_FREEZE Tejun Heo
2011-08-19 15:40 ` Paul Menage
2011-08-28 17:39 ` Oleg Nesterov
2011-08-29 6:30 ` Tejun Heo
2011-08-19 14:16 ` [PATCH 14/16] freezer: make freezing() test freeze conditions in effect instead " Tejun Heo
2011-08-19 15:43 ` Paul Menage
2011-08-29 15:49 ` Oleg Nesterov
2011-08-29 15:56 ` Oleg Nesterov
2011-08-29 16:30 ` Oleg Nesterov
2011-08-29 16:17 ` Oleg Nesterov
2011-08-19 14:16 ` [PATCH 15/16] freezer: remove now unused TIF_FREEZE Tejun Heo
2011-08-19 14:16 ` [PATCH 16/16] freezer: remove should_send_signal() and update frozen() Tejun Heo
2011-08-19 14:23 ` [PATCHSET] freezer: fix various bugs and simplify implementation Tejun Heo
2011-08-19 15:34 ` Paul Menage
2011-08-19 16:25 ` Tejun Heo
2011-08-24 1:10 ` Matt Helsley
2011-08-19 21:00 ` Rafael J. Wysocki
2011-08-20 8:14 ` Tejun Heo
2011-09-05 8:52 ` [BUG] CPU hotplug, freezer: Freezing of tasks failed after 20.00 seconds Srivatsa S. Bhat
2011-09-05 14:15 ` Tejun Heo
2011-09-06 5:08 ` Tejun Heo
2011-09-06 6:01 ` Rafael J. Wysocki
2011-10-02 19:13 ` Srivatsa S. Bhat
2011-10-02 19:33 ` Rafael J. Wysocki
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1313763382-12341-9-git-send-email-tj@kernel.org \
--to=tj@kernel.org \
--cc=arnd@arndb.de \
--cc=linux-kernel@vger.kernel.org \
--cc=menage@google.com \
--cc=oleg@redhat.com \
--cc=rjw@sisk.pl \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox