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