On Tuesday, 5 December 2006 22:26, Rafael J. Wysocki wrote: > On Tuesday, 5 December 2006 22:03, Rafael J. Wysocki wrote: > > Okay, I have replaced my [1/2] with the patch below ... > > > > On Tuesday, 5 December 2006 11:34, Pavel Machek wrote: <--snip--> > > Well, now the task that was stopped before the suspend doesn't go to the > refrigerator when it's received the continuation signal after the resume. > Good, but is it sufficient? Well, almost. Namely, if you suspend with a stopped vi and you look at the dmesg output after the resume, there will be something like this: Restarting tasks ... <4> Strange, vi not stopped which means that thaw_tasks() is confused by the lurking stopped task. We can fix that by checking if the task in question is not stopped before printing the message in thaw_tasks() and we get this: kernel/power/process.c | 21 ++++++++++++++++++--- kernel/signal.c | 4 +++- 2 files changed, 21 insertions(+), 4 deletions(-) Index: linux-2.6.19-rc6-mm2/kernel/power/process.c =================================================================== --- linux-2.6.19-rc6-mm2.orig/kernel/power/process.c 2006-12-05 21:10:00.000000000 +0100 +++ linux-2.6.19-rc6-mm2/kernel/power/process.c 2006-12-05 22:44:45.000000000 +0100 @@ -28,8 +28,7 @@ static inline int freezeable(struct task if ((p == current) || (p->flags & PF_NOFREEZE) || (p->exit_state == EXIT_ZOMBIE) || - (p->exit_state == EXIT_DEAD) || - (p->state == TASK_STOPPED)) + (p->exit_state == EXIT_DEAD)) return 0; return 1; } @@ -103,6 +102,9 @@ static unsigned int try_to_freeze_tasks( if (frozen(p)) continue; + if (p->state == TASK_STOPPED && freezing(p)) + continue; + if (p->state == TASK_TRACED && (frozen(p->parent) || p->parent->state == TASK_STOPPED)) { @@ -185,6 +187,18 @@ int freeze_processes(void) return 0; } +static inline void release_stopped_tasks(void) +{ + struct task_struct *g, *p; + + read_lock(&tasklist_lock); + do_each_thread(g, p) { + if (p->state == TASK_STOPPED && freezing(p)) + cancel_freezing(p); + } while_each_thread(g, p); + read_unlock(&tasklist_lock); +} + static void thaw_tasks(int thaw_user_space) { struct task_struct *g, *p; @@ -197,7 +211,7 @@ static void thaw_tasks(int thaw_user_spa if (is_user_space(p) == !thaw_user_space) continue; - if (!thaw_process(p)) + if (!thaw_process(p) && p->state != TASK_STOPPED) printk(KERN_WARNING " Strange, %s not stopped\n", p->comm ); } while_each_thread(g, p); @@ -207,6 +221,7 @@ static void thaw_tasks(int thaw_user_spa void thaw_processes(void) { printk("Restarting tasks ... "); + release_stopped_tasks(); thaw_tasks(FREEZER_KERNEL_THREADS); thaw_tasks(FREEZER_USER_SPACE); schedule(); Index: linux-2.6.19-rc6-mm2/kernel/signal.c =================================================================== --- linux-2.6.19-rc6-mm2.orig/kernel/signal.c 2006-12-05 21:10:00.000000000 +0100 +++ linux-2.6.19-rc6-mm2/kernel/signal.c 2006-12-05 21:11:31.000000000 +0100 @@ -1829,7 +1829,9 @@ finish_stop(int stop_count) read_unlock(&tasklist_lock); } - schedule(); + do { + schedule(); + } while (try_to_freeze()); /* * Now we don't run again until continued. */ But now it looks almost like my [1/2], doesn't it? ;-) Greetings, Rafael -- If you don't have the time to read, you don't have the time or the tools to write. - Stephen King