summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorArve Hjønnevåg <arve@android.com>2010-05-24 20:35:11 +0200
committerRafael J. Wysocki <rjw@sisk.pl>2010-05-24 20:35:11 +0200
commitb36d6886dbebf48626bf27effe36fb4e70601b5d (patch)
tree426ec68295e86482452ada35f5a98da0c4ebf1e2 /kernel
parent4965b20bd331ac061c466472e923b3fd70452928 (diff)
PM: Abort task freezing if there is an active suspend blocker
If a suspend_blocker is active, suspend will fail anyway. Since try_to_freeze_tasks can take up to 20 seconds to complete or fail, aborting as soon as someone blocks suspend (e.g. from an interrupt handler) improves the worst case wakeup latency. On an older kernel where task freezing could fail for processes attached to a debugger, this fixed a problem where the device sometimes hung for 20 seconds before the screen turned on. Signed-off-by: Arve Hjønnevåg <arve@android.com> Acked-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/power/process.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 71ae29052ab6..27d26d3eb748 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -38,6 +38,7 @@ static int try_to_freeze_tasks(bool sig_only)
struct timeval start, end;
u64 elapsed_csecs64;
unsigned int elapsed_csecs;
+ bool wakeup = false;
do_gettimeofday(&start);
@@ -63,6 +64,10 @@ static int try_to_freeze_tasks(bool sig_only)
todo++;
} while_each_thread(g, p);
read_unlock(&tasklist_lock);
+ if (todo && suspend_is_blocked()) {
+ wakeup = true;
+ break;
+ }
if (!todo || time_after(jiffies, end_time))
break;
@@ -85,13 +90,15 @@ static int try_to_freeze_tasks(bool sig_only)
* but it cleans up leftover PF_FREEZE requests.
*/
printk("\n");
- printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds "
+ printk(KERN_ERR "Freezing of tasks %s after %d.%02d seconds "
"(%d tasks refusing to freeze):\n",
+ wakeup ? "aborted" : "failed",
elapsed_csecs / 100, elapsed_csecs % 100, todo);
read_lock(&tasklist_lock);
do_each_thread(g, p) {
task_lock(p);
- if (freezing(p) && !freezer_should_skip(p))
+ if (freezing(p) && !freezer_should_skip(p)
+ && elapsed_csecs > 100)
sched_show_task(p);
cancel_freezing(p);
task_unlock(p);