diff options
Diffstat (limited to 'kernel/power/process.c')
-rw-r--r-- | kernel/power/process.c | 57 |
1 files changed, 34 insertions, 23 deletions
diff --git a/kernel/power/process.c b/kernel/power/process.c index 088419387388..e0233d8422b9 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c | |||
@@ -31,16 +31,36 @@ static inline int freezeable(struct task_struct * p) | |||
31 | return 1; | 31 | return 1; |
32 | } | 32 | } |
33 | 33 | ||
34 | /* | ||
35 | * freezing is complete, mark current process as frozen | ||
36 | */ | ||
37 | static inline void frozen_process(void) | ||
38 | { | ||
39 | if (!unlikely(current->flags & PF_NOFREEZE)) { | ||
40 | current->flags |= PF_FROZEN; | ||
41 | wmb(); | ||
42 | } | ||
43 | clear_tsk_thread_flag(current, TIF_FREEZE); | ||
44 | } | ||
45 | |||
34 | /* Refrigerator is place where frozen processes are stored :-). */ | 46 | /* Refrigerator is place where frozen processes are stored :-). */ |
35 | void refrigerator(void) | 47 | void refrigerator(void) |
36 | { | 48 | { |
37 | /* Hmm, should we be allowed to suspend when there are realtime | 49 | /* Hmm, should we be allowed to suspend when there are realtime |
38 | processes around? */ | 50 | processes around? */ |
39 | long save; | 51 | long save; |
52 | |||
53 | task_lock(current); | ||
54 | if (freezing(current)) { | ||
55 | frozen_process(); | ||
56 | task_unlock(current); | ||
57 | } else { | ||
58 | task_unlock(current); | ||
59 | return; | ||
60 | } | ||
40 | save = current->state; | 61 | save = current->state; |
41 | pr_debug("%s entered refrigerator\n", current->comm); | 62 | pr_debug("%s entered refrigerator\n", current->comm); |
42 | 63 | ||
43 | frozen_process(current); | ||
44 | spin_lock_irq(¤t->sighand->siglock); | 64 | spin_lock_irq(¤t->sighand->siglock); |
45 | recalc_sigpending(); /* We sent fake signal, clean it up */ | 65 | recalc_sigpending(); /* We sent fake signal, clean it up */ |
46 | spin_unlock_irq(¤t->sighand->siglock); | 66 | spin_unlock_irq(¤t->sighand->siglock); |
@@ -81,7 +101,7 @@ static void cancel_freezing(struct task_struct *p) | |||
81 | pr_debug(" clean up: %s\n", p->comm); | 101 | pr_debug(" clean up: %s\n", p->comm); |
82 | do_not_freeze(p); | 102 | do_not_freeze(p); |
83 | spin_lock_irqsave(&p->sighand->siglock, flags); | 103 | spin_lock_irqsave(&p->sighand->siglock, flags); |
84 | recalc_sigpending_tsk(p); | 104 | recalc_sigpending_and_wake(p); |
85 | spin_unlock_irqrestore(&p->sighand->siglock, flags); | 105 | spin_unlock_irqrestore(&p->sighand->siglock, flags); |
86 | } | 106 | } |
87 | } | 107 | } |
@@ -112,22 +132,12 @@ static unsigned int try_to_freeze_tasks(int freeze_user_space) | |||
112 | cancel_freezing(p); | 132 | cancel_freezing(p); |
113 | continue; | 133 | continue; |
114 | } | 134 | } |
115 | if (is_user_space(p)) { | 135 | if (freeze_user_space && !is_user_space(p)) |
116 | if (!freeze_user_space) | 136 | continue; |
117 | continue; | 137 | |
118 | 138 | freeze_process(p); | |
119 | /* Freeze the task unless there is a vfork | 139 | if (!freezer_should_skip(p)) |
120 | * completion pending | 140 | todo++; |
121 | */ | ||
122 | if (!p->vfork_done) | ||
123 | freeze_process(p); | ||
124 | } else { | ||
125 | if (freeze_user_space) | ||
126 | continue; | ||
127 | |||
128 | freeze_process(p); | ||
129 | } | ||
130 | todo++; | ||
131 | } while_each_thread(g, p); | 141 | } while_each_thread(g, p); |
132 | read_unlock(&tasklist_lock); | 142 | read_unlock(&tasklist_lock); |
133 | yield(); /* Yield is okay here */ | 143 | yield(); /* Yield is okay here */ |
@@ -149,13 +159,16 @@ static unsigned int try_to_freeze_tasks(int freeze_user_space) | |||
149 | TIMEOUT / HZ, todo); | 159 | TIMEOUT / HZ, todo); |
150 | read_lock(&tasklist_lock); | 160 | read_lock(&tasklist_lock); |
151 | do_each_thread(g, p) { | 161 | do_each_thread(g, p) { |
152 | if (is_user_space(p) == !freeze_user_space) | 162 | if (freeze_user_space && !is_user_space(p)) |
153 | continue; | 163 | continue; |
154 | 164 | ||
155 | if (freezeable(p) && !frozen(p)) | 165 | task_lock(p); |
166 | if (freezeable(p) && !frozen(p) && | ||
167 | !freezer_should_skip(p)) | ||
156 | printk(KERN_ERR " %s\n", p->comm); | 168 | printk(KERN_ERR " %s\n", p->comm); |
157 | 169 | ||
158 | cancel_freezing(p); | 170 | cancel_freezing(p); |
171 | task_unlock(p); | ||
159 | } while_each_thread(g, p); | 172 | } while_each_thread(g, p); |
160 | read_unlock(&tasklist_lock); | 173 | read_unlock(&tasklist_lock); |
161 | } | 174 | } |
@@ -200,9 +213,7 @@ static void thaw_tasks(int thaw_user_space) | |||
200 | if (is_user_space(p) == !thaw_user_space) | 213 | if (is_user_space(p) == !thaw_user_space) |
201 | continue; | 214 | continue; |
202 | 215 | ||
203 | if (!thaw_process(p)) | 216 | thaw_process(p); |
204 | printk(KERN_WARNING " Strange, %s not stopped\n", | ||
205 | p->comm ); | ||
206 | } while_each_thread(g, p); | 217 | } while_each_thread(g, p); |
207 | read_unlock(&tasklist_lock); | 218 | read_unlock(&tasklist_lock); |
208 | } | 219 | } |