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.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 98088e0e71e8..06ec8869dbf1 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -30,9 +30,10 @@ static int try_to_freeze_tasks(bool user_only)
30 unsigned int todo; 30 unsigned int todo;
31 bool wq_busy = false; 31 bool wq_busy = false;
32 struct timeval start, end; 32 struct timeval start, end;
33 u64 elapsed_csecs64; 33 u64 elapsed_msecs64;
34 unsigned int elapsed_csecs; 34 unsigned int elapsed_msecs;
35 bool wakeup = false; 35 bool wakeup = false;
36 int sleep_usecs = USEC_PER_MSEC;
36 37
37 do_gettimeofday(&start); 38 do_gettimeofday(&start);
38 39
@@ -68,22 +69,25 @@ static int try_to_freeze_tasks(bool user_only)
68 69
69 /* 70 /*
70 * We need to retry, but first give the freezing tasks some 71 * We need to retry, but first give the freezing tasks some
71 * time to enter the refrigerator. 72 * time to enter the refrigerator. Start with an initial
73 * 1 ms sleep followed by exponential backoff until 8 ms.
72 */ 74 */
73 msleep(10); 75 usleep_range(sleep_usecs / 2, sleep_usecs);
76 if (sleep_usecs < 8 * USEC_PER_MSEC)
77 sleep_usecs *= 2;
74 } 78 }
75 79
76 do_gettimeofday(&end); 80 do_gettimeofday(&end);
77 elapsed_csecs64 = timeval_to_ns(&end) - timeval_to_ns(&start); 81 elapsed_msecs64 = timeval_to_ns(&end) - timeval_to_ns(&start);
78 do_div(elapsed_csecs64, NSEC_PER_SEC / 100); 82 do_div(elapsed_msecs64, NSEC_PER_MSEC);
79 elapsed_csecs = elapsed_csecs64; 83 elapsed_msecs = elapsed_msecs64;
80 84
81 if (todo) { 85 if (todo) {
82 printk("\n"); 86 printk("\n");
83 printk(KERN_ERR "Freezing of tasks %s after %d.%02d seconds " 87 printk(KERN_ERR "Freezing of tasks %s after %d.%03d seconds "
84 "(%d tasks refusing to freeze, wq_busy=%d):\n", 88 "(%d tasks refusing to freeze, wq_busy=%d):\n",
85 wakeup ? "aborted" : "failed", 89 wakeup ? "aborted" : "failed",
86 elapsed_csecs / 100, elapsed_csecs % 100, 90 elapsed_msecs / 1000, elapsed_msecs % 1000,
87 todo - wq_busy, wq_busy); 91 todo - wq_busy, wq_busy);
88 92
89 if (!wakeup) { 93 if (!wakeup) {
@@ -96,8 +100,8 @@ static int try_to_freeze_tasks(bool user_only)
96 read_unlock(&tasklist_lock); 100 read_unlock(&tasklist_lock);
97 } 101 }
98 } else { 102 } else {
99 printk("(elapsed %d.%02d seconds) ", elapsed_csecs / 100, 103 printk("(elapsed %d.%03d seconds) ", elapsed_msecs / 1000,
100 elapsed_csecs % 100); 104 elapsed_msecs % 1000);
101 } 105 }
102 106
103 return todo ? -EBUSY : 0; 107 return todo ? -EBUSY : 0;
@@ -105,6 +109,8 @@ static int try_to_freeze_tasks(bool user_only)
105 109
106/** 110/**
107 * freeze_processes - Signal user space processes to enter the refrigerator. 111 * freeze_processes - Signal user space processes to enter the refrigerator.
112 * The current thread will not be frozen. The same process that calls
113 * freeze_processes must later call thaw_processes.
108 * 114 *
109 * On success, returns 0. On failure, -errno and system is fully thawed. 115 * On success, returns 0. On failure, -errno and system is fully thawed.
110 */ 116 */
@@ -116,6 +122,9 @@ int freeze_processes(void)
116 if (error) 122 if (error)
117 return error; 123 return error;
118 124
125 /* Make sure this task doesn't get frozen */
126 current->flags |= PF_SUSPEND_TASK;
127
119 if (!pm_freezing) 128 if (!pm_freezing)
120 atomic_inc(&system_freezing_cnt); 129 atomic_inc(&system_freezing_cnt);
121 130
@@ -164,6 +173,7 @@ int freeze_kernel_threads(void)
164void thaw_processes(void) 173void thaw_processes(void)
165{ 174{
166 struct task_struct *g, *p; 175 struct task_struct *g, *p;
176 struct task_struct *curr = current;
167 177
168 if (pm_freezing) 178 if (pm_freezing)
169 atomic_dec(&system_freezing_cnt); 179 atomic_dec(&system_freezing_cnt);
@@ -178,10 +188,15 @@ void thaw_processes(void)
178 188
179 read_lock(&tasklist_lock); 189 read_lock(&tasklist_lock);
180 do_each_thread(g, p) { 190 do_each_thread(g, p) {
191 /* No other threads should have PF_SUSPEND_TASK set */
192 WARN_ON((p != curr) && (p->flags & PF_SUSPEND_TASK));
181 __thaw_task(p); 193 __thaw_task(p);
182 } while_each_thread(g, p); 194 } while_each_thread(g, p);
183 read_unlock(&tasklist_lock); 195 read_unlock(&tasklist_lock);
184 196
197 WARN_ON(!(curr->flags & PF_SUSPEND_TASK));
198 curr->flags &= ~PF_SUSPEND_TASK;
199
185 usermodehelper_enable(); 200 usermodehelper_enable();
186 201
187 schedule(); 202 schedule();