freezer: close potential race between refrigerator and thaw_tasks
[linux-2.6] / 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/suspend.h>
13 #include <linux/module.h>
14 #include <linux/syscalls.h>
15 #include <linux/freezer.h>
16
17 /* 
18  * Timeout for stopping processes
19  */
20 #define TIMEOUT (20 * HZ)
21
22 #define FREEZER_KERNEL_THREADS 0
23 #define FREEZER_USER_SPACE 1
24
25 static inline int freezeable(struct task_struct * p)
26 {
27         if ((p == current) ||
28             (p->flags & PF_NOFREEZE) ||
29             (p->exit_state != 0))
30                 return 0;
31         return 1;
32 }
33
34 /* Refrigerator is place where frozen processes are stored :-). */
35 void refrigerator(void)
36 {
37         /* Hmm, should we be allowed to suspend when there are realtime
38            processes around? */
39         long save;
40
41         task_lock(current);
42         if (freezing(current)) {
43                 frozen_process(current);
44                 task_unlock(current);
45         } else {
46                 task_unlock(current);
47                 return;
48         }
49         save = current->state;
50         pr_debug("%s entered refrigerator\n", current->comm);
51
52         spin_lock_irq(&current->sighand->siglock);
53         recalc_sigpending(); /* We sent fake signal, clean it up */
54         spin_unlock_irq(&current->sighand->siglock);
55
56         for (;;) {
57                 set_current_state(TASK_UNINTERRUPTIBLE);
58                 if (!frozen(current))
59                         break;
60                 schedule();
61         }
62         pr_debug("%s left refrigerator\n", current->comm);
63         current->state = save;
64 }
65
66 static inline void freeze_process(struct task_struct *p)
67 {
68         unsigned long flags;
69
70         if (!freezing(p)) {
71                 rmb();
72                 if (!frozen(p)) {
73                         if (p->state == TASK_STOPPED)
74                                 force_sig_specific(SIGSTOP, p);
75
76                         freeze(p);
77                         spin_lock_irqsave(&p->sighand->siglock, flags);
78                         signal_wake_up(p, p->state == TASK_STOPPED);
79                         spin_unlock_irqrestore(&p->sighand->siglock, flags);
80                 }
81         }
82 }
83
84 static void cancel_freezing(struct task_struct *p)
85 {
86         unsigned long flags;
87
88         if (freezing(p)) {
89                 pr_debug("  clean up: %s\n", p->comm);
90                 do_not_freeze(p);
91                 spin_lock_irqsave(&p->sighand->siglock, flags);
92                 recalc_sigpending_tsk(p);
93                 spin_unlock_irqrestore(&p->sighand->siglock, flags);
94         }
95 }
96
97 static inline int is_user_space(struct task_struct *p)
98 {
99         return p->mm && !(p->flags & PF_BORROWED_MM);
100 }
101
102 static unsigned int try_to_freeze_tasks(int freeze_user_space)
103 {
104         struct task_struct *g, *p;
105         unsigned long end_time;
106         unsigned int todo;
107
108         end_time = jiffies + TIMEOUT;
109         do {
110                 todo = 0;
111                 read_lock(&tasklist_lock);
112                 do_each_thread(g, p) {
113                         if (!freezeable(p))
114                                 continue;
115
116                         if (frozen(p))
117                                 continue;
118
119                         if (p->state == TASK_TRACED && frozen(p->parent)) {
120                                 cancel_freezing(p);
121                                 continue;
122                         }
123                         if (is_user_space(p)) {
124                                 if (!freeze_user_space)
125                                         continue;
126
127                                 /* Freeze the task unless there is a vfork
128                                  * completion pending
129                                  */
130                                 if (!p->vfork_done)
131                                         freeze_process(p);
132                         } else {
133                                 if (freeze_user_space)
134                                         continue;
135
136                                 freeze_process(p);
137                         }
138                         todo++;
139                 } while_each_thread(g, p);
140                 read_unlock(&tasklist_lock);
141                 yield();                        /* Yield is okay here */
142                 if (todo && time_after(jiffies, end_time))
143                         break;
144         } while (todo);
145
146         if (todo) {
147                 /* This does not unfreeze processes that are already frozen
148                  * (we have slightly ugly calling convention in that respect,
149                  * and caller must call thaw_processes() if something fails),
150                  * but it cleans up leftover PF_FREEZE requests.
151                  */
152                 printk("\n");
153                 printk(KERN_ERR "Stopping %s timed out after %d seconds "
154                                 "(%d tasks refusing to freeze):\n",
155                                 freeze_user_space ? "user space processes" :
156                                         "kernel threads",
157                                 TIMEOUT / HZ, todo);
158                 read_lock(&tasklist_lock);
159                 do_each_thread(g, p) {
160                         if (is_user_space(p) == !freeze_user_space)
161                                 continue;
162
163                         task_lock(p);
164                         if (freezeable(p) && !frozen(p))
165                                 printk(KERN_ERR " %s\n", p->comm);
166
167                         cancel_freezing(p);
168                         task_unlock(p);
169                 } while_each_thread(g, p);
170                 read_unlock(&tasklist_lock);
171         }
172
173         return todo;
174 }
175
176 /**
177  *      freeze_processes - tell processes to enter the refrigerator
178  *
179  *      Returns 0 on success, or the number of processes that didn't freeze,
180  *      although they were told to.
181  */
182 int freeze_processes(void)
183 {
184         unsigned int nr_unfrozen;
185
186         printk("Stopping tasks ... ");
187         nr_unfrozen = try_to_freeze_tasks(FREEZER_USER_SPACE);
188         if (nr_unfrozen)
189                 return nr_unfrozen;
190
191         sys_sync();
192         nr_unfrozen = try_to_freeze_tasks(FREEZER_KERNEL_THREADS);
193         if (nr_unfrozen)
194                 return nr_unfrozen;
195
196         printk("done.\n");
197         BUG_ON(in_atomic());
198         return 0;
199 }
200
201 static void thaw_tasks(int thaw_user_space)
202 {
203         struct task_struct *g, *p;
204
205         read_lock(&tasklist_lock);
206         do_each_thread(g, p) {
207                 if (!freezeable(p))
208                         continue;
209
210                 if (is_user_space(p) == !thaw_user_space)
211                         continue;
212
213                 if (!thaw_process(p))
214                         printk(KERN_WARNING " Strange, %s not stopped\n",
215                                 p->comm );
216         } while_each_thread(g, p);
217         read_unlock(&tasklist_lock);
218 }
219
220 void thaw_processes(void)
221 {
222         printk("Restarting tasks ... ");
223         thaw_tasks(FREEZER_KERNEL_THREADS);
224         thaw_tasks(FREEZER_USER_SPACE);
225         schedule();
226         printk("done.\n");
227 }
228
229 EXPORT_SYMBOL(refrigerator);