History

workqueue: break init_and_link_pwq() into two functions and introduce alloc_unbound_pwq()

Break init_and_link_pwq() into init_pwq() and link_pwq() and move unbound-workqueue specific handling into apply_workqueue_attrs(). Also, factor out unbound pool and pool_workqueue allocation into alloc_unbound_pwq(). This reorganization is to prepare for NUMA affinity and doesn't introduce any functional changes.

Tejun Heo committed 13 years ago

Commit f147f291 parent df2d5ae1 file · +49 −29Browse files

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

Unified · Split

kernel/workqueue.c+49−29
@@ -3626,13 +3626,10 @@ static void pwq_adjust_max_active(struct pool_workqueue *pwq) · 3625 unmodified lines
36263626 spin_unlock_irq(&pwq->pool->lock);
36273627 }
36283628
3629−static void init_and_link_pwq(struct pool_workqueue *pwq,
3630− struct workqueue_struct *wq,
3631− struct worker_pool *pool,
3632− struct pool_workqueue **p_last_pwq)
3629+/* initialize newly zalloced @pwq which is associated with @wq and @pool */
3630+static void init_pwq(struct pool_workqueue *pwq, struct workqueue_struct *wq,
3631+ struct worker_pool *pool)
36333632 {
3634− int node;
3635−
36363633 BUG_ON((unsigned long)pwq & WORK_STRUCT_FLAG_MASK);
36373634
36383635 pwq->pool = pool;
@@ -3642,8 +3639,15 @@ static void init_and_link_pwq(struct pool_workqueue *pwq, · 3 unmodified lines
36423639 INIT_LIST_HEAD(&pwq->delayed_works);
36433640 INIT_LIST_HEAD(&pwq->mayday_node);
36443641 INIT_WORK(&pwq->unbound_release_work, pwq_unbound_release_workfn);
3642+}
36453643
3646− mutex_lock(&wq->mutex);
3644+/* sync @pwq with the current state of its associated wq and link it */
3645+static void link_pwq(struct pool_workqueue *pwq,
3646+ struct pool_workqueue **p_last_pwq)
3647+{
3648+ struct workqueue_struct *wq = pwq->wq;
3649+
3650+ lockdep_assert_held(&wq->mutex);
36473651
36483652 /*
36493653 * Set the matching work_color. This is synchronized with
@@ -3658,14 +3662,29 @@ static void init_and_link_pwq(struct pool_workqueue *pwq, · 8 unmodified lines
36583662
36593663 /* link in @pwq */
36603664 list_add_rcu(&pwq->pwqs_node, &wq->pwqs);
3665+}
36613666
3662− if (wq->flags & WQ_UNBOUND) {
3663− copy_workqueue_attrs(wq->unbound_attrs, pool->attrs);
3664− for_each_node(node)
3665− rcu_assign_pointer(wq->numa_pwq_tbl[node], pwq);
3667+/* obtain a pool matching @attr and create a pwq associating the pool and @wq */
3668+static struct pool_workqueue *alloc_unbound_pwq(struct workqueue_struct *wq,
3669+ const struct workqueue_attrs *attrs)
3670+{
3671+ struct worker_pool *pool;
3672+ struct pool_workqueue *pwq;
3673+
3674+ lockdep_assert_held(&wq_pool_mutex);
3675+
3676+ pool = get_unbound_pool(attrs);
3677+ if (!pool)
3678+ return NULL;
3679+
3680+ pwq = kmem_cache_zalloc(pwq_cache, GFP_KERNEL);
3681+ if (!pwq) {
3682+ put_unbound_pool(pool);
3683+ return NULL;
36663684 }
36673685
3668− mutex_unlock(&wq->mutex);
3686+ init_pwq(pwq, wq, pool);
3687+ return pwq;
36693688 }
36703689
36713690 /**
@@ -3686,9 +3705,8 @@ int apply_workqueue_attrs(struct workqueue_struct *wq, · 14 unmodified lines
36863705 const struct workqueue_attrs *attrs)
36873706 {
36883707 struct workqueue_attrs *new_attrs;
3689− struct pool_workqueue *pwq = NULL, *last_pwq;
3690− struct worker_pool *pool;
3691− int ret;
3708+ struct pool_workqueue *pwq, *last_pwq;
3709+ int node, ret;
36923710
36933711 /* only unbound workqueues can change attributes */
36943712 if (WARN_ON(!(wq->flags & WQ_UNBOUND)))
@@ -3707,22 +3725,21 @@ int apply_workqueue_attrs(struct workqueue_struct *wq, · 12 unmodified lines
37073725 cpumask_and(new_attrs->cpumask, new_attrs->cpumask, cpu_possible_mask);
37083726
37093727 mutex_lock(&wq_pool_mutex);
3710−
3711− pwq = kmem_cache_zalloc(pwq_cache, GFP_KERNEL);
3712− if (!pwq) {
3713− mutex_unlock(&wq_pool_mutex);
3728+ pwq = alloc_unbound_pwq(wq, new_attrs);
3729+ mutex_unlock(&wq_pool_mutex);
3730+ if (!pwq)
37143731 goto enomem;
3715− }
37163732
3717− pool = get_unbound_pool(new_attrs);
3718− if (!pool) {
3719− mutex_unlock(&wq_pool_mutex);
3720− goto enomem;
3721− }
3733+ mutex_lock(&wq->mutex);
37223734
3723− mutex_unlock(&wq_pool_mutex);
3735+ link_pwq(pwq, &last_pwq);
3736+
3737+ copy_workqueue_attrs(wq->unbound_attrs, new_attrs);
3738+ for_each_node(node)
3739+ rcu_assign_pointer(wq->numa_pwq_tbl[node], pwq);
3740+
3741+ mutex_unlock(&wq->mutex);
37243742
3725− init_and_link_pwq(pwq, wq, pool, &last_pwq);
37263743 if (last_pwq) {
37273744 spin_lock_irq(&last_pwq->pool->lock);
37283745 put_pwq(last_pwq);
@@ -3736,7 +3753,6 @@ out_free: · 7 unmodified lines
37363753 return ret;
37373754
37383755 enomem:
3739− kmem_cache_free(pwq_cache, pwq);
37403756 ret = -ENOMEM;
37413757 goto out_free;
37423758 }
@@ -3757,7 +3773,11 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq) · 14 unmodified lines
37573773 struct worker_pool *cpu_pools =
37583774 per_cpu(cpu_worker_pools, cpu);
37593775
3760− init_and_link_pwq(pwq, wq, &cpu_pools[highpri], NULL);
3776+ init_pwq(pwq, wq, &cpu_pools[highpri]);
3777+
3778+ mutex_lock(&wq->mutex);
3779+ link_pwq(pwq, NULL);
3780+ mutex_unlock(&wq->mutex);
37613781 }
37623782 return 0;
37633783 } else {