aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/workqueue.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2010-07-14 05:31:20 -0400
committerTejun Heo <tj@kernel.org>2010-07-14 05:31:20 -0400
commit9f9c23644b07e7a51f6f39064e61c150be712932 (patch)
tree831849ae8bfd602b3333e8ea8e3beb2cf0dee348 /kernel/workqueue.c
parent083b804c4d3e1e3d0eace56bdbc0f674946d2847 (diff)
workqueue: fix locking in retry path of maybe_create_worker()
maybe_create_worker() mismanaged locking when worker creation fails and it has to retry. Fix locking and simplify lock manipulation. Signed-off-by: Tejun Heo <tj@kernel.org> Reported-by: Yong Zhang <yong.zhang@windriver.com>
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r--kernel/workqueue.c8
1 files changed, 3 insertions, 5 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 20d6237d749..aca94726e20 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1442,14 +1442,14 @@ static bool maybe_create_worker(struct global_cwq *gcwq)
1442 if (!need_to_create_worker(gcwq)) 1442 if (!need_to_create_worker(gcwq))
1443 return false; 1443 return false;
1444restart: 1444restart:
1445 spin_unlock_irq(&gcwq->lock);
1446
1445 /* if we don't make progress in MAYDAY_INITIAL_TIMEOUT, call for help */ 1447 /* if we don't make progress in MAYDAY_INITIAL_TIMEOUT, call for help */
1446 mod_timer(&gcwq->mayday_timer, jiffies + MAYDAY_INITIAL_TIMEOUT); 1448 mod_timer(&gcwq->mayday_timer, jiffies + MAYDAY_INITIAL_TIMEOUT);
1447 1449
1448 while (true) { 1450 while (true) {
1449 struct worker *worker; 1451 struct worker *worker;
1450 1452
1451 spin_unlock_irq(&gcwq->lock);
1452
1453 worker = create_worker(gcwq, true); 1453 worker = create_worker(gcwq, true);
1454 if (worker) { 1454 if (worker) {
1455 del_timer_sync(&gcwq->mayday_timer); 1455 del_timer_sync(&gcwq->mayday_timer);
@@ -1462,15 +1462,13 @@ restart:
1462 if (!need_to_create_worker(gcwq)) 1462 if (!need_to_create_worker(gcwq))
1463 break; 1463 break;
1464 1464
1465 spin_unlock_irq(&gcwq->lock);
1466 __set_current_state(TASK_INTERRUPTIBLE); 1465 __set_current_state(TASK_INTERRUPTIBLE);
1467 schedule_timeout(CREATE_COOLDOWN); 1466 schedule_timeout(CREATE_COOLDOWN);
1468 spin_lock_irq(&gcwq->lock); 1467
1469 if (!need_to_create_worker(gcwq)) 1468 if (!need_to_create_worker(gcwq))
1470 break; 1469 break;
1471 } 1470 }
1472 1471
1473 spin_unlock_irq(&gcwq->lock);
1474 del_timer_sync(&gcwq->mayday_timer); 1472 del_timer_sync(&gcwq->mayday_timer);
1475 spin_lock_irq(&gcwq->lock); 1473 spin_lock_irq(&gcwq->lock);
1476 if (need_to_create_worker(gcwq)) 1474 if (need_to_create_worker(gcwq))