diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-10-23 17:02:45 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-10-23 17:02:45 -0400 |
commit | 96ed753235c674a8cb261dac1a258cf6e50c6cd4 (patch) | |
tree | f9210625db82644ebcf88d1879288b2fc389d211 /kernel | |
parent | 37c72cac0e2ef9cd3c53dc9369a35dad6ef23f00 (diff) | |
parent | 71be2114a5474a76edad95343d89b8731457fccd (diff) |
Merge branch 'freezer'
* freezer:
PM / freezer: Clean up code after recent fixes
PM: convert do_each_thread to for_each_process_thread
OOM, PM: OOM killed task shouldn't escape PM suspend
freezer: remove obsolete comments in __thaw_task()
freezer: Do not freeze tasks killed by OOM killer
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/freezer.c | 9 | ||||
-rw-r--r-- | kernel/power/process.c | 57 |
2 files changed, 51 insertions, 15 deletions
diff --git a/kernel/freezer.c b/kernel/freezer.c index aa6a8aadb911..a8900a3bc27a 100644 --- a/kernel/freezer.c +++ b/kernel/freezer.c | |||
@@ -42,6 +42,9 @@ bool freezing_slow_path(struct task_struct *p) | |||
42 | if (p->flags & (PF_NOFREEZE | PF_SUSPEND_TASK)) | 42 | if (p->flags & (PF_NOFREEZE | PF_SUSPEND_TASK)) |
43 | return false; | 43 | return false; |
44 | 44 | ||
45 | if (test_thread_flag(TIF_MEMDIE)) | ||
46 | return false; | ||
47 | |||
45 | if (pm_nosig_freezing || cgroup_freezing(p)) | 48 | if (pm_nosig_freezing || cgroup_freezing(p)) |
46 | return true; | 49 | return true; |
47 | 50 | ||
@@ -147,12 +150,6 @@ void __thaw_task(struct task_struct *p) | |||
147 | { | 150 | { |
148 | unsigned long flags; | 151 | unsigned long flags; |
149 | 152 | ||
150 | /* | ||
151 | * Clear freezing and kick @p if FROZEN. Clearing is guaranteed to | ||
152 | * be visible to @p as waking up implies wmb. Waking up inside | ||
153 | * freezer_lock also prevents wakeups from leaking outside | ||
154 | * refrigerator. | ||
155 | */ | ||
156 | spin_lock_irqsave(&freezer_lock, flags); | 153 | spin_lock_irqsave(&freezer_lock, flags); |
157 | if (frozen(p)) | 154 | if (frozen(p)) |
158 | wake_up_process(p); | 155 | wake_up_process(p); |
diff --git a/kernel/power/process.c b/kernel/power/process.c index 7b323221b9ee..5a6ec8678b9a 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c | |||
@@ -46,13 +46,13 @@ static int try_to_freeze_tasks(bool user_only) | |||
46 | while (true) { | 46 | while (true) { |
47 | todo = 0; | 47 | todo = 0; |
48 | read_lock(&tasklist_lock); | 48 | read_lock(&tasklist_lock); |
49 | do_each_thread(g, p) { | 49 | for_each_process_thread(g, p) { |
50 | if (p == current || !freeze_task(p)) | 50 | if (p == current || !freeze_task(p)) |
51 | continue; | 51 | continue; |
52 | 52 | ||
53 | if (!freezer_should_skip(p)) | 53 | if (!freezer_should_skip(p)) |
54 | todo++; | 54 | todo++; |
55 | } while_each_thread(g, p); | 55 | } |
56 | read_unlock(&tasklist_lock); | 56 | read_unlock(&tasklist_lock); |
57 | 57 | ||
58 | if (!user_only) { | 58 | if (!user_only) { |
@@ -93,11 +93,11 @@ static int try_to_freeze_tasks(bool user_only) | |||
93 | 93 | ||
94 | if (!wakeup) { | 94 | if (!wakeup) { |
95 | read_lock(&tasklist_lock); | 95 | read_lock(&tasklist_lock); |
96 | do_each_thread(g, p) { | 96 | for_each_process_thread(g, p) { |
97 | if (p != current && !freezer_should_skip(p) | 97 | if (p != current && !freezer_should_skip(p) |
98 | && freezing(p) && !frozen(p)) | 98 | && freezing(p) && !frozen(p)) |
99 | sched_show_task(p); | 99 | sched_show_task(p); |
100 | } while_each_thread(g, p); | 100 | } |
101 | read_unlock(&tasklist_lock); | 101 | read_unlock(&tasklist_lock); |
102 | } | 102 | } |
103 | } else { | 103 | } else { |
@@ -108,6 +108,30 @@ static int try_to_freeze_tasks(bool user_only) | |||
108 | return todo ? -EBUSY : 0; | 108 | return todo ? -EBUSY : 0; |
109 | } | 109 | } |
110 | 110 | ||
111 | static bool __check_frozen_processes(void) | ||
112 | { | ||
113 | struct task_struct *g, *p; | ||
114 | |||
115 | for_each_process_thread(g, p) | ||
116 | if (p != current && !freezer_should_skip(p) && !frozen(p)) | ||
117 | return false; | ||
118 | |||
119 | return true; | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | * Returns true if all freezable tasks (except for current) are frozen already | ||
124 | */ | ||
125 | static bool check_frozen_processes(void) | ||
126 | { | ||
127 | bool ret; | ||
128 | |||
129 | read_lock(&tasklist_lock); | ||
130 | ret = __check_frozen_processes(); | ||
131 | read_unlock(&tasklist_lock); | ||
132 | return ret; | ||
133 | } | ||
134 | |||
111 | /** | 135 | /** |
112 | * freeze_processes - Signal user space processes to enter the refrigerator. | 136 | * freeze_processes - Signal user space processes to enter the refrigerator. |
113 | * The current thread will not be frozen. The same process that calls | 137 | * The current thread will not be frozen. The same process that calls |
@@ -118,6 +142,7 @@ static int try_to_freeze_tasks(bool user_only) | |||
118 | int freeze_processes(void) | 142 | int freeze_processes(void) |
119 | { | 143 | { |
120 | int error; | 144 | int error; |
145 | int oom_kills_saved; | ||
121 | 146 | ||
122 | error = __usermodehelper_disable(UMH_FREEZING); | 147 | error = __usermodehelper_disable(UMH_FREEZING); |
123 | if (error) | 148 | if (error) |
@@ -132,11 +157,25 @@ int freeze_processes(void) | |||
132 | pm_wakeup_clear(); | 157 | pm_wakeup_clear(); |
133 | printk("Freezing user space processes ... "); | 158 | printk("Freezing user space processes ... "); |
134 | pm_freezing = true; | 159 | pm_freezing = true; |
160 | oom_kills_saved = oom_kills_count(); | ||
135 | error = try_to_freeze_tasks(true); | 161 | error = try_to_freeze_tasks(true); |
136 | if (!error) { | 162 | if (!error) { |
137 | printk("done."); | ||
138 | __usermodehelper_set_disable_depth(UMH_DISABLED); | 163 | __usermodehelper_set_disable_depth(UMH_DISABLED); |
139 | oom_killer_disable(); | 164 | oom_killer_disable(); |
165 | |||
166 | /* | ||
167 | * There might have been an OOM kill while we were | ||
168 | * freezing tasks and the killed task might be still | ||
169 | * on the way out so we have to double check for race. | ||
170 | */ | ||
171 | if (oom_kills_count() != oom_kills_saved && | ||
172 | !check_frozen_processes()) { | ||
173 | __usermodehelper_set_disable_depth(UMH_ENABLED); | ||
174 | printk("OOM in progress."); | ||
175 | error = -EBUSY; | ||
176 | } else { | ||
177 | printk("done."); | ||
178 | } | ||
140 | } | 179 | } |
141 | printk("\n"); | 180 | printk("\n"); |
142 | BUG_ON(in_atomic()); | 181 | BUG_ON(in_atomic()); |
@@ -191,11 +230,11 @@ void thaw_processes(void) | |||
191 | thaw_workqueues(); | 230 | thaw_workqueues(); |
192 | 231 | ||
193 | read_lock(&tasklist_lock); | 232 | read_lock(&tasklist_lock); |
194 | do_each_thread(g, p) { | 233 | for_each_process_thread(g, p) { |
195 | /* No other threads should have PF_SUSPEND_TASK set */ | 234 | /* No other threads should have PF_SUSPEND_TASK set */ |
196 | WARN_ON((p != curr) && (p->flags & PF_SUSPEND_TASK)); | 235 | WARN_ON((p != curr) && (p->flags & PF_SUSPEND_TASK)); |
197 | __thaw_task(p); | 236 | __thaw_task(p); |
198 | } while_each_thread(g, p); | 237 | } |
199 | read_unlock(&tasklist_lock); | 238 | read_unlock(&tasklist_lock); |
200 | 239 | ||
201 | WARN_ON(!(curr->flags & PF_SUSPEND_TASK)); | 240 | WARN_ON(!(curr->flags & PF_SUSPEND_TASK)); |
@@ -218,10 +257,10 @@ void thaw_kernel_threads(void) | |||
218 | thaw_workqueues(); | 257 | thaw_workqueues(); |
219 | 258 | ||
220 | read_lock(&tasklist_lock); | 259 | read_lock(&tasklist_lock); |
221 | do_each_thread(g, p) { | 260 | for_each_process_thread(g, p) { |
222 | if (p->flags & (PF_KTHREAD | PF_WQ_WORKER)) | 261 | if (p->flags & (PF_KTHREAD | PF_WQ_WORKER)) |
223 | __thaw_task(p); | 262 | __thaw_task(p); |
224 | } while_each_thread(g, p); | 263 | } |
225 | read_unlock(&tasklist_lock); | 264 | read_unlock(&tasklist_lock); |
226 | 265 | ||
227 | schedule(); | 266 | schedule(); |