From: Rafael J. Wysocki <rjw@xxxxxxx> 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@xxxxxxx> --- 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); _______________________________________________ linux-pm mailing list linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/linux-pm