Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
1da177e4 LT |
2 | /* |
3 | * drivers/power/process.c - Functions for starting/stopping processes on | |
4 | * suspend transitions. | |
5 | * | |
6 | * Originally from swsusp. | |
7 | */ | |
8 | ||
9 | ||
10 | #undef DEBUG | |
11 | ||
1da177e4 | 12 | #include <linux/interrupt.h> |
1a8670a2 | 13 | #include <linux/oom.h> |
1da177e4 LT |
14 | #include <linux/suspend.h> |
15 | #include <linux/module.h> | |
b17b0153 | 16 | #include <linux/sched/debug.h> |
29930025 | 17 | #include <linux/sched/task.h> |
02aaeb9b | 18 | #include <linux/syscalls.h> |
7dfb7103 | 19 | #include <linux/freezer.h> |
be404f02 | 20 | #include <linux/delay.h> |
a0a1a5fd | 21 | #include <linux/workqueue.h> |
1e73203c | 22 | #include <linux/kmod.h> |
bb3632c6 | 23 | #include <trace/events/power.h> |
50e76632 | 24 | #include <linux/cpuset.h> |
1da177e4 | 25 | |
50e76632 | 26 | /* |
1da177e4 LT |
27 | * Timeout for stopping processes |
28 | */ | |
957d1282 | 29 | unsigned int __read_mostly freeze_timeout_msecs = 20 * MSEC_PER_SEC; |
1da177e4 | 30 | |
839e3407 | 31 | static int try_to_freeze_tasks(bool user_only) |
1da177e4 | 32 | { |
1da177e4 | 33 | struct task_struct *g, *p; |
11b2ce2b RW |
34 | unsigned long end_time; |
35 | unsigned int todo; | |
a0a1a5fd | 36 | bool wq_busy = false; |
f7b382b9 | 37 | ktime_t start, end, elapsed; |
18ad0c62 | 38 | unsigned int elapsed_msecs; |
dbeeec5f | 39 | bool wakeup = false; |
18ad0c62 | 40 | int sleep_usecs = USEC_PER_MSEC; |
438e2ce6 | 41 | |
f7b382b9 | 42 | start = ktime_get_boottime(); |
3e1d1d28 | 43 | |
957d1282 | 44 | end_time = jiffies + msecs_to_jiffies(freeze_timeout_msecs); |
a0a1a5fd | 45 | |
839e3407 | 46 | if (!user_only) |
a0a1a5fd TH |
47 | freeze_workqueues_begin(); |
48 | ||
be404f02 | 49 | while (true) { |
11b2ce2b | 50 | todo = 0; |
1da177e4 | 51 | read_lock(&tasklist_lock); |
a28e785a | 52 | for_each_process_thread(g, p) { |
839e3407 | 53 | if (p == current || !freeze_task(p)) |
d5d8c597 RW |
54 | continue; |
55 | ||
5d8f72b5 | 56 | if (!freezer_should_skip(p)) |
ba96a0c8 | 57 | todo++; |
a28e785a | 58 | } |
1da177e4 | 59 | read_unlock(&tasklist_lock); |
a0a1a5fd | 60 | |
839e3407 | 61 | if (!user_only) { |
a0a1a5fd TH |
62 | wq_busy = freeze_workqueues_busy(); |
63 | todo += wq_busy; | |
64 | } | |
65 | ||
be404f02 | 66 | if (!todo || time_after(jiffies, end_time)) |
6161b2ce | 67 | break; |
be404f02 | 68 | |
a2867e08 | 69 | if (pm_wakeup_pending()) { |
dbeeec5f RW |
70 | wakeup = true; |
71 | break; | |
72 | } | |
73 | ||
be404f02 TH |
74 | /* |
75 | * We need to retry, but first give the freezing tasks some | |
18ad0c62 CC |
76 | * time to enter the refrigerator. Start with an initial |
77 | * 1 ms sleep followed by exponential backoff until 8 ms. | |
be404f02 | 78 | */ |
18ad0c62 CC |
79 | usleep_range(sleep_usecs / 2, sleep_usecs); |
80 | if (sleep_usecs < 8 * USEC_PER_MSEC) | |
81 | sleep_usecs *= 2; | |
be404f02 | 82 | } |
3e1d1d28 | 83 | |
f7b382b9 AJ |
84 | end = ktime_get_boottime(); |
85 | elapsed = ktime_sub(end, start); | |
86 | elapsed_msecs = ktime_to_ms(elapsed); | |
438e2ce6 | 87 | |
6161b2ce | 88 | if (todo) { |
35536ae1 MH |
89 | pr_cont("\n"); |
90 | pr_err("Freezing of tasks %s after %d.%03d seconds " | |
a0a1a5fd | 91 | "(%d tasks refusing to freeze, wq_busy=%d):\n", |
dbeeec5f | 92 | wakeup ? "aborted" : "failed", |
18ad0c62 | 93 | elapsed_msecs / 1000, elapsed_msecs % 1000, |
a0a1a5fd TH |
94 | todo - wq_busy, wq_busy); |
95 | ||
7b776af6 RL |
96 | if (wq_busy) |
97 | show_workqueue_state(); | |
98 | ||
8412dbd6 | 99 | if (!wakeup || pm_debug_messages_on) { |
6c83b481 | 100 | read_lock(&tasklist_lock); |
a28e785a | 101 | for_each_process_thread(g, p) { |
6c83b481 RW |
102 | if (p != current && !freezer_should_skip(p) |
103 | && freezing(p) && !frozen(p)) | |
104 | sched_show_task(p); | |
a28e785a | 105 | } |
6c83b481 RW |
106 | read_unlock(&tasklist_lock); |
107 | } | |
438e2ce6 | 108 | } else { |
35536ae1 | 109 | pr_cont("(elapsed %d.%03d seconds) ", elapsed_msecs / 1000, |
18ad0c62 | 110 | elapsed_msecs % 1000); |
6161b2ce PM |
111 | } |
112 | ||
e7cd8a72 | 113 | return todo ? -EBUSY : 0; |
11b2ce2b RW |
114 | } |
115 | ||
116 | /** | |
2aede851 | 117 | * freeze_processes - Signal user space processes to enter the refrigerator. |
2b44c4db CC |
118 | * The current thread will not be frozen. The same process that calls |
119 | * freeze_processes must later call thaw_processes. | |
03afed8b TH |
120 | * |
121 | * On success, returns 0. On failure, -errno and system is fully thawed. | |
11b2ce2b RW |
122 | */ |
123 | int freeze_processes(void) | |
124 | { | |
e7cd8a72 | 125 | int error; |
11b2ce2b | 126 | |
247bc037 | 127 | error = __usermodehelper_disable(UMH_FREEZING); |
1e73203c RW |
128 | if (error) |
129 | return error; | |
130 | ||
2b44c4db CC |
131 | /* Make sure this task doesn't get frozen */ |
132 | current->flags |= PF_SUSPEND_TASK; | |
133 | ||
a3201227 TH |
134 | if (!pm_freezing) |
135 | atomic_inc(&system_freezing_cnt); | |
136 | ||
33e4f80e | 137 | pm_wakeup_clear(true); |
35536ae1 | 138 | pr_info("Freezing user space processes ... "); |
a3201227 | 139 | pm_freezing = true; |
ebb12db5 | 140 | error = try_to_freeze_tasks(true); |
2aede851 | 141 | if (!error) { |
247bc037 | 142 | __usermodehelper_set_disable_depth(UMH_DISABLED); |
c32b3cbe | 143 | pr_cont("done."); |
2aede851 | 144 | } |
35536ae1 | 145 | pr_cont("\n"); |
2aede851 RW |
146 | BUG_ON(in_atomic()); |
147 | ||
c32b3cbe MH |
148 | /* |
149 | * Now that the whole userspace is frozen we need to disbale | |
150 | * the OOM killer to disallow any further interference with | |
7d2e7a22 MH |
151 | * killable tasks. There is no guarantee oom victims will |
152 | * ever reach a point they go away we have to wait with a timeout. | |
c32b3cbe | 153 | */ |
7d2e7a22 | 154 | if (!error && !oom_killer_disable(msecs_to_jiffies(freeze_timeout_msecs))) |
c32b3cbe MH |
155 | error = -EBUSY; |
156 | ||
03afed8b TH |
157 | if (error) |
158 | thaw_processes(); | |
2aede851 RW |
159 | return error; |
160 | } | |
161 | ||
162 | /** | |
163 | * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator. | |
03afed8b | 164 | * |
379e0be8 SB |
165 | * On success, returns 0. On failure, -errno and only the kernel threads are |
166 | * thawed, so as to give a chance to the caller to do additional cleanups | |
167 | * (if any) before thawing the userspace tasks. So, it is the responsibility | |
168 | * of the caller to thaw the userspace tasks, when the time is right. | |
2aede851 RW |
169 | */ |
170 | int freeze_kernel_threads(void) | |
171 | { | |
172 | int error; | |
11b2ce2b | 173 | |
35536ae1 MH |
174 | pr_info("Freezing remaining freezable tasks ... "); |
175 | ||
a3201227 | 176 | pm_nosig_freezing = true; |
ebb12db5 | 177 | error = try_to_freeze_tasks(false); |
2aede851 | 178 | if (!error) |
35536ae1 | 179 | pr_cont("done."); |
7f33d49a | 180 | |
35536ae1 | 181 | pr_cont("\n"); |
2aede851 | 182 | BUG_ON(in_atomic()); |
7f33d49a | 183 | |
03afed8b | 184 | if (error) |
379e0be8 | 185 | thaw_kernel_threads(); |
b842ee57 | 186 | return error; |
1da177e4 LT |
187 | } |
188 | ||
6cd8dedc | 189 | void thaw_processes(void) |
1da177e4 LT |
190 | { |
191 | struct task_struct *g, *p; | |
2b44c4db | 192 | struct task_struct *curr = current; |
1da177e4 | 193 | |
bb3632c6 | 194 | trace_suspend_resume(TPS("thaw_processes"), 0, true); |
a3201227 TH |
195 | if (pm_freezing) |
196 | atomic_dec(&system_freezing_cnt); | |
197 | pm_freezing = false; | |
198 | pm_nosig_freezing = false; | |
199 | ||
6cd8dedc TH |
200 | oom_killer_enable(); |
201 | ||
35536ae1 | 202 | pr_info("Restarting tasks ... "); |
6cd8dedc | 203 | |
4320f6b1 | 204 | __usermodehelper_set_disable_depth(UMH_FREEZING); |
6cd8dedc TH |
205 | thaw_workqueues(); |
206 | ||
50e76632 PZ |
207 | cpuset_wait_for_hotplug(); |
208 | ||
1da177e4 | 209 | read_lock(&tasklist_lock); |
a28e785a | 210 | for_each_process_thread(g, p) { |
2b44c4db CC |
211 | /* No other threads should have PF_SUSPEND_TASK set */ |
212 | WARN_ON((p != curr) && (p->flags & PF_SUSPEND_TASK)); | |
a5be2d0d | 213 | __thaw_task(p); |
a28e785a | 214 | } |
1da177e4 | 215 | read_unlock(&tasklist_lock); |
7f33d49a | 216 | |
2b44c4db CC |
217 | WARN_ON(!(curr->flags & PF_SUSPEND_TASK)); |
218 | curr->flags &= ~PF_SUSPEND_TASK; | |
219 | ||
1e73203c RW |
220 | usermodehelper_enable(); |
221 | ||
1da177e4 | 222 | schedule(); |
35536ae1 | 223 | pr_cont("done.\n"); |
bb3632c6 | 224 | trace_suspend_resume(TPS("thaw_processes"), 0, false); |
1da177e4 LT |
225 | } |
226 | ||
181e9bde RW |
227 | void thaw_kernel_threads(void) |
228 | { | |
229 | struct task_struct *g, *p; | |
230 | ||
231 | pm_nosig_freezing = false; | |
35536ae1 | 232 | pr_info("Restarting kernel threads ... "); |
181e9bde RW |
233 | |
234 | thaw_workqueues(); | |
235 | ||
236 | read_lock(&tasklist_lock); | |
a28e785a | 237 | for_each_process_thread(g, p) { |
181e9bde RW |
238 | if (p->flags & (PF_KTHREAD | PF_WQ_WORKER)) |
239 | __thaw_task(p); | |
a28e785a | 240 | } |
181e9bde RW |
241 | read_unlock(&tasklist_lock); |
242 | ||
243 | schedule(); | |
35536ae1 | 244 | pr_cont("done.\n"); |
181e9bde | 245 | } |