提交 3e3cb7b7 编写于 作者: B Biaoxiang Ye 提交者: Yang Yingliang

workqueue: implement NUMA affinity for single thread workqueue

euleros inclusion
category: feature
feature: Implement NUMA affinity for order workqueue

-------------------------------------------------

Currently, single thread workqueue only have single pwq, all of
works are queued the same workerpool. This is not optimal on
NUMA machines, will cause workers jump around across node.

This patch add a new wq flags __WQ_DYNAMIC,  this new kind of
single thread workqueue creates a separate pwq covering the
intersecting CPUS for each NUMA node which has online CPUS
in @attrs->cpumask instead of mapping all entries of numa_pwq_tbl[]
to the same pwq. After this, we can specify the @cpu of
queue_work_on, so the work can be executed on the same NUMA
node of the specified @cpu.
This kind of wq only support single work, multi works can't guarantee
the work's order.
Signed-off-by: NBiaoxiang Ye <yebiaoxiang@huawei.com>
Acked-by: NHanjun Guo <guohanjun@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 bea876f1
...@@ -361,6 +361,7 @@ enum { ...@@ -361,6 +361,7 @@ enum {
__WQ_ORDERED = 1 << 17, /* internal: workqueue is ordered */ __WQ_ORDERED = 1 << 17, /* internal: workqueue is ordered */
__WQ_LEGACY = 1 << 18, /* internal: create*_workqueue() */ __WQ_LEGACY = 1 << 18, /* internal: create*_workqueue() */
__WQ_ORDERED_EXPLICIT = 1 << 19, /* internal: alloc_ordered_workqueue() */ __WQ_ORDERED_EXPLICIT = 1 << 19, /* internal: alloc_ordered_workqueue() */
__WQ_DYNAMIC = 1 << 25, /* internal: only support single work order WQ */
WQ_MAX_ACTIVE = 512, /* I like 512, better ideas? */ WQ_MAX_ACTIVE = 512, /* I like 512, better ideas? */
WQ_MAX_UNBOUND_PER_CPU = 4, /* 4 * #cpus for unbound wq */ WQ_MAX_UNBOUND_PER_CPU = 4, /* 4 * #cpus for unbound wq */
......
...@@ -3843,6 +3843,9 @@ apply_wqattrs_prepare(struct workqueue_struct *wq, ...@@ -3843,6 +3843,9 @@ apply_wqattrs_prepare(struct workqueue_struct *wq,
* wq_unbound_cpumask, we fallback to the wq_unbound_cpumask. * wq_unbound_cpumask, we fallback to the wq_unbound_cpumask.
*/ */
copy_workqueue_attrs(new_attrs, attrs); copy_workqueue_attrs(new_attrs, attrs);
if (wq->flags & __WQ_DYNAMIC)
new_attrs->no_numa = false;
cpumask_and(new_attrs->cpumask, new_attrs->cpumask, wq_unbound_cpumask); cpumask_and(new_attrs->cpumask, new_attrs->cpumask, wq_unbound_cpumask);
if (unlikely(cpumask_empty(new_attrs->cpumask))) if (unlikely(cpumask_empty(new_attrs->cpumask)))
cpumask_copy(new_attrs->cpumask, wq_unbound_cpumask); cpumask_copy(new_attrs->cpumask, wq_unbound_cpumask);
...@@ -4092,10 +4095,12 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq) ...@@ -4092,10 +4095,12 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq)
return 0; return 0;
} else if (wq->flags & __WQ_ORDERED) { } else if (wq->flags & __WQ_ORDERED) {
ret = apply_workqueue_attrs(wq, ordered_wq_attrs[highpri]); ret = apply_workqueue_attrs(wq, ordered_wq_attrs[highpri]);
/* there should only be single pwq for ordering guarantee */ if (!(wq->flags & __WQ_DYNAMIC)) {
WARN(!ret && (wq->pwqs.next != &wq->dfl_pwq->pwqs_node || /* there should only be single pwq for ordering guarantee */
wq->pwqs.prev != &wq->dfl_pwq->pwqs_node), WARN(!ret && (wq->pwqs.next != &wq->dfl_pwq->pwqs_node ||
"ordering guarantee broken for workqueue %s\n", wq->name); wq->pwqs.prev != &wq->dfl_pwq->pwqs_node),
"ordering guarantee broken for workqueue %s\n", wq->name);
}
return ret; return ret;
} else { } else {
return apply_workqueue_attrs(wq, unbound_std_wq_attrs[highpri]); return apply_workqueue_attrs(wq, unbound_std_wq_attrs[highpri]);
...@@ -5166,7 +5171,7 @@ static int workqueue_apply_unbound_cpumask(void) ...@@ -5166,7 +5171,7 @@ static int workqueue_apply_unbound_cpumask(void)
if (!(wq->flags & WQ_UNBOUND)) if (!(wq->flags & WQ_UNBOUND))
continue; continue;
/* creating multiple pwqs breaks ordering guarantee */ /* creating multiple pwqs breaks ordering guarantee */
if (wq->flags & __WQ_ORDERED) if ((wq->flags & __WQ_ORDERED) && !(wq->flags & __WQ_DYNAMIC))
continue; continue;
ctx = apply_wqattrs_prepare(wq, wq->unbound_attrs); ctx = apply_wqattrs_prepare(wq, wq->unbound_attrs);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册