aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/workqueue.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-03-13 19:51:35 -0400
committerTejun Heo <tj@kernel.org>2013-03-13 19:51:35 -0400
commit699ce097efe8f45bc5c055e4f12cb1e271c270d9 (patch)
treedb116c908ed97eaf621c4dc99a4896acd51e56a2 /kernel/workqueue.c
parent0fbd95aa8a056194933fba4ae78c50fc20f0704e (diff)
workqueue: implement and use pwq_adjust_max_active()
Rename pwq_set_max_active() to pwq_adjust_max_active() and move pool_workqueue->max_active synchronization and max_active determination logic into it. The new function should be called with workqueue_lock held for stable workqueue->saved_max_active, determines the current max_active value the target pool_workqueue should be using from @wq->saved_max_active and the state of the associated pool, and applies it with proper synchronization. The current two users - workqueue_set_max_active() and thaw_workqueues() - are updated accordingly. In addition, the manual freezing handling in __alloc_workqueue_key() and freeze_workqueues_begin() are replaced with calls to pwq_adjust_max_active(). This centralizes max_active handling so that it's less error-prone. Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r--kernel/workqueue.c83
1 files changed, 38 insertions, 45 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index d51928981615..9e2ec4ca415a 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -3726,23 +3726,38 @@ static void pwq_unbound_release_workfn(struct work_struct *work)
3726} 3726}
3727 3727
3728/** 3728/**
3729 * pwq_set_max_active - adjust max_active of a pwq 3729 * pwq_adjust_max_active - update a pwq's max_active to the current setting
3730 * @pwq: target pool_workqueue 3730 * @pwq: target pool_workqueue
3731 * @max_active: new max_active value.
3732 *
3733 * Set @pwq->max_active to @max_active and activate delayed works if
3734 * increased.
3735 * 3731 *
3736 * CONTEXT: 3732 * If @pwq isn't freezing, set @pwq->max_active to the associated
3737 * spin_lock_irq(pool->lock). 3733 * workqueue's saved_max_active and activate delayed work items
3734 * accordingly. If @pwq is freezing, clear @pwq->max_active to zero.
3738 */ 3735 */
3739static void pwq_set_max_active(struct pool_workqueue *pwq, int max_active) 3736static void pwq_adjust_max_active(struct pool_workqueue *pwq)
3740{ 3737{
3741 pwq->max_active = max_active; 3738 struct workqueue_struct *wq = pwq->wq;
3739 bool freezable = wq->flags & WQ_FREEZABLE;
3740
3741 /* for @wq->saved_max_active */
3742 lockdep_assert_held(&workqueue_lock);
3743
3744 /* fast exit for non-freezable wqs */
3745 if (!freezable && pwq->max_active == wq->saved_max_active)
3746 return;
3747
3748 spin_lock(&pwq->pool->lock);
3749
3750 if (!freezable || !(pwq->pool->flags & POOL_FREEZING)) {
3751 pwq->max_active = wq->saved_max_active;
3742 3752
3743 while (!list_empty(&pwq->delayed_works) && 3753 while (!list_empty(&pwq->delayed_works) &&
3744 pwq->nr_active < pwq->max_active) 3754 pwq->nr_active < pwq->max_active)
3745 pwq_activate_first_delayed(pwq); 3755 pwq_activate_first_delayed(pwq);
3756 } else {
3757 pwq->max_active = 0;
3758 }
3759
3760 spin_unlock(&pwq->pool->lock);
3746} 3761}
3747 3762
3748static void init_and_link_pwq(struct pool_workqueue *pwq, 3763static void init_and_link_pwq(struct pool_workqueue *pwq,
@@ -3932,15 +3947,14 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
3932 goto err_destroy; 3947 goto err_destroy;
3933 3948
3934 /* 3949 /*
3935 * workqueue_lock protects global freeze state and workqueues 3950 * workqueue_lock protects global freeze state and workqueues list.
3936 * list. Grab it, set max_active accordingly and add the new 3951 * Grab it, adjust max_active and add the new workqueue to
3937 * workqueue to workqueues list. 3952 * workqueues list.
3938 */ 3953 */
3939 spin_lock_irq(&workqueue_lock); 3954 spin_lock_irq(&workqueue_lock);
3940 3955
3941 if (workqueue_freezing && wq->flags & WQ_FREEZABLE) 3956 for_each_pwq(pwq, wq)
3942 for_each_pwq(pwq, wq) 3957 pwq_adjust_max_active(pwq);
3943 pwq->max_active = 0;
3944 3958
3945 list_add(&wq->list, &workqueues); 3959 list_add(&wq->list, &workqueues);
3946 3960
@@ -4055,17 +4069,8 @@ void workqueue_set_max_active(struct workqueue_struct *wq, int max_active)
4055 4069
4056 wq->saved_max_active = max_active; 4070 wq->saved_max_active = max_active;
4057 4071
4058 for_each_pwq(pwq, wq) { 4072 for_each_pwq(pwq, wq)
4059 struct worker_pool *pool = pwq->pool; 4073 pwq_adjust_max_active(pwq);
4060
4061 spin_lock(&pool->lock);
4062
4063 if (!(wq->flags & WQ_FREEZABLE) ||
4064 !(pool->flags & POOL_FREEZING))
4065 pwq_set_max_active(pwq, max_active);
4066
4067 spin_unlock(&pool->lock);
4068 }
4069 4074
4070 spin_unlock_irq(&workqueue_lock); 4075 spin_unlock_irq(&workqueue_lock);
4071} 4076}
@@ -4358,14 +4363,8 @@ void freeze_workqueues_begin(void)
4358 4363
4359 /* suppress further executions by setting max_active to zero */ 4364 /* suppress further executions by setting max_active to zero */
4360 list_for_each_entry(wq, &workqueues, list) { 4365 list_for_each_entry(wq, &workqueues, list) {
4361 if (!(wq->flags & WQ_FREEZABLE)) 4366 for_each_pwq(pwq, wq)
4362 continue; 4367 pwq_adjust_max_active(pwq);
4363
4364 for_each_pwq(pwq, wq) {
4365 spin_lock(&pwq->pool->lock);
4366 pwq->max_active = 0;
4367 spin_unlock(&pwq->pool->lock);
4368 }
4369 } 4368 }
4370 4369
4371 spin_unlock_irq(&workqueue_lock); 4370 spin_unlock_irq(&workqueue_lock);
@@ -4445,14 +4444,8 @@ void thaw_workqueues(void)
4445 4444
4446 /* restore max_active and repopulate worklist */ 4445 /* restore max_active and repopulate worklist */
4447 list_for_each_entry(wq, &workqueues, list) { 4446 list_for_each_entry(wq, &workqueues, list) {
4448 if (!(wq->flags & WQ_FREEZABLE)) 4447 for_each_pwq(pwq, wq)
4449 continue; 4448 pwq_adjust_max_active(pwq);
4450
4451 for_each_pwq(pwq, wq) {
4452 spin_lock(&pwq->pool->lock);
4453 pwq_set_max_active(pwq, wq->saved_max_active);
4454 spin_unlock(&pwq->pool->lock);
4455 }
4456 } 4449 }
4457 4450
4458 /* kick workers */ 4451 /* kick workers */