summary refs log tree commit diff
path: root/kernel/workqueue.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-02-14 14:04:46 +0100
committerTejun Heo <tj@kernel.org>2011-02-14 14:04:46 +0100
commit7576958a9d5a4a677ad7dd40901cdbb6c1110c98 (patch)
treedb0b180feebf3a4ca6cd3155764cfc61a6d7f3cf /kernel/workqueue.c
parent795abaf1e4e188c4171e3cd3dbb11a9fcacaf505 (diff)
downloadlinux-7576958a9d5a4a677ad7dd40901cdbb6c1110c98.tar.gz
workqueue: wake up a worker when a rescuer is leaving a gcwq
After executing the matching works, a rescuer leaves the gcwq whether
there are more pending works or not.  This may decrease the
concurrency level to zero and stall execution until a new work item is
queued on the gcwq.

Make rescuer wake up a regular worker when it leaves a gcwq if there
are more works to execute, so that execution isn't stalled.

Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: Ray Jui <rjui@broadcom.com>
Cc: stable@kernel.org
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r--kernel/workqueue.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 11869faa6819..90a17ca2ad0b 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -2047,6 +2047,15 @@ repeat:
 				move_linked_works(work, scheduled, &n);
 
 		process_scheduled_works(rescuer);
+
+		/*
+		 * Leave this gcwq.  If keep_working() is %true, notify a
+		 * regular worker; otherwise, we end up with 0 concurrency
+		 * and stalling the execution.
+		 */
+		if (keep_working(gcwq))
+			wake_up_worker(gcwq);
+
 		spin_unlock_irq(&gcwq->lock);
 	}