Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

suspend: enable freeze timeout configuration through sys

At present, the value of timeout for freezing is 20s, which is
meaningless in case that one thread is frozen with mutex locked
and another thread is trying to lock the mutex, as this time of
freezing will fail unavoidably.
And if there is no new wakeup event registered, the system will
waste at most 20s for such meaningless trying of freezing.

With this patch, the value of timeout can be configured to smaller
value, so such meaningless trying of freezing will be aborted in
earlier time, and later freezing can be also triggered in earlier
time. And more power will be saved.
In normal case on mobile phone, it costs real little time to freeze
processes. On some platform, it only costs about 20ms to freeze
user space processes and 10ms to freeze kernel freezable threads.

Signed-off-by: Liu Chuansheng <chuansheng.liu@intel.com>
Signed-off-by: Li Fei <fei.li@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Li Fei and committed by
Rafael J. Wysocki
957d1282 89a22dad

+39 -2
+5
Documentation/power/freezing-of-tasks.txt
··· 223 223 only after the entire suspend/hibernation sequence is complete. 224 224 So, to summarize, use [un]lock_system_sleep() instead of directly using 225 225 mutex_[un]lock(&pm_mutex). That would prevent freezing failures. 226 + 227 + V. Miscellaneous 228 + /sys/power/pm_freeze_timeout controls how long it will cost at most to freeze 229 + all user space processes or all freezable kernel threads, in unit of millisecond. 230 + The default value is 20000, with range of unsigned integer.
+5
include/linux/freezer.h
··· 13 13 extern bool pm_nosig_freezing; /* PM nosig freezing in effect */ 14 14 15 15 /* 16 + * Timeout for stopping processes 17 + */ 18 + extern unsigned int freeze_timeout_msecs; 19 + 20 + /* 16 21 * Check if a process has been frozen 17 22 */ 18 23 static inline bool frozen(struct task_struct *p)
+27
kernel/power/main.c
··· 553 553 554 554 #endif /* CONFIG_PM_TRACE */ 555 555 556 + #ifdef CONFIG_FREEZER 557 + static ssize_t pm_freeze_timeout_show(struct kobject *kobj, 558 + struct kobj_attribute *attr, char *buf) 559 + { 560 + return sprintf(buf, "%u\n", freeze_timeout_msecs); 561 + } 562 + 563 + static ssize_t pm_freeze_timeout_store(struct kobject *kobj, 564 + struct kobj_attribute *attr, 565 + const char *buf, size_t n) 566 + { 567 + unsigned long val; 568 + 569 + if (kstrtoul(buf, 10, &val)) 570 + return -EINVAL; 571 + 572 + freeze_timeout_msecs = val; 573 + return n; 574 + } 575 + 576 + power_attr(pm_freeze_timeout); 577 + 578 + #endif /* CONFIG_FREEZER*/ 579 + 556 580 static struct attribute * g[] = { 557 581 &state_attr.attr, 558 582 #ifdef CONFIG_PM_TRACE ··· 599 575 #ifdef CONFIG_PM_SLEEP_DEBUG 600 576 &pm_print_times_attr.attr, 601 577 #endif 578 + #endif 579 + #ifdef CONFIG_FREEZER 580 + &pm_freeze_timeout_attr.attr, 602 581 #endif 603 582 NULL, 604 583 };
+2 -2
kernel/power/process.c
··· 21 21 /* 22 22 * Timeout for stopping processes 23 23 */ 24 - #define TIMEOUT (20 * HZ) 24 + unsigned int __read_mostly freeze_timeout_msecs = 20 * MSEC_PER_SEC; 25 25 26 26 static int try_to_freeze_tasks(bool user_only) 27 27 { ··· 36 36 37 37 do_gettimeofday(&start); 38 38 39 - end_time = jiffies + TIMEOUT; 39 + end_time = jiffies + msecs_to_jiffies(freeze_timeout_msecs); 40 40 41 41 if (!user_only) 42 42 freeze_workqueues_begin();