aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sched.h1
-rw-r--r--kernel/freezer.c2
-rw-r--r--kernel/power/process.c11
3 files changed, 13 insertions, 1 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 50d04b92ceda..d722490da030 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1628,6 +1628,7 @@ extern void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut,
1628#define PF_MEMPOLICY 0x10000000 /* Non-default NUMA mempolicy */ 1628#define PF_MEMPOLICY 0x10000000 /* Non-default NUMA mempolicy */
1629#define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */ 1629#define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */
1630#define PF_FREEZER_SKIP 0x40000000 /* Freezer should not count it as freezable */ 1630#define PF_FREEZER_SKIP 0x40000000 /* Freezer should not count it as freezable */
1631#define PF_SUSPEND_TASK 0x80000000 /* this thread called freeze_processes and should not be frozen */
1631 1632
1632/* 1633/*
1633 * Only the _current_ task can read/write to tsk->flags, but other 1634 * Only the _current_ task can read/write to tsk->flags, but other
diff --git a/kernel/freezer.c b/kernel/freezer.c
index 8b2afc1c9df0..b462fa197517 100644
--- a/kernel/freezer.c
+++ b/kernel/freezer.c
@@ -33,7 +33,7 @@ static DEFINE_SPINLOCK(freezer_lock);
33 */ 33 */
34bool freezing_slow_path(struct task_struct *p) 34bool freezing_slow_path(struct task_struct *p)
35{ 35{
36 if (p->flags & PF_NOFREEZE) 36 if (p->flags & (PF_NOFREEZE | PF_SUSPEND_TASK))
37 return false; 37 return false;
38 38
39 if (pm_nosig_freezing || cgroup_freezing(p)) 39 if (pm_nosig_freezing || cgroup_freezing(p))
diff --git a/kernel/power/process.c b/kernel/power/process.c
index fc0df8486449..06ec8869dbf1 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -109,6 +109,8 @@ static int try_to_freeze_tasks(bool user_only)
109 109
110/** 110/**
111 * freeze_processes - Signal user space processes to enter the refrigerator. 111 * freeze_processes - Signal user space processes to enter the refrigerator.
112 * The current thread will not be frozen. The same process that calls
113 * freeze_processes must later call thaw_processes.
112 * 114 *
113 * On success, returns 0. On failure, -errno and system is fully thawed. 115 * On success, returns 0. On failure, -errno and system is fully thawed.
114 */ 116 */
@@ -120,6 +122,9 @@ int freeze_processes(void)
120 if (error) 122 if (error)
121 return error; 123 return error;
122 124
125 /* Make sure this task doesn't get frozen */
126 current->flags |= PF_SUSPEND_TASK;
127
123 if (!pm_freezing) 128 if (!pm_freezing)
124 atomic_inc(&system_freezing_cnt); 129 atomic_inc(&system_freezing_cnt);
125 130
@@ -168,6 +173,7 @@ int freeze_kernel_threads(void)
168void thaw_processes(void) 173void thaw_processes(void)
169{ 174{
170 struct task_struct *g, *p; 175 struct task_struct *g, *p;
176 struct task_struct *curr = current;
171 177
172 if (pm_freezing) 178 if (pm_freezing)
173 atomic_dec(&system_freezing_cnt); 179 atomic_dec(&system_freezing_cnt);
@@ -182,10 +188,15 @@ void thaw_processes(void)
182 188
183 read_lock(&tasklist_lock); 189 read_lock(&tasklist_lock);
184 do_each_thread(g, p) { 190 do_each_thread(g, p) {
191 /* No other threads should have PF_SUSPEND_TASK set */
192 WARN_ON((p != curr) && (p->flags & PF_SUSPEND_TASK));
185 __thaw_task(p); 193 __thaw_task(p);
186 } while_each_thread(g, p); 194 } while_each_thread(g, p);
187 read_unlock(&tasklist_lock); 195 read_unlock(&tasklist_lock);
188 196
197 WARN_ON(!(curr->flags & PF_SUSPEND_TASK));
198 curr->flags &= ~PF_SUSPEND_TASK;
199
189 usermodehelper_enable(); 200 usermodehelper_enable();
190 201
191 schedule(); 202 schedule();