aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/workqueue.c
diff options
context:
space:
mode:
authorLai Jiangshan <laijs@cn.fujitsu.com>2013-03-25 19:57:19 -0400
committerTejun Heo <tj@kernel.org>2013-03-25 19:57:19 -0400
commita357fc03262988f2aa6c4a668b89be22b11ff1e7 (patch)
tree01a7064d6684ba992bc77cbac6a184497f40110c /kernel/workqueue.c
parentb09f4fd39c0e562aff3682773f4c451d6125048c (diff)
workqueue: protect wq->saved_max_active with wq->mutex
We're expanding wq->mutex to cover all fields specific to each workqueue with the end goal of replacing pwq_lock which will make locking simpler and easier to understand. This patch makes wq->saved_max_active protected by wq->mutex instead of pwq_lock. As pwq_lock locking around pwq_adjust_mac_active() is no longer necessary, this patch also replaces pwq_lock lockings of for_each_pwq() around pwq_adjust_max_active() to wq->mutex. tj: Rebased on top of the current dev branch. Updated description. Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com> Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r--kernel/workqueue.c33
1 files changed, 16 insertions, 17 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 9c32fd171d5c..af6087a5a10a 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -243,7 +243,7 @@ struct workqueue_struct {
243 struct worker *rescuer; /* I: rescue worker */ 243 struct worker *rescuer; /* I: rescue worker */
244 244
245 int nr_drainers; /* WQ: drain in progress */ 245 int nr_drainers; /* WQ: drain in progress */
246 int saved_max_active; /* PW: saved pwq max_active */ 246 int saved_max_active; /* WQ: saved pwq max_active */
247 247
248#ifdef CONFIG_SYSFS 248#ifdef CONFIG_SYSFS
249 struct wq_device *wq_dev; /* I: for sysfs interface */ 249 struct wq_device *wq_dev; /* I: for sysfs interface */
@@ -3579,13 +3579,13 @@ static void pwq_adjust_max_active(struct pool_workqueue *pwq)
3579 bool freezable = wq->flags & WQ_FREEZABLE; 3579 bool freezable = wq->flags & WQ_FREEZABLE;
3580 3580
3581 /* for @wq->saved_max_active */ 3581 /* for @wq->saved_max_active */
3582 lockdep_assert_held(&pwq_lock); 3582 lockdep_assert_held(&wq->mutex);
3583 3583
3584 /* fast exit for non-freezable wqs */ 3584 /* fast exit for non-freezable wqs */
3585 if (!freezable && pwq->max_active == wq->saved_max_active) 3585 if (!freezable && pwq->max_active == wq->saved_max_active)
3586 return; 3586 return;
3587 3587
3588 spin_lock(&pwq->pool->lock); 3588 spin_lock_irq(&pwq->pool->lock);
3589 3589
3590 if (!freezable || !(pwq->pool->flags & POOL_FREEZING)) { 3590 if (!freezable || !(pwq->pool->flags & POOL_FREEZING)) {
3591 pwq->max_active = wq->saved_max_active; 3591 pwq->max_active = wq->saved_max_active;
@@ -3603,7 +3603,7 @@ static void pwq_adjust_max_active(struct pool_workqueue *pwq)
3603 pwq->max_active = 0; 3603 pwq->max_active = 0;
3604 } 3604 }
3605 3605
3606 spin_unlock(&pwq->pool->lock); 3606 spin_unlock_irq(&pwq->pool->lock);
3607} 3607}
3608 3608
3609static void init_and_link_pwq(struct pool_workqueue *pwq, 3609static void init_and_link_pwq(struct pool_workqueue *pwq,
@@ -3622,7 +3622,6 @@ static void init_and_link_pwq(struct pool_workqueue *pwq,
3622 INIT_WORK(&pwq->unbound_release_work, pwq_unbound_release_workfn); 3622 INIT_WORK(&pwq->unbound_release_work, pwq_unbound_release_workfn);
3623 3623
3624 mutex_lock(&wq->mutex); 3624 mutex_lock(&wq->mutex);
3625 spin_lock_irq(&pwq_lock);
3626 3625
3627 /* 3626 /*
3628 * Set the matching work_color. This is synchronized with 3627 * Set the matching work_color. This is synchronized with
@@ -3636,9 +3635,10 @@ static void init_and_link_pwq(struct pool_workqueue *pwq,
3636 pwq_adjust_max_active(pwq); 3635 pwq_adjust_max_active(pwq);
3637 3636
3638 /* link in @pwq */ 3637 /* link in @pwq */
3638 spin_lock_irq(&pwq_lock);
3639 list_add_rcu(&pwq->pwqs_node, &wq->pwqs); 3639 list_add_rcu(&pwq->pwqs_node, &wq->pwqs);
3640
3641 spin_unlock_irq(&pwq_lock); 3640 spin_unlock_irq(&pwq_lock);
3641
3642 mutex_unlock(&wq->mutex); 3642 mutex_unlock(&wq->mutex);
3643} 3643}
3644 3644
@@ -3803,10 +3803,10 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
3803 */ 3803 */
3804 mutex_lock(&wq_pool_mutex); 3804 mutex_lock(&wq_pool_mutex);
3805 3805
3806 spin_lock_irq(&pwq_lock); 3806 mutex_lock(&wq->mutex);
3807 for_each_pwq(pwq, wq) 3807 for_each_pwq(pwq, wq)
3808 pwq_adjust_max_active(pwq); 3808 pwq_adjust_max_active(pwq);
3809 spin_unlock_irq(&pwq_lock); 3809 mutex_unlock(&wq->mutex);
3810 3810
3811 list_add(&wq->list, &workqueues); 3811 list_add(&wq->list, &workqueues);
3812 3812
@@ -3917,14 +3917,14 @@ void workqueue_set_max_active(struct workqueue_struct *wq, int max_active)
3917 3917
3918 max_active = wq_clamp_max_active(max_active, wq->flags, wq->name); 3918 max_active = wq_clamp_max_active(max_active, wq->flags, wq->name);
3919 3919
3920 spin_lock_irq(&pwq_lock); 3920 mutex_lock(&wq->mutex);
3921 3921
3922 wq->saved_max_active = max_active; 3922 wq->saved_max_active = max_active;
3923 3923
3924 for_each_pwq(pwq, wq) 3924 for_each_pwq(pwq, wq)
3925 pwq_adjust_max_active(pwq); 3925 pwq_adjust_max_active(pwq);
3926 3926
3927 spin_unlock_irq(&pwq_lock); 3927 mutex_unlock(&wq->mutex);
3928} 3928}
3929EXPORT_SYMBOL_GPL(workqueue_set_max_active); 3929EXPORT_SYMBOL_GPL(workqueue_set_max_active);
3930 3930
@@ -4287,7 +4287,7 @@ EXPORT_SYMBOL_GPL(work_on_cpu);
4287 * pool->worklist. 4287 * pool->worklist.
4288 * 4288 *
4289 * CONTEXT: 4289 * CONTEXT:
4290 * Grabs and releases wq_pool_mutex, pwq_lock and pool->lock's. 4290 * Grabs and releases wq_pool_mutex, wq->mutex and pool->lock's.
4291 */ 4291 */
4292void freeze_workqueues_begin(void) 4292void freeze_workqueues_begin(void)
4293{ 4293{
@@ -4309,13 +4309,12 @@ void freeze_workqueues_begin(void)
4309 spin_unlock_irq(&pool->lock); 4309 spin_unlock_irq(&pool->lock);
4310 } 4310 }
4311 4311
4312 /* suppress further executions by setting max_active to zero */
4313 spin_lock_irq(&pwq_lock);
4314 list_for_each_entry(wq, &workqueues, list) { 4312 list_for_each_entry(wq, &workqueues, list) {
4313 mutex_lock(&wq->mutex);
4315 for_each_pwq(pwq, wq) 4314 for_each_pwq(pwq, wq)
4316 pwq_adjust_max_active(pwq); 4315 pwq_adjust_max_active(pwq);
4316 mutex_unlock(&wq->mutex);
4317 } 4317 }
4318 spin_unlock_irq(&pwq_lock);
4319 4318
4320 mutex_unlock(&wq_pool_mutex); 4319 mutex_unlock(&wq_pool_mutex);
4321} 4320}
@@ -4373,7 +4372,7 @@ out_unlock:
4373 * frozen works are transferred to their respective pool worklists. 4372 * frozen works are transferred to their respective pool worklists.
4374 * 4373 *
4375 * CONTEXT: 4374 * CONTEXT:
4376 * Grabs and releases wq_pool_mutex, pwq_lock and pool->lock's. 4375 * Grabs and releases wq_pool_mutex, wq->mutex and pool->lock's.
4377 */ 4376 */
4378void thaw_workqueues(void) 4377void thaw_workqueues(void)
4379{ 4378{
@@ -4396,12 +4395,12 @@ void thaw_workqueues(void)
4396 } 4395 }
4397 4396
4398 /* restore max_active and repopulate worklist */ 4397 /* restore max_active and repopulate worklist */
4399 spin_lock_irq(&pwq_lock);
4400 list_for_each_entry(wq, &workqueues, list) { 4398 list_for_each_entry(wq, &workqueues, list) {
4399 mutex_lock(&wq->mutex);
4401 for_each_pwq(pwq, wq) 4400 for_each_pwq(pwq, wq)
4402 pwq_adjust_max_active(pwq); 4401 pwq_adjust_max_active(pwq);
4402 mutex_unlock(&wq->mutex);
4403 } 4403 }
4404 spin_unlock_irq(&pwq_lock);
4405 4404
4406 workqueue_freezing = false; 4405 workqueue_freezing = false;
4407out_unlock: 4406out_unlock: