[RFC][PATCH -mm 3/3] Freezer: Replace the timeout

Rafael J. Wysocki
2007-07-31T22:29:42Z

From: Rafael J. Wysocki <rjw@sisk.pl>

Instead of using the global timeout, we can use a more fine grained method of
checking if the freezing of tasks should fail. Namely, we can measure the time
in which no tasks have entered the refrigerator by counting the number of calls
to wait_event_timeout() in try_to_freeze_tasks() that have returned 0 (in a
row).

After sending freeze requests to the tasks regarded as freezable
try_to_freeze_tasks() goes to sleep and waits until at least one task enters the
refrigerator.  If the refrigerator is not entered by any tasks before WAIT_TIME
expires, try_to_freeze_tasks() increases the counter of expired timeouts and
sends freeze requests to the remaining tasks. If the number of expired timeouts
becomes greater than MAX_WAITS, the freezing of tasks fails (the counter of
expired timeouts is reset whenever a task enters the refrigerator).

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
kernel/power/process.c | 29 +++++++++++++++++------------
1 file changed, 17 insertions(+), 12 deletions(-)

Index: linux-2.6.23-rc1/kernel/power/process.c
===================================================================
--- linux-2.6.23-rc1.orig/kernel/power/process.c 2007-07-31 23:01:10.000000000 +0200
+++ linux-2.6.23-rc1/kernel/power/process.c 2007-07-31 23:12:34.000000000 +0200
@@ -14,17 +14,21 @@
#include <linux/syscalls.h>
#include <linux/freezer.h>

-/*
- * Timeout for stopping processes
- */
-#define TIMEOUT (20 * HZ)
-
/*
* Time to wait until one or more tasks enter the refrigerator after sending
* freeze requests to them.
*/
#define WAIT_TIME (HZ / 5)

+/*
+ * Each time after sending freeze requests to tasks the freezer will wait until
+ * some of them enter the refrigerater, but no longer than TIMEOUT. If TIMEOUT
+ * has been exceeded, the freezer increases the number of waits by one and
+ * repeats. If the number of waits becomes greater than MAX_WAITS, the
+ * freezing fails.
+ */
+#define MAX_WAITS 5
+
#define FREEZER_KERNEL_THREADS 0
#define FREEZER_USER_SPACE 1

@@ -188,16 +192,15 @@ static void cancel_freezing(struct task_
static int try_to_freeze_tasks(int freeze_user_space)
{
struct task_struct *g, *p;
- unsigned long end_time;
- unsigned int todo;
+ unsigned int todo, waits;
struct timeval start, end;
s64 elapsed_csecs64;
unsigned int elapsed_csecs;

do_gettimeofday(&start);

- end_time = jiffies + TIMEOUT;
refrigerator_called = 0;
+ waits = 0;
do {
todo = 0;
read_lock(&tasklist_lock);
@@ -223,12 +226,14 @@ static int try_to_freeze_tasks(int freez

ret = wait_event_timeout(refrigerator_waitq,
refrigerator_called, WAIT_TIME);
- if (ret)
+ if (ret) {
refrigerator_called = 0;
+ waits = 0;
+ } else {
+ if (++waits > MAX_WAITS)
+ break;
+ }
}
-
- if (time_after(jiffies, end_time))
- break;
} while (todo);

do_gettimeofday(&end);