History

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.

Lai Jiangshan committed 13 years ago

Commit a357fc01 parent b09f4fd1 file · +16 −17Browse files

Showing the changes to kernel/workqueue.c (1 of 1 file). Show all

Unified · Split

kernel/workqueue.c+16−17
@@ -243,7 +243,7 @@ struct workqueue_struct { · 242 unmodified lines
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_SYSFS248#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) · 3329 unmodified lines
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) · 11 unmodified lines
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, · 12 unmodified lines
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 with3627 * Set the matching work_color. This is synchronized with
@@ -3636,9 +3635,10 @@ static void init_and_link_pwq(struct pool_workqueue *pwq, · 7 unmodified lines
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, · 158 unmodified lines
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) · 104 unmodified lines
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); · 356 unmodified lines
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) · 15 unmodified lines
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: · 51 unmodified lines
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) · 16 unmodified lines
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:

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t