suspend: enable freeze timeout configuration through sys
authorLi Fei <fei.li@intel.com>
Fri, 1 Feb 2013 08:56:03 +0000 (08:56 +0000)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Sat, 9 Feb 2013 21:32:48 +0000 (22:32 +0100)
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>
Documentation/power/freezing-of-tasks.txt
include/linux/freezer.h
kernel/power/main.c
kernel/power/process.c

index 6ec291ea1c78c64e4e1ec35ad614336859ab4c31..85894d83b3525f2ff0bc6033b80d50ef220d906b 100644 (file)
@@ -223,3 +223,8 @@ since they ask the freezer to skip freezing this task, since it is anyway
 only after the entire suspend/hibernation sequence is complete.
 So, to summarize, use [un]lock_system_sleep() instead of directly using
 mutex_[un]lock(&pm_mutex). That would prevent freezing failures.
+
+V. Miscellaneous
+/sys/power/pm_freeze_timeout controls how long it will cost at most to freeze
+all user space processes or all freezable kernel threads, in unit of millisecond.
+The default value is 20000, with range of unsigned integer.
index e4238ceaa4d6a039d7acf55ae6ad69b6871ac4bd..e70df40d84f6fe83c72f732aa44b454148661b6e 100644 (file)
@@ -12,6 +12,11 @@ extern atomic_t system_freezing_cnt; /* nr of freezing conds in effect */
 extern bool pm_freezing;               /* PM freezing in effect */
 extern bool pm_nosig_freezing;         /* PM nosig freezing in effect */
 
+/*
+ * Timeout for stopping processes
+ */
+extern unsigned int freeze_timeout_msecs;
+
 /*
  * Check if a process has been frozen
  */
index b1c26a92ca9f75dc27151c13fb6865455e9942a6..d77663bfedeb071370f584f2bf1e42cd8332e5a4 100644 (file)
@@ -553,6 +553,30 @@ power_attr(pm_trace_dev_match);
 
 #endif /* CONFIG_PM_TRACE */
 
+#ifdef CONFIG_FREEZER
+static ssize_t pm_freeze_timeout_show(struct kobject *kobj,
+                                     struct kobj_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%u\n", freeze_timeout_msecs);
+}
+
+static ssize_t pm_freeze_timeout_store(struct kobject *kobj,
+                                      struct kobj_attribute *attr,
+                                      const char *buf, size_t n)
+{
+       unsigned long val;
+
+       if (kstrtoul(buf, 10, &val))
+               return -EINVAL;
+
+       freeze_timeout_msecs = val;
+       return n;
+}
+
+power_attr(pm_freeze_timeout);
+
+#endif /* CONFIG_FREEZER*/
+
 static struct attribute * g[] = {
        &state_attr.attr,
 #ifdef CONFIG_PM_TRACE
@@ -575,6 +599,9 @@ static struct attribute * g[] = {
 #ifdef CONFIG_PM_SLEEP_DEBUG
        &pm_print_times_attr.attr,
 #endif
+#endif
+#ifdef CONFIG_FREEZER
+       &pm_freeze_timeout_attr.attr,
 #endif
        NULL,
 };
index d5a258b60c6fd71aed065a0dd2ea5acadddc991f..98088e0e71e83a3b9cd157c5415f9e79083592c0 100644 (file)
@@ -21,7 +21,7 @@
 /* 
  * Timeout for stopping processes
  */
-#define TIMEOUT        (20 * HZ)
+unsigned int __read_mostly freeze_timeout_msecs = 20 * MSEC_PER_SEC;
 
 static int try_to_freeze_tasks(bool user_only)
 {
@@ -36,7 +36,7 @@ static int try_to_freeze_tasks(bool user_only)
 
        do_gettimeofday(&start);
 
-       end_time = jiffies + TIMEOUT;
+       end_time = jiffies + msecs_to_jiffies(freeze_timeout_msecs);
 
        if (!user_only)
                freeze_workqueues_begin();