aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power/process.c')
-rw-r--r--kernel/power/process.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 7b323221b9ee..5cc588c1abab 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -108,6 +108,28 @@ static int try_to_freeze_tasks(bool user_only)
108 return todo ? -EBUSY : 0; 108 return todo ? -EBUSY : 0;
109} 109}
110 110
111/*
112 * Returns true if all freezable tasks (except for current) are frozen already
113 */
114static bool check_frozen_processes(void)
115{
116 struct task_struct *g, *p;
117 bool ret = true;
118
119 read_lock(&tasklist_lock);
120 for_each_process_thread(g, p) {
121 if (p != current && !freezer_should_skip(p) &&
122 !frozen(p)) {
123 ret = false;
124 goto done;
125 }
126 }
127done:
128 read_unlock(&tasklist_lock);
129
130 return ret;
131}
132
111/** 133/**
112 * freeze_processes - Signal user space processes to enter the refrigerator. 134 * freeze_processes - Signal user space processes to enter the refrigerator.
113 * The current thread will not be frozen. The same process that calls 135 * The current thread will not be frozen. The same process that calls
@@ -118,6 +140,7 @@ static int try_to_freeze_tasks(bool user_only)
118int freeze_processes(void) 140int freeze_processes(void)
119{ 141{
120 int error; 142 int error;
143 int oom_kills_saved;
121 144
122 error = __usermodehelper_disable(UMH_FREEZING); 145 error = __usermodehelper_disable(UMH_FREEZING);
123 if (error) 146 if (error)
@@ -132,12 +155,27 @@ int freeze_processes(void)
132 pm_wakeup_clear(); 155 pm_wakeup_clear();
133 printk("Freezing user space processes ... "); 156 printk("Freezing user space processes ... ");
134 pm_freezing = true; 157 pm_freezing = true;
158 oom_kills_saved = oom_kills_count();
135 error = try_to_freeze_tasks(true); 159 error = try_to_freeze_tasks(true);
136 if (!error) { 160 if (!error) {
137 printk("done.");
138 __usermodehelper_set_disable_depth(UMH_DISABLED); 161 __usermodehelper_set_disable_depth(UMH_DISABLED);
139 oom_killer_disable(); 162 oom_killer_disable();
163
164 /*
165 * There might have been an OOM kill while we were
166 * freezing tasks and the killed task might be still
167 * on the way out so we have to double check for race.
168 */
169 if (oom_kills_count() != oom_kills_saved &&
170 !check_frozen_processes()) {
171 __usermodehelper_set_disable_depth(UMH_ENABLED);
172 printk("OOM in progress.");
173 error = -EBUSY;
174 goto done;
175 }
176 printk("done.");
140 } 177 }
178done:
141 printk("\n"); 179 printk("\n");
142 BUG_ON(in_atomic()); 180 BUG_ON(in_atomic());
143 181