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>

+11 -2
+2
include/linux/suspend.h
··· 308 } 309 310 #define pm_notifier(fn, pri) do { (void)(fn); } while (0) 311 #endif /* !CONFIG_PM_SLEEP */ 312 313 extern struct mutex pm_mutex;
··· 308 } 309 310 #define pm_notifier(fn, pri) do { (void)(fn); } while (0) 311 + 312 + static inline bool pm_check_wakeup_events(void) { return true; } 313 #endif /* !CONFIG_PM_SLEEP */ 314 315 extern struct mutex pm_mutex;
+9 -2
kernel/power/process.c
··· 40 struct timeval start, end; 41 u64 elapsed_csecs64; 42 unsigned int elapsed_csecs; 43 44 do_gettimeofday(&start); 45 ··· 79 if (!todo || time_after(jiffies, end_time)) 80 break; 81 82 /* 83 * We need to retry, but first give the freezing tasks some 84 * time to enter the regrigerator. ··· 103 * but it cleans up leftover PF_FREEZE requests. 104 */ 105 printk("\n"); 106 - printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds " 107 "(%d tasks refusing to freeze, wq_busy=%d):\n", 108 elapsed_csecs / 100, elapsed_csecs % 100, 109 todo - wq_busy, wq_busy); 110 ··· 114 read_lock(&tasklist_lock); 115 do_each_thread(g, p) { 116 task_lock(p); 117 - if (freezing(p) && !freezer_should_skip(p)) 118 sched_show_task(p); 119 cancel_freezing(p); 120 task_unlock(p);
··· 40 struct timeval start, end; 41 u64 elapsed_csecs64; 42 unsigned int elapsed_csecs; 43 + bool wakeup = false; 44 45 do_gettimeofday(&start); 46 ··· 78 if (!todo || time_after(jiffies, end_time)) 79 break; 80 81 + if (!pm_check_wakeup_events()) { 82 + wakeup = true; 83 + break; 84 + } 85 + 86 /* 87 * We need to retry, but first give the freezing tasks some 88 * time to enter the regrigerator. ··· 97 * but it cleans up leftover PF_FREEZE requests. 98 */ 99 printk("\n"); 100 + printk(KERN_ERR "Freezing of tasks %s after %d.%02d seconds " 101 "(%d tasks refusing to freeze, wq_busy=%d):\n", 102 + wakeup ? "aborted" : "failed", 103 elapsed_csecs / 100, elapsed_csecs % 100, 104 todo - wq_busy, wq_busy); 105 ··· 107 read_lock(&tasklist_lock); 108 do_each_thread(g, p) { 109 task_lock(p); 110 + if (!wakeup && freezing(p) && !freezer_should_skip(p)) 111 sched_show_task(p); 112 cancel_freezing(p); 113 task_unlock(p);