[linux-pm] SMP suspend broken due to "swsusp: Change code ordering in disk.c" et al.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

On Friday, 23 February 2007 21:23, Johannes Berg wrote:
> Hi,
> 
> > In that case the fastest fix would be to revert the commit in question (and
> > some others too),
> 
> Yeah, the same thing exists for uswsusp and regular suspend-to-ram
> afaict.

Exactly.

> > but I don't think it will be satisfactory for the people with
> > the ACPI issues related to the resume code ordering.  Moreover, it really
> > is more reasonable to disable nonboot CPUs after tasks have been frozen
> > (I think it's also necessary for the CPU hotplugging with the help of the
> > freezer; see below).
> > 
> > I'll try to find a better solution later today.
> 
> Great.

I'm looking at it right now, but this is quite complicated.

Could you please try the appended patch?  It's somewhat hackish, but may work.

The idea is to do nothing on CPU unplug if the CPU's worker thread is frozen
and later check in the thread itself if it has been replaced by another one.

Greetings,
Rafael


 kernel/workqueue.c |   10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

Index: linux-2.6.20-mm2/kernel/workqueue.c
===================================================================
--- linux-2.6.20-mm2.orig/kernel/workqueue.c	2007-02-23 22:48:50.000000000 +0100
+++ linux-2.6.20-mm2/kernel/workqueue.c	2007-02-24 00:58:57.000000000 +0100
@@ -316,7 +316,13 @@ static int worker_thread(void *__cwq)
 	do_sigaction(SIGCHLD, &sa, (struct k_sigaction *)0);
 
 	for (;;) {
-		try_to_freeze();
+		if (try_to_freeze()) {
+			/* We've just exited the refrigerator.  If our CPU is
+			 * a nonboot one, we might have been replaced.
+			 */
+			if (cwq->thread != current)
+				break;
+		}
 
 		prepare_to_wait(&cwq->more_work, &wait, TASK_INTERRUPTIBLE);
 		if (!cwq->should_stop && list_empty(&cwq->worklist))
@@ -713,7 +719,7 @@ static void cleanup_workqueue_thread(str
 	int alive = 0;
 
 	spin_lock_irq(&cwq->lock);
-	if (cwq->thread != NULL) {
+	if (cwq->thread != NULL && !frozen(cwq->thread)) {
 		insert_wq_barrier(cwq, &barr, 1);
 		cwq->should_stop = 1;
 		alive = 1;


[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux