printk: use rcuidle console tracepoint
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / kernel / power / process.c
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 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_csecs64;
34 unsigned int elapsed_csecs;
35 bool wakeup = false;
36
37 do_gettimeofday(&start);
38
39 end_time = jiffies + msecs_to_jiffies(freeze_timeout_msecs);
40
41 if (!user_only)
42 freeze_workqueues_begin();
43
44 while (true) {
45 todo = 0;
46 read_lock(&tasklist_lock);
47 do_each_thread(g, p) {
48 if (p == current || !freeze_task(p))
49 continue;
50
51 if (!freezer_should_skip(p))
52 todo++;
53 } while_each_thread(g, p);
54 read_unlock(&tasklist_lock);
55
56 if (!user_only) {
57 wq_busy = freeze_workqueues_busy();
58 todo += wq_busy;
59 }
60
61 if (!todo || time_after(jiffies, end_time))
62 break;
63
64 if (pm_wakeup_pending()) {
65 wakeup = true;
66 break;
67 }
68
69 /*
70 * We need to retry, but first give the freezing tasks some
71 * time to enter the refrigerator.
72 */
73 msleep(10);
74 }
75
76 do_gettimeofday(&end);
77 elapsed_csecs64 = timeval_to_ns(&end) - timeval_to_ns(&start);
78 do_div(elapsed_csecs64, NSEC_PER_SEC / 100);
79 elapsed_csecs = elapsed_csecs64;
80
81 if (todo) {
82 printk("\n");
83 printk(KERN_ERR "Freezing of tasks %s after %d.%02d seconds "
84 "(%d tasks refusing to freeze, wq_busy=%d):\n",
85 wakeup ? "aborted" : "failed",
86 elapsed_csecs / 100, elapsed_csecs % 100,
87 todo - wq_busy, wq_busy);
88
89 if (!wakeup) {
90 read_lock(&tasklist_lock);
91 do_each_thread(g, p) {
92 if (p != current && !freezer_should_skip(p)
93 && freezing(p) && !frozen(p))
94 sched_show_task(p);
95 } while_each_thread(g, p);
96 read_unlock(&tasklist_lock);
97 }
98 } else {
99 printk("(elapsed %d.%02d seconds) ", elapsed_csecs / 100,
100 elapsed_csecs % 100);
101 }
102
103 return todo ? -EBUSY : 0;
104 }
105
106 /*
107 * Returns true if all freezable tasks (except for current) are frozen already
108 */
109 static bool check_frozen_processes(void)
110 {
111 struct task_struct *g, *p;
112 bool ret = true;
113
114 read_lock(&tasklist_lock);
115 for_each_process_thread(g, p) {
116 if (p != current && !freezer_should_skip(p) &&
117 !frozen(p)) {
118 ret = false;
119 goto done;
120 }
121 }
122 done:
123 read_unlock(&tasklist_lock);
124
125 return ret;
126 }
127
128 /**
129 * freeze_processes - Signal user space processes to enter the refrigerator.
130 *
131 * On success, returns 0. On failure, -errno and system is fully thawed.
132 */
133 int freeze_processes(void)
134 {
135 int error;
136 int oom_kills_saved;
137
138 error = __usermodehelper_disable(UMH_FREEZING);
139 if (error)
140 return error;
141
142 if (!pm_freezing)
143 atomic_inc(&system_freezing_cnt);
144
145 printk("Freezing user space processes ... ");
146 pm_freezing = true;
147 oom_kills_saved = oom_kills_count();
148 error = try_to_freeze_tasks(true);
149 if (!error) {
150 __usermodehelper_set_disable_depth(UMH_DISABLED);
151 oom_killer_disable();
152
153 /*
154 * There might have been an OOM kill while we were
155 * freezing tasks and the killed task might be still
156 * on the way out so we have to double check for race.
157 */
158 if (oom_kills_count() != oom_kills_saved &&
159 !check_frozen_processes()) {
160 __usermodehelper_set_disable_depth(UMH_ENABLED);
161 printk("OOM in progress.");
162 error = -EBUSY;
163 goto done;
164 }
165 printk("done.");
166 }
167 done:
168 printk("\n");
169 BUG_ON(in_atomic());
170
171 if (error)
172 thaw_processes();
173 return error;
174 }
175
176 /**
177 * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator.
178 *
179 * On success, returns 0. On failure, -errno and only the kernel threads are
180 * thawed, so as to give a chance to the caller to do additional cleanups
181 * (if any) before thawing the userspace tasks. So, it is the responsibility
182 * of the caller to thaw the userspace tasks, when the time is right.
183 */
184 int freeze_kernel_threads(void)
185 {
186 int error;
187
188 printk("Freezing remaining freezable tasks ... ");
189 pm_nosig_freezing = true;
190 error = try_to_freeze_tasks(false);
191 if (!error)
192 printk("done.");
193
194 printk("\n");
195 BUG_ON(in_atomic());
196
197 if (error)
198 thaw_kernel_threads();
199 return error;
200 }
201
202 void thaw_processes(void)
203 {
204 struct task_struct *g, *p;
205
206 if (pm_freezing)
207 atomic_dec(&system_freezing_cnt);
208 pm_freezing = false;
209 pm_nosig_freezing = false;
210
211 oom_killer_enable();
212
213 printk("Restarting tasks ... ");
214
215 __usermodehelper_set_disable_depth(UMH_FREEZING);
216 thaw_workqueues();
217
218 read_lock(&tasklist_lock);
219 do_each_thread(g, p) {
220 __thaw_task(p);
221 } while_each_thread(g, p);
222 read_unlock(&tasklist_lock);
223
224 usermodehelper_enable();
225
226 schedule();
227 printk("done.\n");
228 }
229
230 void thaw_kernel_threads(void)
231 {
232 struct task_struct *g, *p;
233
234 pm_nosig_freezing = false;
235 printk("Restarting kernel threads ... ");
236
237 thaw_workqueues();
238
239 read_lock(&tasklist_lock);
240 do_each_thread(g, p) {
241 if (p->flags & (PF_KTHREAD | PF_WQ_WORKER))
242 __thaw_task(p);
243 } while_each_thread(g, p);
244 read_unlock(&tasklist_lock);
245
246 schedule();
247 printk("done.\n");
248 }