blob: 0ca8d83e2369e253706ff787c2e4243928fbcca0 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include <linux/interrupt.h>
Alexey Dobriyan1a8670a2009-09-21 17:03:09 -070012#include <linux/oom.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <linux/suspend.h>
14#include <linux/module.h>
Rafael J. Wysocki02aaeb92006-03-23 03:00:04 -080015#include <linux/syscalls.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080016#include <linux/freezer.h>
Tejun Heobe404f02009-10-08 22:47:30 +020017#include <linux/delay.h>
Tejun Heoa0a1a5f2010-06-29 10:07:12 +020018#include <linux/workqueue.h>
Rafael J. Wysocki1e732032012-03-28 23:30:21 +020019#include <linux/kmod.h>
Todd E Brandtbb3632c2014-06-06 05:40:17 -070020#include <trace/events/power.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021
22/*
23 * Timeout for stopping processes
24 */
Li Fei957d1282013-02-01 08:56:03 +000025unsigned int __read_mostly freeze_timeout_msecs = 20 * MSEC_PER_SEC;
Linus Torvalds1da177e2005-04-16 15:20:36 -070026
Tejun Heo839e3402011-11-21 12:32:26 -080027static int try_to_freeze_tasks(bool user_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -070028{
Linus Torvalds1da177e2005-04-16 15:20:36 -070029 struct task_struct *g, *p;
Rafael J. Wysocki11b2ce22006-12-06 20:34:40 -080030 unsigned long end_time;
31 unsigned int todo;
Tejun Heoa0a1a5f2010-06-29 10:07:12 +020032 bool wq_busy = false;
Rafael J. Wysocki438e2ce2007-10-18 03:04:49 -070033 struct timeval start, end;
Colin Cross18ad0c62013-05-06 23:50:10 +000034 u64 elapsed_msecs64;
35 unsigned int elapsed_msecs;
Rafael J. Wysockidbeeec52010-10-04 22:07:32 +020036 bool wakeup = false;
Colin Cross18ad0c62013-05-06 23:50:10 +000037 int sleep_usecs = USEC_PER_MSEC;
Rafael J. Wysocki438e2ce2007-10-18 03:04:49 -070038
39 do_gettimeofday(&start);
Christoph Lameter3e1d1d22005-06-24 23:13:50 -070040
Li Fei957d1282013-02-01 08:56:03 +000041 end_time = jiffies + msecs_to_jiffies(freeze_timeout_msecs);
Tejun Heoa0a1a5f2010-06-29 10:07:12 +020042
Tejun Heo839e3402011-11-21 12:32:26 -080043 if (!user_only)
Tejun Heoa0a1a5f2010-06-29 10:07:12 +020044 freeze_workqueues_begin();
45
Tejun Heobe404f02009-10-08 22:47:30 +020046 while (true) {
Rafael J. Wysocki11b2ce22006-12-06 20:34:40 -080047 todo = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070048 read_lock(&tasklist_lock);
49 do_each_thread(g, p) {
Tejun Heo839e3402011-11-21 12:32:26 -080050 if (p == current || !freeze_task(p))
Rafael J. Wysockid5d8c592007-10-18 03:04:46 -070051 continue;
52
Oleg Nesterov5d8f72b2012-10-26 19:46:06 +020053 if (!freezer_should_skip(p))
Rafael J. Wysockiba96a0c2007-05-23 13:57:25 -070054 todo++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070055 } while_each_thread(g, p);
56 read_unlock(&tasklist_lock);
Tejun Heoa0a1a5f2010-06-29 10:07:12 +020057
Tejun Heo839e3402011-11-21 12:32:26 -080058 if (!user_only) {
Tejun Heoa0a1a5f2010-06-29 10:07:12 +020059 wq_busy = freeze_workqueues_busy();
60 todo += wq_busy;
61 }
62
Tejun Heobe404f02009-10-08 22:47:30 +020063 if (!todo || time_after(jiffies, end_time))
Rafael J. Wysocki02aaeb92006-03-23 03:00:04 -080064 break;
Tejun Heobe404f02009-10-08 22:47:30 +020065
Rafael J. Wysockia2867e02010-12-03 22:58:31 +010066 if (pm_wakeup_pending()) {
Rafael J. Wysockidbeeec52010-10-04 22:07:32 +020067 wakeup = true;
68 break;
69 }
70
Tejun Heobe404f02009-10-08 22:47:30 +020071 /*
72 * We need to retry, but first give the freezing tasks some
Colin Cross18ad0c62013-05-06 23:50:10 +000073 * time to enter the refrigerator. Start with an initial
74 * 1 ms sleep followed by exponential backoff until 8 ms.
Tejun Heobe404f02009-10-08 22:47:30 +020075 */
Colin Cross18ad0c62013-05-06 23:50:10 +000076 usleep_range(sleep_usecs / 2, sleep_usecs);
77 if (sleep_usecs < 8 * USEC_PER_MSEC)
78 sleep_usecs *= 2;
Tejun Heobe404f02009-10-08 22:47:30 +020079 }
Christoph Lameter3e1d1d22005-06-24 23:13:50 -070080
Rafael J. Wysocki438e2ce2007-10-18 03:04:49 -070081 do_gettimeofday(&end);
Colin Cross18ad0c62013-05-06 23:50:10 +000082 elapsed_msecs64 = timeval_to_ns(&end) - timeval_to_ns(&start);
83 do_div(elapsed_msecs64, NSEC_PER_MSEC);
84 elapsed_msecs = elapsed_msecs64;
Rafael J. Wysocki438e2ce2007-10-18 03:04:49 -070085
Pavel Machek6161b2c2005-09-03 15:57:05 -070086 if (todo) {
Nigel Cunningham14b5b7c2006-12-06 20:34:26 -080087 printk("\n");
Colin Cross18ad0c62013-05-06 23:50:10 +000088 printk(KERN_ERR "Freezing of tasks %s after %d.%03d seconds "
Tejun Heoa0a1a5f2010-06-29 10:07:12 +020089 "(%d tasks refusing to freeze, wq_busy=%d):\n",
Rafael J. Wysockidbeeec52010-10-04 22:07:32 +020090 wakeup ? "aborted" : "failed",
Colin Cross18ad0c62013-05-06 23:50:10 +000091 elapsed_msecs / 1000, elapsed_msecs % 1000,
Tejun Heoa0a1a5f2010-06-29 10:07:12 +020092 todo - wq_busy, wq_busy);
93
Rafael J. Wysocki6c83b482012-02-11 00:00:34 +010094 if (!wakeup) {
95 read_lock(&tasklist_lock);
96 do_each_thread(g, p) {
97 if (p != current && !freezer_should_skip(p)
98 && freezing(p) && !frozen(p))
99 sched_show_task(p);
100 } while_each_thread(g, p);
101 read_unlock(&tasklist_lock);
102 }
Rafael J. Wysocki438e2ce2007-10-18 03:04:49 -0700103 } else {
Colin Cross18ad0c62013-05-06 23:50:10 +0000104 printk("(elapsed %d.%03d seconds) ", elapsed_msecs / 1000,
105 elapsed_msecs % 1000);
Pavel Machek6161b2c2005-09-03 15:57:05 -0700106 }
107
Rafael J. Wysockie7cd8a72007-07-19 01:47:34 -0700108 return todo ? -EBUSY : 0;
Rafael J. Wysocki11b2ce22006-12-06 20:34:40 -0800109}
110
111/**
Rafael J. Wysocki2aede852011-09-26 20:32:27 +0200112 * freeze_processes - Signal user space processes to enter the refrigerator.
Colin Cross2b44c4d2013-07-24 17:41:33 -0700113 * The current thread will not be frozen. The same process that calls
114 * freeze_processes must later call thaw_processes.
Tejun Heo03afed82011-11-21 12:32:24 -0800115 *
116 * On success, returns 0. On failure, -errno and system is fully thawed.
Rafael J. Wysocki11b2ce22006-12-06 20:34:40 -0800117 */
118int freeze_processes(void)
119{
Rafael J. Wysockie7cd8a72007-07-19 01:47:34 -0700120 int error;
Rafael J. Wysocki11b2ce22006-12-06 20:34:40 -0800121
Rafael J. Wysocki247bc032012-03-28 23:30:28 +0200122 error = __usermodehelper_disable(UMH_FREEZING);
Rafael J. Wysocki1e732032012-03-28 23:30:21 +0200123 if (error)
124 return error;
125
Colin Cross2b44c4d2013-07-24 17:41:33 -0700126 /* Make sure this task doesn't get frozen */
127 current->flags |= PF_SUSPEND_TASK;
128
Tejun Heoa3201222011-11-21 12:32:25 -0800129 if (!pm_freezing)
130 atomic_inc(&system_freezing_cnt);
131
Rafael J. Wysockib842ee52007-10-18 03:04:48 -0700132 printk("Freezing user space processes ... ");
Tejun Heoa3201222011-11-21 12:32:25 -0800133 pm_freezing = true;
Rafael J. Wysockiebb12db2008-06-11 22:04:29 +0200134 error = try_to_freeze_tasks(true);
Rafael J. Wysocki2aede852011-09-26 20:32:27 +0200135 if (!error) {
136 printk("done.");
Rafael J. Wysocki247bc032012-03-28 23:30:28 +0200137 __usermodehelper_set_disable_depth(UMH_DISABLED);
Rafael J. Wysocki2aede852011-09-26 20:32:27 +0200138 oom_killer_disable();
139 }
140 printk("\n");
141 BUG_ON(in_atomic());
142
Tejun Heo03afed82011-11-21 12:32:24 -0800143 if (error)
144 thaw_processes();
Rafael J. Wysocki2aede852011-09-26 20:32:27 +0200145 return error;
146}
147
148/**
149 * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator.
Tejun Heo03afed82011-11-21 12:32:24 -0800150 *
Srivatsa S. Bhat379e0be2012-02-03 22:22:41 +0100151 * On success, returns 0. On failure, -errno and only the kernel threads are
152 * thawed, so as to give a chance to the caller to do additional cleanups
153 * (if any) before thawing the userspace tasks. So, it is the responsibility
154 * of the caller to thaw the userspace tasks, when the time is right.
Rafael J. Wysocki2aede852011-09-26 20:32:27 +0200155 */
156int freeze_kernel_threads(void)
157{
158 int error;
Rafael J. Wysocki11b2ce22006-12-06 20:34:40 -0800159
Rafael J. Wysockib842ee52007-10-18 03:04:48 -0700160 printk("Freezing remaining freezable tasks ... ");
Tejun Heoa3201222011-11-21 12:32:25 -0800161 pm_nosig_freezing = true;
Rafael J. Wysockiebb12db2008-06-11 22:04:29 +0200162 error = try_to_freeze_tasks(false);
Rafael J. Wysocki2aede852011-09-26 20:32:27 +0200163 if (!error)
164 printk("done.");
Rafael J. Wysocki7f33d492009-06-16 15:32:41 -0700165
Rafael J. Wysockib842ee52007-10-18 03:04:48 -0700166 printk("\n");
Rafael J. Wysocki2aede852011-09-26 20:32:27 +0200167 BUG_ON(in_atomic());
Rafael J. Wysocki7f33d492009-06-16 15:32:41 -0700168
Tejun Heo03afed82011-11-21 12:32:24 -0800169 if (error)
Srivatsa S. Bhat379e0be2012-02-03 22:22:41 +0100170 thaw_kernel_threads();
Rafael J. Wysockib842ee52007-10-18 03:04:48 -0700171 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172}
173
Tejun Heo6cd8ded2011-11-21 12:32:23 -0800174void thaw_processes(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175{
176 struct task_struct *g, *p;
Colin Cross2b44c4d2013-07-24 17:41:33 -0700177 struct task_struct *curr = current;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700179 trace_suspend_resume(TPS("thaw_processes"), 0, true);
Tejun Heoa3201222011-11-21 12:32:25 -0800180 if (pm_freezing)
181 atomic_dec(&system_freezing_cnt);
182 pm_freezing = false;
183 pm_nosig_freezing = false;
184
Tejun Heo6cd8ded2011-11-21 12:32:23 -0800185 oom_killer_enable();
186
187 printk("Restarting tasks ... ");
188
189 thaw_workqueues();
190
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 read_lock(&tasklist_lock);
Rafael J. Wysockia9b6f562006-12-06 20:34:37 -0800192 do_each_thread(g, p) {
Colin Cross2b44c4d2013-07-24 17:41:33 -0700193 /* No other threads should have PF_SUSPEND_TASK set */
194 WARN_ON((p != curr) && (p->flags & PF_SUSPEND_TASK));
Tejun Heoa5be2d02011-11-21 12:32:23 -0800195 __thaw_task(p);
Rafael J. Wysockia9b6f562006-12-06 20:34:37 -0800196 } while_each_thread(g, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 read_unlock(&tasklist_lock);
Rafael J. Wysockia9b6f562006-12-06 20:34:37 -0800198
Colin Cross2b44c4d2013-07-24 17:41:33 -0700199 WARN_ON(!(curr->flags & PF_SUSPEND_TASK));
200 curr->flags &= ~PF_SUSPEND_TASK;
201
Rafael J. Wysocki1e732032012-03-28 23:30:21 +0200202 usermodehelper_enable();
203
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 schedule();
Nigel Cunningham14b5b7c2006-12-06 20:34:26 -0800205 printk("done.\n");
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700206 trace_suspend_resume(TPS("thaw_processes"), 0, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207}
208
Rafael J. Wysocki181e9bd2012-01-29 20:35:52 +0100209void thaw_kernel_threads(void)
210{
211 struct task_struct *g, *p;
212
213 pm_nosig_freezing = false;
214 printk("Restarting kernel threads ... ");
215
216 thaw_workqueues();
217
218 read_lock(&tasklist_lock);
219 do_each_thread(g, p) {
220 if (p->flags & (PF_KTHREAD | PF_WQ_WORKER))
221 __thaw_task(p);
222 } while_each_thread(g, p);
223 read_unlock(&tasklist_lock);
224
225 schedule();
226 printk("done.\n");
227}