Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dbeeec5f authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

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: default avatarRafael J. Wysocki <rjw@sisk.pl>
Acked-by: default avatarPavel Machek <pavel@ucw.cz>
parent 5fc62aad
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -308,6 +308,8 @@ static inline int unregister_pm_notifier(struct notifier_block *nb)
}

#define pm_notifier(fn, pri)	do { (void)(fn); } while (0)

static inline bool pm_check_wakeup_events(void) { return true; }
#endif /* !CONFIG_PM_SLEEP */

extern struct mutex pm_mutex;
+9 −2
Original line number Diff line number Diff line
@@ -40,6 +40,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);

@@ -78,6 +79,11 @@ static int try_to_freeze_tasks(bool sig_only)
		if (!todo || time_after(jiffies, end_time))
			break;

		if (!pm_check_wakeup_events()) {
			wakeup = true;
			break;
		}

		/*
		 * We need to retry, but first give the freezing tasks some
		 * 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.
		 */
		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",
		       wakeup ? "aborted" : "failed",
		       elapsed_csecs / 100, elapsed_csecs % 100,
		       todo - wq_busy, wq_busy);

@@ -107,7 +114,7 @@ static int try_to_freeze_tasks(bool sig_only)
		read_lock(&tasklist_lock);
		do_each_thread(g, p) {
			task_lock(p);
			if (freezing(p) && !freezer_should_skip(p))
			if (!wakeup && freezing(p) && !freezer_should_skip(p))
				sched_show_task(p);
			cancel_freezing(p);
			task_unlock(p);