fd0ebb942f5097495e493b79527da5b7c87f74d4
[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             (p->state == TASK_STOPPED))
33                 return 0;
34         return 1;
35 }
36
37 /* Refrigerator is place where frozen processes are stored :-). */
38 void refrigerator(void)
39 {
40         /* Hmm, should we be allowed to suspend when there are realtime
41            processes around? */
42         long save;
43         save = current->state;
44         pr_debug("%s entered refrigerator\n", current->comm);
45
46         frozen_process(current);
47         spin_lock_irq(&current->sighand->siglock);
48         recalc_sigpending(); /* We sent fake signal, clean it up */
49         spin_unlock_irq(&current->sighand->siglock);
50
51         while (frozen(current)) {
52                 current->state = TASK_UNINTERRUPTIBLE;
53                 schedule();
54         }
55         pr_debug("%s left refrigerator\n", current->comm);
56         current->state = save;
57 }
58
59 static inline void freeze_process(struct task_struct *p)
60 {
61         unsigned long flags;
62
63         if (!freezing(p)) {
64                 freeze(p);
65                 spin_lock_irqsave(&p->sighand->siglock, flags);
66                 signal_wake_up(p, 0);
67                 spin_unlock_irqrestore(&p->sighand->siglock, flags);
68         }
69 }
70
71 static void cancel_freezing(struct task_struct *p)
72 {
73         unsigned long flags;
74
75         if (freezing(p)) {
76                 pr_debug("  clean up: %s\n", p->comm);
77                 do_not_freeze(p);
78                 spin_lock_irqsave(&p->sighand->siglock, flags);
79                 recalc_sigpending_tsk(p);
80                 spin_unlock_irqrestore(&p->sighand->siglock, flags);
81         }
82 }
83
84 static inline int is_user_space(struct task_struct *p)
85 {
86         return p->mm && !(p->flags & PF_BORROWED_MM);
87 }
88
89 /* 0 = success, else # of processes that we failed to stop */
90 int freeze_processes(void)
91 {
92         int todo, nr_user, user_frozen;
93         unsigned long start_time;
94         struct task_struct *g, *p;
95
96         printk("Stopping tasks... ");
97         start_time = jiffies;
98         user_frozen = 0;
99         do {
100                 nr_user = todo = 0;
101                 read_lock(&tasklist_lock);
102                 do_each_thread(g, p) {
103                         if (!freezeable(p))
104                                 continue;
105                         if (frozen(p))
106                                 continue;
107                         if (p->state == TASK_TRACED &&
108                             (frozen(p->parent) ||
109                              p->parent->state == TASK_STOPPED)) {
110                                 cancel_freezing(p);
111                                 continue;
112                         }
113                         if (is_user_space(p)) {
114                                 /* Freeze the task unless there is a vfork
115                                  * completion pending
116                                  */
117                                 if (!p->vfork_done)
118                                         freeze_process(p);
119                                 nr_user++;
120                         } else {
121                                 /* Freeze only if the user space is frozen */
122                                 if (user_frozen)
123                                         freeze_process(p);
124                                 todo++;
125                         }
126                 } while_each_thread(g, p);
127                 read_unlock(&tasklist_lock);
128                 todo += nr_user;
129                 if (!user_frozen && !nr_user) {
130                         sys_sync();
131                         start_time = jiffies;
132                 }
133                 user_frozen = !nr_user;
134                 yield();                        /* Yield is okay here */
135                 if (todo && time_after(jiffies, start_time + TIMEOUT))
136                         break;
137         } while(todo);
138
139         /* This does not unfreeze processes that are already frozen
140          * (we have slightly ugly calling convention in that respect,
141          * and caller must call thaw_processes() if something fails),
142          * but it cleans up leftover PF_FREEZE requests.
143          */
144         if (todo) {
145                 printk("\n");
146                 printk(KERN_ERR "Stopping tasks timed out "
147                         "after %d seconds (%d tasks remaining):\n",
148                         TIMEOUT / HZ, todo);
149                 read_lock(&tasklist_lock);
150                 do_each_thread(g, p) {
151                         if (freezeable(p) && !frozen(p))
152                                 printk(KERN_ERR " %s\n", p->comm);
153                         cancel_freezing(p);
154                 } while_each_thread(g, p);
155                 read_unlock(&tasklist_lock);
156                 return todo;
157         }
158
159         printk("done.\n");
160         BUG_ON(in_atomic());
161         return 0;
162 }
163
164 static void thaw_tasks(int thaw_user_space)
165 {
166         struct task_struct *g, *p;
167
168         read_lock(&tasklist_lock);
169         do_each_thread(g, p) {
170                 if (!freezeable(p))
171                         continue;
172
173                 if (is_user_space(p) == !thaw_user_space)
174                         continue;
175
176                 if (!thaw_process(p))
177                         printk(KERN_WARNING " Strange, %s not stopped\n",
178                                 p->comm );
179         } while_each_thread(g, p);
180         read_unlock(&tasklist_lock);
181 }
182
183 void thaw_processes(void)
184 {
185         printk("Restarting tasks ... ");
186         thaw_tasks(FREEZER_KERNEL_THREADS);
187         thaw_tasks(FREEZER_USER_SPACE);
188         schedule();
189         printk("done.\n");
190 }
191
192 EXPORT_SYMBOL(refrigerator);