aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power/process.c')
-rw-r--r--kernel/power/process.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 028a99598f49..0cf3a27a6c9d 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -22,7 +22,7 @@
22 */ 22 */
23#define TIMEOUT (20 * HZ) 23#define TIMEOUT (20 * HZ)
24 24
25static inline int freezeable(struct task_struct * p) 25static inline int freezable(struct task_struct * p)
26{ 26{
27 if ((p == current) || 27 if ((p == current) ||
28 (p->flags & PF_NOFREEZE) || 28 (p->flags & PF_NOFREEZE) ||
@@ -40,6 +40,7 @@ static int try_to_freeze_tasks(bool sig_only)
40 struct timeval start, end; 40 struct timeval start, end;
41 u64 elapsed_csecs64; 41 u64 elapsed_csecs64;
42 unsigned int elapsed_csecs; 42 unsigned int elapsed_csecs;
43 bool wakeup = false;
43 44
44 do_gettimeofday(&start); 45 do_gettimeofday(&start);
45 46
@@ -52,7 +53,7 @@ static int try_to_freeze_tasks(bool sig_only)
52 todo = 0; 53 todo = 0;
53 read_lock(&tasklist_lock); 54 read_lock(&tasklist_lock);
54 do_each_thread(g, p) { 55 do_each_thread(g, p) {
55 if (frozen(p) || !freezeable(p)) 56 if (frozen(p) || !freezable(p))
56 continue; 57 continue;
57 58
58 if (!freeze_task(p, sig_only)) 59 if (!freeze_task(p, sig_only))
@@ -63,6 +64,12 @@ static int try_to_freeze_tasks(bool sig_only)
63 * perturb a task in TASK_STOPPED or TASK_TRACED. 64 * perturb a task in TASK_STOPPED or TASK_TRACED.
64 * It is "frozen enough". If the task does wake 65 * It is "frozen enough". If the task does wake
65 * up, it will immediately call try_to_freeze. 66 * up, it will immediately call try_to_freeze.
67 *
68 * Because freeze_task() goes through p's
69 * scheduler lock after setting TIF_FREEZE, it's
70 * guaranteed that either we see TASK_RUNNING or
71 * try_to_stop() after schedule() in ptrace/signal
72 * stop sees TIF_FREEZE.
66 */ 73 */
67 if (!task_is_stopped_or_traced(p) && 74 if (!task_is_stopped_or_traced(p) &&
68 !freezer_should_skip(p)) 75 !freezer_should_skip(p))
@@ -78,6 +85,11 @@ static int try_to_freeze_tasks(bool sig_only)
78 if (!todo || time_after(jiffies, end_time)) 85 if (!todo || time_after(jiffies, end_time))
79 break; 86 break;
80 87
88 if (pm_wakeup_pending()) {
89 wakeup = true;
90 break;
91 }
92
81 /* 93 /*
82 * We need to retry, but first give the freezing tasks some 94 * We need to retry, but first give the freezing tasks some
83 * time to enter the regrigerator. 95 * time to enter the regrigerator.
@@ -97,8 +109,9 @@ static int try_to_freeze_tasks(bool sig_only)
97 * but it cleans up leftover PF_FREEZE requests. 109 * but it cleans up leftover PF_FREEZE requests.
98 */ 110 */
99 printk("\n"); 111 printk("\n");
100 printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds " 112 printk(KERN_ERR "Freezing of tasks %s after %d.%02d seconds "
101 "(%d tasks refusing to freeze, wq_busy=%d):\n", 113 "(%d tasks refusing to freeze, wq_busy=%d):\n",
114 wakeup ? "aborted" : "failed",
102 elapsed_csecs / 100, elapsed_csecs % 100, 115 elapsed_csecs / 100, elapsed_csecs % 100,
103 todo - wq_busy, wq_busy); 116 todo - wq_busy, wq_busy);
104 117
@@ -107,7 +120,7 @@ static int try_to_freeze_tasks(bool sig_only)
107 read_lock(&tasklist_lock); 120 read_lock(&tasklist_lock);
108 do_each_thread(g, p) { 121 do_each_thread(g, p) {
109 task_lock(p); 122 task_lock(p);
110 if (freezing(p) && !freezer_should_skip(p)) 123 if (!wakeup && freezing(p) && !freezer_should_skip(p))
111 sched_show_task(p); 124 sched_show_task(p);
112 cancel_freezing(p); 125 cancel_freezing(p);
113 task_unlock(p); 126 task_unlock(p);
@@ -154,7 +167,7 @@ static void thaw_tasks(bool nosig_only)
154 167
155 read_lock(&tasklist_lock); 168 read_lock(&tasklist_lock);
156 do_each_thread(g, p) { 169 do_each_thread(g, p) {
157 if (!freezeable(p)) 170 if (!freezable(p))
158 continue; 171 continue;
159 172
160 if (nosig_only && should_send_signal(p)) 173 if (nosig_only && should_send_signal(p))