diff options
author | Tejun Heo <tj@kernel.org> | 2010-06-29 04:07:12 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2010-06-29 04:07:12 -0400 |
commit | a0a1a5fd4fb15ec61117c759fe9f5c16c53d9e9c (patch) | |
tree | 6df8eddcaeff6cde892c8cae6bdfa7653805e144 /kernel/power | |
parent | 1e19ffc63dbbaea7a7d1c63d99c38d3e5a4c7edf (diff) |
workqueue: reimplement workqueue freeze using max_active
Currently, workqueue freezing is implemented by marking the worker
freezeable and calling try_to_freeze() from dispatch loop.
Reimplement it using cwq->limit so that the workqueue is frozen
instead of the worker.
* workqueue_struct->saved_max_active is added which stores the
specified max_active on initialization.
* On freeze, all cwq->max_active's are quenched to zero. Freezing is
complete when nr_active on all cwqs reach zero.
* On thaw, all cwq->max_active's are restored to wq->saved_max_active
and the worklist is repopulated.
This new implementation allows having single shared pool of workers
per cpu.
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/power')
-rw-r--r-- | kernel/power/process.c | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/kernel/power/process.c b/kernel/power/process.c index 71ae29052ab6..028a99598f49 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/syscalls.h> | 15 | #include <linux/syscalls.h> |
16 | #include <linux/freezer.h> | 16 | #include <linux/freezer.h> |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/workqueue.h> | ||
18 | 19 | ||
19 | /* | 20 | /* |
20 | * Timeout for stopping processes | 21 | * Timeout for stopping processes |
@@ -35,6 +36,7 @@ static int try_to_freeze_tasks(bool sig_only) | |||
35 | struct task_struct *g, *p; | 36 | struct task_struct *g, *p; |
36 | unsigned long end_time; | 37 | unsigned long end_time; |
37 | unsigned int todo; | 38 | unsigned int todo; |
39 | bool wq_busy = false; | ||
38 | struct timeval start, end; | 40 | struct timeval start, end; |
39 | u64 elapsed_csecs64; | 41 | u64 elapsed_csecs64; |
40 | unsigned int elapsed_csecs; | 42 | unsigned int elapsed_csecs; |
@@ -42,6 +44,10 @@ static int try_to_freeze_tasks(bool sig_only) | |||
42 | do_gettimeofday(&start); | 44 | do_gettimeofday(&start); |
43 | 45 | ||
44 | end_time = jiffies + TIMEOUT; | 46 | end_time = jiffies + TIMEOUT; |
47 | |||
48 | if (!sig_only) | ||
49 | freeze_workqueues_begin(); | ||
50 | |||
45 | while (true) { | 51 | while (true) { |
46 | todo = 0; | 52 | todo = 0; |
47 | read_lock(&tasklist_lock); | 53 | read_lock(&tasklist_lock); |
@@ -63,6 +69,12 @@ static int try_to_freeze_tasks(bool sig_only) | |||
63 | todo++; | 69 | todo++; |
64 | } while_each_thread(g, p); | 70 | } while_each_thread(g, p); |
65 | read_unlock(&tasklist_lock); | 71 | read_unlock(&tasklist_lock); |
72 | |||
73 | if (!sig_only) { | ||
74 | wq_busy = freeze_workqueues_busy(); | ||
75 | todo += wq_busy; | ||
76 | } | ||
77 | |||
66 | if (!todo || time_after(jiffies, end_time)) | 78 | if (!todo || time_after(jiffies, end_time)) |
67 | break; | 79 | break; |
68 | 80 | ||
@@ -86,8 +98,12 @@ static int try_to_freeze_tasks(bool sig_only) | |||
86 | */ | 98 | */ |
87 | printk("\n"); | 99 | printk("\n"); |
88 | printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds " | 100 | printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds " |
89 | "(%d tasks refusing to freeze):\n", | 101 | "(%d tasks refusing to freeze, wq_busy=%d):\n", |
90 | elapsed_csecs / 100, elapsed_csecs % 100, todo); | 102 | elapsed_csecs / 100, elapsed_csecs % 100, |
103 | todo - wq_busy, wq_busy); | ||
104 | |||
105 | thaw_workqueues(); | ||
106 | |||
91 | read_lock(&tasklist_lock); | 107 | read_lock(&tasklist_lock); |
92 | do_each_thread(g, p) { | 108 | do_each_thread(g, p) { |
93 | task_lock(p); | 109 | task_lock(p); |
@@ -157,6 +173,7 @@ void thaw_processes(void) | |||
157 | oom_killer_enable(); | 173 | oom_killer_enable(); |
158 | 174 | ||
159 | printk("Restarting tasks ... "); | 175 | printk("Restarting tasks ... "); |
176 | thaw_workqueues(); | ||
160 | thaw_tasks(true); | 177 | thaw_tasks(true); |
161 | thaw_tasks(false); | 178 | thaw_tasks(false); |
162 | schedule(); | 179 | schedule(); |