PM: Allow wakeup events to abort freezing of tasks

If there is a wakeup event during the freezing of tasks, suspend or
hibernation will fail anyway.  Since try_to_freeze_tasks() can take
up to 20 seconds to complete or fail, aborting it as soon as a wakeup
event is detected improves the worst case wakeup latency.

Based on a patch from Arve Hjønnevåg.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
This commit is contained in:
Rafael J. Wysocki 2010-10-04 22:07:32 +02:00
parent 5fc62aad4e
commit dbeeec5fe8
2 changed files with 11 additions and 2 deletions

View File

@ -308,6 +308,8 @@ static inline int unregister_pm_notifier(struct notifier_block *nb)
} }
#define pm_notifier(fn, pri) do { (void)(fn); } while (0) #define pm_notifier(fn, pri) do { (void)(fn); } while (0)
static inline bool pm_check_wakeup_events(void) { return true; }
#endif /* !CONFIG_PM_SLEEP */ #endif /* !CONFIG_PM_SLEEP */
extern struct mutex pm_mutex; extern struct mutex pm_mutex;

View File

@ -40,6 +40,7 @@ static int try_to_freeze_tasks(bool sig_only)
struct timeval start, end; struct timeval start, end;
u64 elapsed_csecs64; u64 elapsed_csecs64;
unsigned int elapsed_csecs; unsigned int elapsed_csecs;
bool wakeup = false;
do_gettimeofday(&start); do_gettimeofday(&start);
@ -78,6 +79,11 @@ static int try_to_freeze_tasks(bool sig_only)
if (!todo || time_after(jiffies, end_time)) if (!todo || time_after(jiffies, end_time))
break; break;
if (!pm_check_wakeup_events()) {
wakeup = true;
break;
}
/* /*
* We need to retry, but first give the freezing tasks some * We need to retry, but first give the freezing tasks some
* time to enter the regrigerator. * time to enter the regrigerator.
@ -97,8 +103,9 @@ static int try_to_freeze_tasks(bool sig_only)
* but it cleans up leftover PF_FREEZE requests. * but it cleans up leftover PF_FREEZE requests.
*/ */
printk("\n"); 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, wq_busy=%d):\n", "(%d tasks refusing to freeze, wq_busy=%d):\n",
wakeup ? "aborted" : "failed",
elapsed_csecs / 100, elapsed_csecs % 100, elapsed_csecs / 100, elapsed_csecs % 100,
todo - wq_busy, wq_busy); todo - wq_busy, wq_busy);
@ -107,7 +114,7 @@ static int try_to_freeze_tasks(bool sig_only)
read_lock(&tasklist_lock); read_lock(&tasklist_lock);
do_each_thread(g, p) { do_each_thread(g, p) {
task_lock(p); task_lock(p);
if (freezing(p) && !freezer_should_skip(p)) if (!wakeup && freezing(p) && !freezer_should_skip(p))
sched_show_task(p); sched_show_task(p);
cancel_freezing(p); cancel_freezing(p);
task_unlock(p); task_unlock(p);