Merge tag 'md-3.9-fixes' of git://neil.brown.name/md
[linux-2.6-microblaze.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  * freeze_processes - Signal user space processes to enter the refrigerator.
108  *
109  * On success, returns 0.  On failure, -errno and system is fully thawed.
110  */
111 int freeze_processes(void)
112 {
113         int error;
114
115         error = __usermodehelper_disable(UMH_FREEZING);
116         if (error)
117                 return error;
118
119         if (!pm_freezing)
120                 atomic_inc(&system_freezing_cnt);
121
122         printk("Freezing user space processes ... ");
123         pm_freezing = true;
124         error = try_to_freeze_tasks(true);
125         if (!error) {
126                 printk("done.");
127                 __usermodehelper_set_disable_depth(UMH_DISABLED);
128                 oom_killer_disable();
129         }
130         printk("\n");
131         BUG_ON(in_atomic());
132
133         if (error)
134                 thaw_processes();
135         return error;
136 }
137
138 /**
139  * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator.
140  *
141  * On success, returns 0.  On failure, -errno and only the kernel threads are
142  * thawed, so as to give a chance to the caller to do additional cleanups
143  * (if any) before thawing the userspace tasks. So, it is the responsibility
144  * of the caller to thaw the userspace tasks, when the time is right.
145  */
146 int freeze_kernel_threads(void)
147 {
148         int error;
149
150         printk("Freezing remaining freezable tasks ... ");
151         pm_nosig_freezing = true;
152         error = try_to_freeze_tasks(false);
153         if (!error)
154                 printk("done.");
155
156         printk("\n");
157         BUG_ON(in_atomic());
158
159         if (error)
160                 thaw_kernel_threads();
161         return error;
162 }
163
164 void thaw_processes(void)
165 {
166         struct task_struct *g, *p;
167
168         if (pm_freezing)
169                 atomic_dec(&system_freezing_cnt);
170         pm_freezing = false;
171         pm_nosig_freezing = false;
172
173         oom_killer_enable();
174
175         printk("Restarting tasks ... ");
176
177         thaw_workqueues();
178
179         read_lock(&tasklist_lock);
180         do_each_thread(g, p) {
181                 __thaw_task(p);
182         } while_each_thread(g, p);
183         read_unlock(&tasklist_lock);
184
185         usermodehelper_enable();
186
187         schedule();
188         printk("done.\n");
189 }
190
191 void thaw_kernel_threads(void)
192 {
193         struct task_struct *g, *p;
194
195         pm_nosig_freezing = false;
196         printk("Restarting kernel threads ... ");
197
198         thaw_workqueues();
199
200         read_lock(&tasklist_lock);
201         do_each_thread(g, p) {
202                 if (p->flags & (PF_KTHREAD | PF_WQ_WORKER))
203                         __thaw_task(p);
204         } while_each_thread(g, p);
205         read_unlock(&tasklist_lock);
206
207         schedule();
208         printk("done.\n");
209 }