Branch data Line data Source code
1 : : /*
2 : : * drivers/power/process.c - Functions for starting/stopping processes on
3 : : * suspend transitions.
4 : : *
5 : : * Originally from swsusp.
6 : : */
7 : :
8 : :
9 : : #undef DEBUG
10 : :
11 : : #include <linux/interrupt.h>
12 : : #include <linux/oom.h>
13 : : #include <linux/suspend.h>
14 : : #include <linux/module.h>
15 : : #include <linux/syscalls.h>
16 : : #include <linux/freezer.h>
17 : : #include <linux/delay.h>
18 : : #include <linux/workqueue.h>
19 : : #include <linux/kmod.h>
20 : :
21 : : /*
22 : : * Timeout for stopping processes
23 : : */
24 : : unsigned int __read_mostly freeze_timeout_msecs = 20 * MSEC_PER_SEC;
25 : :
26 : 0 : static int try_to_freeze_tasks(bool user_only)
27 : : {
28 : : struct task_struct *g, *p;
29 : : unsigned long end_time;
30 : : unsigned int todo;
31 : : bool wq_busy = false;
32 : : struct timeval start, end;
33 : : u64 elapsed_msecs64;
34 : : unsigned int elapsed_msecs;
35 : : bool wakeup = false;
36 : : int sleep_usecs = USEC_PER_MSEC;
37 : :
38 : 0 : do_gettimeofday(&start);
39 : :
40 : 0 : end_time = jiffies + msecs_to_jiffies(freeze_timeout_msecs);
41 : :
42 [ # # ]: 0 : if (!user_only)
43 : 0 : freeze_workqueues_begin();
44 : :
45 : : while (true) {
46 : : todo = 0;
47 : 0 : read_lock(&tasklist_lock);
48 [ # # ]: 0 : do_each_thread(g, p) {
49 [ # # ][ # # ]: 0 : if (p == current || !freeze_task(p))
50 : 0 : continue;
51 : :
52 [ # # ]: 0 : if (!freezer_should_skip(p))
53 : 0 : todo++;
54 [ # # ]: 0 : } while_each_thread(g, p);
55 : : read_unlock(&tasklist_lock);
56 : :
57 [ # # ]: 0 : if (!user_only) {
58 : 0 : wq_busy = freeze_workqueues_busy();
59 : 0 : todo += wq_busy;
60 : : }
61 : :
62 [ # # ][ # # ]: 0 : if (!todo || time_after(jiffies, end_time))
63 : : break;
64 : :
65 [ # # ]: 0 : if (pm_wakeup_pending()) {
66 : : wakeup = true;
67 : : break;
68 : : }
69 : :
70 : : /*
71 : : * We need to retry, but first give the freezing tasks some
72 : : * time to enter the refrigerator. Start with an initial
73 : : * 1 ms sleep followed by exponential backoff until 8 ms.
74 : : */
75 : 0 : usleep_range(sleep_usecs / 2, sleep_usecs);
76 [ # # ]: 0 : if (sleep_usecs < 8 * USEC_PER_MSEC)
77 : 0 : sleep_usecs *= 2;
78 : : }
79 : :
80 : 0 : do_gettimeofday(&end);
81 : 0 : elapsed_msecs64 = timeval_to_ns(&end) - timeval_to_ns(&start);
82 : 0 : do_div(elapsed_msecs64, NSEC_PER_MSEC);
83 : : elapsed_msecs = elapsed_msecs64;
84 : :
85 [ # # ]: 0 : if (todo) {
86 : 0 : printk("\n");
87 [ # # ]: 0 : printk(KERN_ERR "Freezing of tasks %s after %d.%03d seconds "
88 : : "(%d tasks refusing to freeze, wq_busy=%d):\n",
89 : : wakeup ? "aborted" : "failed",
90 : : elapsed_msecs / 1000, elapsed_msecs % 1000,
91 : : todo - wq_busy, wq_busy);
92 : :
93 [ # # ]: 0 : if (!wakeup) {
94 : 0 : read_lock(&tasklist_lock);
95 [ # # ]: 0 : do_each_thread(g, p) {
96 [ # # # # ]: 0 : if (p != current && !freezer_should_skip(p)
97 [ # # ][ # # ]: 0 : && freezing(p) && !frozen(p))
98 : 0 : sched_show_task(p);
99 [ # # ]: 0 : } while_each_thread(g, p);
100 : : read_unlock(&tasklist_lock);
101 : : }
102 : : } else {
103 : 0 : printk("(elapsed %d.%03d seconds) ", elapsed_msecs / 1000,
104 : : elapsed_msecs % 1000);
105 : : }
106 : :
107 [ # # ]: 0 : return todo ? -EBUSY : 0;
108 : : }
109 : :
110 : : /**
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.
114 : : *
115 : : * On success, returns 0. On failure, -errno and system is fully thawed.
116 : : */
117 : 0 : int freeze_processes(void)
118 : : {
119 : : int error;
120 : :
121 : 0 : error = __usermodehelper_disable(UMH_FREEZING);
122 [ # # ]: 0 : if (error)
123 : : return error;
124 : :
125 : : /* Make sure this task doesn't get frozen */
126 : 0 : current->flags |= PF_SUSPEND_TASK;
127 : :
128 [ # # ]: 0 : if (!pm_freezing)
129 : : atomic_inc(&system_freezing_cnt);
130 : :
131 : 0 : printk("Freezing user space processes ... ");
132 : 0 : pm_freezing = true;
133 : 0 : error = try_to_freeze_tasks(true);
134 [ # # ]: 0 : if (!error) {
135 : 0 : printk("done.");
136 : 0 : __usermodehelper_set_disable_depth(UMH_DISABLED);
137 : : oom_killer_disable();
138 : : }
139 : 0 : printk("\n");
140 [ # # ]: 0 : BUG_ON(in_atomic());
141 : :
142 [ # # ]: 0 : if (error)
143 : 0 : thaw_processes();
144 : 0 : return error;
145 : : }
146 : :
147 : : /**
148 : : * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator.
149 : : *
150 : : * On success, returns 0. On failure, -errno and only the kernel threads are
151 : : * thawed, so as to give a chance to the caller to do additional cleanups
152 : : * (if any) before thawing the userspace tasks. So, it is the responsibility
153 : : * of the caller to thaw the userspace tasks, when the time is right.
154 : : */
155 : 0 : int freeze_kernel_threads(void)
156 : : {
157 : : int error;
158 : :
159 : 0 : printk("Freezing remaining freezable tasks ... ");
160 : 0 : pm_nosig_freezing = true;
161 : 0 : error = try_to_freeze_tasks(false);
162 [ # # ]: 0 : if (!error)
163 : 0 : printk("done.");
164 : :
165 : 0 : printk("\n");
166 [ # # ]: 0 : BUG_ON(in_atomic());
167 : :
168 [ # # ]: 0 : if (error)
169 : 0 : thaw_kernel_threads();
170 : 0 : return error;
171 : : }
172 : :
173 : 0 : void thaw_processes(void)
174 : : {
175 : : struct task_struct *g, *p;
176 : 0 : struct task_struct *curr = current;
177 : :
178 [ # # ]: 0 : if (pm_freezing)
179 : : atomic_dec(&system_freezing_cnt);
180 : 0 : pm_freezing = false;
181 : 0 : pm_nosig_freezing = false;
182 : :
183 : : oom_killer_enable();
184 : :
185 : 0 : printk("Restarting tasks ... ");
186 : :
187 : 0 : thaw_workqueues();
188 : :
189 : 0 : read_lock(&tasklist_lock);
190 [ # # ]: 0 : do_each_thread(g, p) {
191 : : /* No other threads should have PF_SUSPEND_TASK set */
192 [ # # ][ # # ]: 0 : WARN_ON((p != curr) && (p->flags & PF_SUSPEND_TASK));
[ # # ]
193 : 0 : __thaw_task(p);
194 [ # # ]: 0 : } while_each_thread(g, p);
195 : : read_unlock(&tasklist_lock);
196 : :
197 [ # # ]: 0 : WARN_ON(!(curr->flags & PF_SUSPEND_TASK));
198 : 0 : curr->flags &= ~PF_SUSPEND_TASK;
199 : :
200 : : usermodehelper_enable();
201 : :
202 : 0 : schedule();
203 : 0 : printk("done.\n");
204 : 0 : }
205 : :
206 : 0 : void thaw_kernel_threads(void)
207 : : {
208 : : struct task_struct *g, *p;
209 : :
210 : 0 : pm_nosig_freezing = false;
211 : 0 : printk("Restarting kernel threads ... ");
212 : :
213 : 0 : thaw_workqueues();
214 : :
215 : 0 : read_lock(&tasklist_lock);
216 [ # # ]: 0 : do_each_thread(g, p) {
217 [ # # ]: 0 : if (p->flags & (PF_KTHREAD | PF_WQ_WORKER))
218 : 0 : __thaw_task(p);
219 [ # # ]: 0 : } while_each_thread(g, p);
220 : : read_unlock(&tasklist_lock);
221 : :
222 : 0 : schedule();
223 : 0 : printk("done.\n");
224 : 0 : }
|