diff options
| -rw-r--r-- | include/linux/sched.h | 1 | ||||
| -rw-r--r-- | kernel/freezer.c | 2 | ||||
| -rw-r--r-- | kernel/power/process.c | 11 |
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(); |
