diff options
| author | Rafael J. Wysocki <rjw@sisk.pl> | 2006-12-06 23:34:40 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-07 11:39:28 -0500 |
| commit | 11b2ce2ba90f801e2a5ebba4e6b7da72d87f2b13 (patch) | |
| tree | e7477edb04a15a3128523877558e1eb8694adbc9 /kernel/power | |
| parent | a9b6f562f14dc28fb4b2415f0f275cede0abe9b5 (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')
| -rw-r--r-- | kernel/power/process.c | 84 |
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 */ | 89 | static unsigned int try_to_freeze_tasks(int freeze_user_space) |
| 90 | int 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 | */ | ||
| 169 | int 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; |
