aboutsummaryrefslogtreecommitdiff
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 9e01d7cd1..abe747553 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1801,6 +1801,7 @@ extern int task_free_unregister(struct notifier_block *n);
#define PF_MEMPOLICY 0x10000000 /* Non-default NUMA mempolicy */
#define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */
#define PF_FREEZER_SKIP 0x40000000 /* Freezer should not count it as freezable */
+#define PF_SUSPEND_TASK 0x80000000 /* this thread called freeze_processes and should not be frozen */
#define PF_MTKPASR 0x80000000 /* I am in MTKPASR process */
diff --git a/kernel/freezer.c b/kernel/freezer.c
index adf590772..e3184b7c9 100644
--- a/kernel/freezer.c
+++ b/kernel/freezer.c
@@ -39,7 +39,7 @@ static DEFINE_SPINLOCK(freezer_lock);
*/
bool freezing_slow_path(struct task_struct *p)
{
- if (p->flags & PF_NOFREEZE)
+ if (p->flags & (PF_NOFREEZE | PF_SUSPEND_TASK))
return false;
if (test_thread_flag_relaxed(TIF_MEMDIE))
diff --git a/kernel/power/process.c b/kernel/power/process.c
index f606d8210..1febd6b4f 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -142,6 +142,8 @@ done:
/**
* freeze_processes - Signal user space processes to enter the refrigerator.
+ * The current thread will not be frozen. The same process that calls
+ * freeze_processes must later call thaw_processes.
*
* On success, returns 0. On failure, -errno and system is fully thawed.
*/
@@ -154,6 +156,9 @@ int freeze_processes(void)
if (error)
return error;
+ /* Make sure this task doesn't get frozen */
+ current->flags |= PF_SUSPEND_TASK;
+
if (!pm_freezing)
atomic_inc(&system_freezing_cnt);
@@ -219,6 +224,7 @@ EXPORT_SYMBOL_GPL(freeze_kernel_threads);
void thaw_processes(void)
{
struct task_struct *g, *p;
+ struct task_struct *curr = current;
if (pm_freezing)
atomic_dec(&system_freezing_cnt);
@@ -236,11 +242,16 @@ void thaw_processes(void)
read_lock(&tasklist_lock);
for_each_process_thread(g, p) {
+ /* No other threads should have PF_SUSPEND_TASK set */
+ WARN_ON((p != curr) && (p->flags & PF_SUSPEND_TASK));
BUG_ON(!virt_addr_valid(next_task(g)));
__thaw_task(p);
}
read_unlock(&tasklist_lock);
+ WARN_ON(!(curr->flags & PF_SUSPEND_TASK));
+ curr->flags &= ~PF_SUSPEND_TASK;
+
usermodehelper_enable();
schedule();