From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: linux-pm@lists.linux-foundation.org
Cc: Matthew Garrett <mjg59@srcf.ucam.org>,
Oleg Nesterov <oleg@tv-sign.ru>, Pavel Machek <pavel@ucw.cz>,
Miklos Szeredi <miklos@szeredi.hu>
Subject: [RFC][PATCH -mm 7/7] Freezer: Use freezing timeout more efficiently (updated)
Date: Thu, 12 Jul 2007 12:38:05 +0200 [thread overview]
Message-ID: <200707121238.06619.rjw@sisk.pl> (raw)
In-Reply-To: <200707120017.23622.rjw@sisk.pl>
[The previous version didn't pass some tests.]
---
From: Rafael J. Wysocki <rjw@sisk.pl>
There is the problem with try_to_freeze_tasks() that it always loops until the
timeout expires, even if it is certain to fail much earlier. Namely, if there
are uninterruptible tasks waiting for some frozen tasks to let them continue,
try_to_freeze_tasks() will certainly fail and it shouldn't waste time in that
cases.
To detect such situations, we can check if the number of tasks that haven't
frozen yet changes between subsequent iterations of the main loop in
try_to_freeze_tasks(). If this number hasn't been changing for sufficiently
long time (say, 250 ms), then most probably some uninterruptible tasks are
blocked by some frozen tasks and we should break out of this stalemate. Thus,
it seems reasonable to thaw the tasks that have already been frozen without
clearing the freeze requests of the tasks that are refusing to freeze. This
way, if these tasks are really blocked by the frozen ones, they will get extra
chance to freeze themselves after we have thawed the other tasks and before we
request those tasks to freeze again. Next, the freezing loop can be repeated
and so on, until all tasks are frozen or the timeout expires.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
kernel/power/process.c | 86 +++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 72 insertions(+), 14 deletions(-)
Index: linux-2.6.22-rc6-mm1/kernel/power/process.c
===================================================================
--- linux-2.6.22-rc6-mm1.orig/kernel/power/process.c 2007-07-12 11:46:10.000000000 +0200
+++ linux-2.6.22-rc6-mm1/kernel/power/process.c 2007-07-12 12:11:41.000000000 +0200
@@ -14,10 +14,11 @@
#include <linux/syscalls.h>
#include <linux/freezer.h>
-/*
- * Timeout for stopping processes
- */
-#define TIMEOUT (20 * HZ)
+/* Timeout for the freezing of tasks */
+#define TIMEOUT (10 * HZ)
+
+/* Timeout for breaking the freezing loop if stalemate state is detected */
+#define BREAK_TIMEOUT (HZ / 4)
#define FREEZER_KERNEL_THREADS 0
#define FREEZER_USER_SPACE 1
@@ -163,14 +164,31 @@ static void cancel_freezing(struct task_
}
}
+/**
+ * try_to_freeze_tasks - send freeze requests to all tasks and wait for
+ * for them to enter the refrigerator
+ * @freeze_user_space - if set, only tasks that have mm of their own are
+ * requested to freeze
+ *
+ * If this function fails, thaw_tasks() must be called to do the cleanup.
+ */
+
static int try_to_freeze_tasks(int freeze_user_space)
{
struct task_struct *g, *p;
- unsigned long end_time;
- unsigned int todo;
+ unsigned long end_time, break_time;
+ unsigned int todo, prev_todo;
+ unsigned int i = 0;
+ char *tick = "-\\|/";
+
+ printk(" ");
end_time = jiffies + TIMEOUT;
+ Repeat:
+ todo = 0;
+ break_time = 0;
do {
+ prev_todo = todo;
todo = 0;
read_lock(&tasklist_lock);
do_each_thread(g, p) {
@@ -189,23 +207,63 @@ static int try_to_freeze_tasks(int freez
todo++;
} while_each_thread(g, p);
read_unlock(&tasklist_lock);
+
yield(); /* Yield is okay here */
+
if (time_after(jiffies, end_time))
break;
+
+ if (freeze_user_space) {
+ /*
+ * Check if we are making any progress. If we aren't,
+ * it's better to break out of this.
+ */
+ if (todo == prev_todo) {
+ if (!break_time)
+ break_time = jiffies + BREAK_TIMEOUT;
+ else if (time_after(jiffies, break_time))
+ break;
+ } else {
+ break_time = 0;
+ }
+ }
} while (todo);
+ if (todo && freeze_user_space && !time_after(jiffies, end_time)) {
+ /*
+ * Some tasks have not been able to freeze. They might be stuck
+ * in TASK_UNINTERRUPTIBLE waiting for the frozen tasks. Try to
+ * thaw the tasks that have frozen without clearing the freeze
+ * requests of the remaining tasks and repeat.
+ */
+ read_lock(&tasklist_lock);
+ do_each_thread(g, p) {
+ if (frozen(p)) {
+ p->flags &= ~PF_FROZEN;
+ wake_up_process(p);
+ }
+ } while_each_thread(g, p);
+ read_unlock(&tasklist_lock);
+
+ yield();
+
+ printk("\b%c", tick[i++%4]);
+
+ goto Repeat;
+ }
+
+ printk("\b");
+
if (todo) {
- /* This does not unfreeze processes that are already frozen
- * (we have slightly ugly calling convention in that respect,
- * and caller must call thaw_processes() if something fails),
- * but it cleans up leftover PF_FREEZE requests.
+ /*
+ * The freezing of tasks has failed. List the tasks that have
+ * refused to freeze. This also clears all pending freeze
+ * requests.
*/
printk("\n");
- printk(KERN_ERR "Freezing of %s timed out after %d seconds "
- "(%d tasks refusing to freeze):\n",
- freeze_user_space ? "user space " : "tasks ",
- TIMEOUT / HZ, todo);
+ printk(KERN_ERR "Freezing of tasks has failed.\n");
show_state();
+ printk(KERN_ERR "Tasks that have not been frozen:\n");
read_lock(&tasklist_lock);
do_each_thread(g, p) {
task_lock(p);
next prev parent reply other threads:[~2007-07-12 10:38 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-07-11 22:06 [RFC][PATCH -mm 0/7] Freezer update (updated) Rafael J. Wysocki
2007-07-11 22:08 ` [RFC][PATCH -mm 1/7] Freezer: Document relationship with memory shrinking Rafael J. Wysocki
2007-07-11 22:10 ` [RFC][PATCH -mm 2/7] Freezer: Do not sync filesystems from freeze_processes Rafael J. Wysocki
2007-07-11 22:42 ` Pavel Machek
2007-07-11 22:12 ` [RFC][PATCH -mm 3/7] Freezer: Prevent new tasks from inheriting TIF_FREEZE set Rafael J. Wysocki
2007-07-11 22:25 ` Nigel Cunningham
2007-07-11 22:13 ` [RFC][PATCH -mm 4/7] Freezer: Introduce freezer-firendly waiting macros Rafael J. Wysocki
2007-07-11 22:56 ` Pavel Machek
2007-07-12 10:33 ` Rafael J. Wysocki
2007-07-11 23:02 ` Oleg Nesterov
2007-07-12 10:30 ` [RFC][PATCH -mm 4/7] Freezer: Introduce freezer-firendly waiting macros (updated) Rafael J. Wysocki
2007-07-12 12:23 ` [RFC][PATCH -mm 4/7] Freezer: Introduce freezer-firendly waiting macros (updated 2x) Rafael J. Wysocki
2007-07-11 22:14 ` [RFC][PATCH -mm 5/7] Freezer: Do not send signals to kernel threads (updated) Rafael J. Wysocki
2007-07-11 22:16 ` [RFC][PATCH -mm 6/7] Freezer: Be more verbose Rafael J. Wysocki
2007-07-11 22:58 ` Pavel Machek
2007-07-12 10:39 ` [RFC][PATCH -mm 6/7] Freezer: Be more verbose (updated) Rafael J. Wysocki
2007-07-11 22:17 ` [RFC][PATCH -mm 7/7] Freezer: Use freezing timeout more efficiently Rafael J. Wysocki
2007-07-12 10:38 ` Rafael J. Wysocki [this message]
2007-07-13 23:43 ` Pavel Machek
2007-07-14 9:20 ` Rafael J. Wysocki
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200707121238.06619.rjw@sisk.pl \
--to=rjw@sisk.pl \
--cc=linux-pm@lists.linux-foundation.org \
--cc=miklos@szeredi.hu \
--cc=mjg59@srcf.ucam.org \
--cc=oleg@tv-sign.ru \
--cc=pavel@ucw.cz \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox