aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power/process.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2006-12-06 23:34:40 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-07 11:39:28 -0500
commit11b2ce2ba90f801e2a5ebba4e6b7da72d87f2b13 (patch)
treee7477edb04a15a3128523877558e1eb8694adbc9 /kernel/power/process.c
parenta9b6f562f14dc28fb4b2415f0f275cede0abe9b5 (diff)
[PATCH] swsusp: Untangle freeze_processes
Move the loop from freeze_processes() to a separate function and call it independently for user space processes and kernel threads so that the order of freezing tasks is clearly visible. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Cc: Pavel Machek <pavel@ucw.cz> Cc: Nigel Cunningham <nigel@suspend2.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/power/process.c')
-rw-r--r--kernel/power/process.c84
1 files changed, 54 insertions, 30 deletions
diff --git a/kernel/power/process.c b/kernel/power/process.c
index fd0ebb942f50..99eeb119b06d 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -86,24 +86,23 @@ static inline int is_user_space(struct task_struct *p)
86 return p->mm && !(p->flags & PF_BORROWED_MM); 86 return p->mm && !(p->flags & PF_BORROWED_MM);
87} 87}
88 88
89/* 0 = success, else # of processes that we failed to stop */ 89static unsigned int try_to_freeze_tasks(int freeze_user_space)
90int freeze_processes(void)
91{ 90{
92 int todo, nr_user, user_frozen;
93 unsigned long start_time;
94 struct task_struct *g, *p; 91 struct task_struct *g, *p;
92 unsigned long end_time;
93 unsigned int todo;
95 94
96 printk("Stopping tasks... "); 95 end_time = jiffies + TIMEOUT;
97 start_time = jiffies;
98 user_frozen = 0;
99 do { 96 do {
100 nr_user = todo = 0; 97 todo = 0;
101 read_lock(&tasklist_lock); 98 read_lock(&tasklist_lock);
102 do_each_thread(g, p) { 99 do_each_thread(g, p) {
103 if (!freezeable(p)) 100 if (!freezeable(p))
104 continue; 101 continue;
102
105 if (frozen(p)) 103 if (frozen(p))
106 continue; 104 continue;
105
107 if (p->state == TASK_TRACED && 106 if (p->state == TASK_TRACED &&
108 (frozen(p->parent) || 107 (frozen(p->parent) ||
109 p->parent->state == TASK_STOPPED)) { 108 p->parent->state == TASK_STOPPED)) {
@@ -111,51 +110,76 @@ int freeze_processes(void)
111 continue; 110 continue;
112 } 111 }
113 if (is_user_space(p)) { 112 if (is_user_space(p)) {
113 if (!freeze_user_space)
114 continue;
115
114 /* Freeze the task unless there is a vfork 116 /* Freeze the task unless there is a vfork
115 * completion pending 117 * completion pending
116 */ 118 */
117 if (!p->vfork_done) 119 if (!p->vfork_done)
118 freeze_process(p); 120 freeze_process(p);
119 nr_user++;
120 } else { 121 } else {
121 /* Freeze only if the user space is frozen */ 122 if (freeze_user_space)
122 if (user_frozen) 123 continue;
123 freeze_process(p); 124
124 todo++; 125 freeze_process(p);
125 } 126 }
127 todo++;
126 } while_each_thread(g, p); 128 } while_each_thread(g, p);
127 read_unlock(&tasklist_lock); 129 read_unlock(&tasklist_lock);
128 todo += nr_user;
129 if (!user_frozen && !nr_user) {
130 sys_sync();
131 start_time = jiffies;
132 }
133 user_frozen = !nr_user;
134 yield(); /* Yield is okay here */ 130 yield(); /* Yield is okay here */
135 if (todo && time_after(jiffies, start_time + TIMEOUT)) 131 if (todo && time_after(jiffies, end_time))
136 break; 132 break;
137 } while(todo); 133 } while (todo);
138 134
139 /* This does not unfreeze processes that are already frozen
140 * (we have slightly ugly calling convention in that respect,
141 * and caller must call thaw_processes() if something fails),
142 * but it cleans up leftover PF_FREEZE requests.
143 */
144 if (todo) { 135 if (todo) {
136 /* This does not unfreeze processes that are already frozen
137 * (we have slightly ugly calling convention in that respect,
138 * and caller must call thaw_processes() if something fails),
139 * but it cleans up leftover PF_FREEZE requests.
140 */
145 printk("\n"); 141 printk("\n");
146 printk(KERN_ERR "Stopping tasks timed out " 142 printk(KERN_ERR "Stopping %s timed out after %d seconds "
147 "after %d seconds (%d tasks remaining):\n", 143 "(%d tasks refusing to freeze):\n",
148 TIMEOUT / HZ, todo); 144 freeze_user_space ? "user space processes" :
145 "kernel threads",
146 TIMEOUT / HZ, todo);
149 read_lock(&tasklist_lock); 147 read_lock(&tasklist_lock);
150 do_each_thread(g, p) { 148 do_each_thread(g, p) {
149 if (is_user_space(p) == !freeze_user_space)
150 continue;
151
151 if (freezeable(p) && !frozen(p)) 152 if (freezeable(p) && !frozen(p))
152 printk(KERN_ERR " %s\n", p->comm); 153 printk(KERN_ERR " %s\n", p->comm);
154
153 cancel_freezing(p); 155 cancel_freezing(p);
154 } while_each_thread(g, p); 156 } while_each_thread(g, p);
155 read_unlock(&tasklist_lock); 157 read_unlock(&tasklist_lock);
156 return todo;
157 } 158 }
158 159
160 return todo;
161}
162
163/**
164 * freeze_processes - tell processes to enter the refrigerator
165 *
166 * Returns 0 on success, or the number of processes that didn't freeze,
167 * although they were told to.
168 */
169int freeze_processes(void)
170{
171 unsigned int nr_unfrozen;
172
173 printk("Stopping tasks ... ");
174 nr_unfrozen = try_to_freeze_tasks(FREEZER_USER_SPACE);
175 if (nr_unfrozen)
176 return nr_unfrozen;
177
178 sys_sync();
179 nr_unfrozen = try_to_freeze_tasks(FREEZER_KERNEL_THREADS);
180 if (nr_unfrozen)
181 return nr_unfrozen;
182
159 printk("done.\n"); 183 printk("done.\n");
160 BUG_ON(in_atomic()); 184 BUG_ON(in_atomic());
161 return 0; 185 return 0;