History

workqueue: introduce numa_pwq_tbl_install()

Factor out pool_workqueue linking and installation into numa_pwq_tbl[] from apply_workqueue_attrs() into numa_pwq_tbl_install(). link_pwq() is made safe to call multiple times. numa_pwq_tbl_install() links the pwq, installs it into numa_pwq_tbl[] at the specified node and returns the old entry. @last_pwq is removed from link_pwq() as the return value of the new function can be used instead. This is to prepare for NUMA affinity support for unbound workqueues.

Tejun Heo committed 13 years ago

Commit 1befcf31 parent e50aba91 file · +26 −9Browse files

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

Unified · Split

kernel/workqueue.c+26−9
@@ -3639,24 +3639,26 @@ static void init_pwq(struct pool_workqueue *pwq, struct workqueue_struct *wq, · 3638 unmodified lines
36393639 pwq->flush_color = -1;
36403640 pwq->refcnt = 1;
36413641 INIT_LIST_HEAD(&pwq->delayed_works);
3642+ INIT_LIST_HEAD(&pwq->pwqs_node);
36423643 INIT_LIST_HEAD(&pwq->mayday_node);
36433644 INIT_WORK(&pwq->unbound_release_work, pwq_unbound_release_workfn);
36443645 }
36453646
36463647 /* sync @pwq with the current state of its associated wq and link it */
3647−static void link_pwq(struct pool_workqueue *pwq,
3648− struct pool_workqueue **p_last_pwq)
3648+static void link_pwq(struct pool_workqueue *pwq)
36493649 {
36503650 struct workqueue_struct *wq = pwq->wq;
36513651
36523652 lockdep_assert_held(&wq->mutex);
36533653
3654+ /* may be called multiple times, ignore if already linked */
3655+ if (!list_empty(&pwq->pwqs_node))
3656+ return;
3657+
36543658 /*
36553659 * Set the matching work_color. This is synchronized with
36563660 * wq->mutex to avoid confusing flush_workqueue().
36573661 */
3658− if (p_last_pwq)
3659− *p_last_pwq = first_pwq(wq);
36603662 pwq->work_color = wq->work_color;
36613663
36623664 /* sync max_active to the current setting */
@@ -3689,6 +3691,23 @@ static struct pool_workqueue *alloc_unbound_pwq(struct workqueue_struct *wq, · 26 unmodified lines
36893691 return pwq;
36903692 }
36913693
3694+/* install @pwq into @wq's numa_pwq_tbl[] for @node and return the old pwq */
3695+static struct pool_workqueue *numa_pwq_tbl_install(struct workqueue_struct *wq,
3696+ int node,
3697+ struct pool_workqueue *pwq)
3698+{
3699+ struct pool_workqueue *old_pwq;
3700+
3701+ lockdep_assert_held(&wq->mutex);
3702+
3703+ /* link_pwq() can handle duplicate calls */
3704+ link_pwq(pwq);
3705+
3706+ old_pwq = rcu_access_pointer(wq->numa_pwq_tbl[node]);
3707+ rcu_assign_pointer(wq->numa_pwq_tbl[node], pwq);
3708+ return old_pwq;
3709+}
3710+
36923711 /**
36933712 * apply_workqueue_attrs - apply new workqueue_attrs to an unbound workqueue
36943713 * @wq: the target workqueue
@@ -3707,7 +3726,7 @@ int apply_workqueue_attrs(struct workqueue_struct *wq, · 12 unmodified lines
37073726 const struct workqueue_attrs *attrs)
37083727 {
37093728 struct workqueue_attrs *new_attrs;
3710− struct pool_workqueue *pwq, *last_pwq;
3729+ struct pool_workqueue *pwq, *last_pwq = NULL;
37113730 int node, ret;
37123731
37133732 /* only unbound workqueues can change attributes */
@@ -3734,11 +3753,9 @@ int apply_workqueue_attrs(struct workqueue_struct *wq, · 20 unmodified lines
37343753
37353754 mutex_lock(&wq->mutex);
37363755
3737− link_pwq(pwq, &last_pwq);
3738−
37393756 copy_workqueue_attrs(wq->unbound_attrs, new_attrs);
37403757 for_each_node(node)
3741− rcu_assign_pointer(wq->numa_pwq_tbl[node], pwq);
3758+ last_pwq = numa_pwq_tbl_install(wq, node, pwq);
37423759
37433760 mutex_unlock(&wq->mutex);
37443761
@@ -3778,7 +3795,7 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq) · 33 unmodified lines
37783795 init_pwq(pwq, wq, &cpu_pools[highpri]);
37793796
37803797 mutex_lock(&wq->mutex);
3781− link_pwq(pwq, NULL);
3798+ link_pwq(pwq);
37823799 mutex_unlock(&wq->mutex);
37833800 }
37843801 return 0;