diff options
Diffstat (limited to 'kernel/power/process.c')
| -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(); |
