lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAJhGHyDaNCoXaK4g4fKg3vfBYuQ7r+e8TT8ObrtT3nBcTeeuMg@mail.gmail.com>
Date: Fri, 19 Jan 2024 15:54:24 +0800
From: Lai Jiangshan <jiangshanlai@...il.com>
To: Tejun Heo <tj@...nel.org>
Cc: linux-kernel@...r.kernel.org, Naohiro.Aota@....com, kernel-team@...a.com
Subject: Re: [PATCH 9/9] workqueue: Implement system-wide nr_active
 enforcement for unbound workqueues

Hello, Tejun

On Sat, Jan 13, 2024 at 8:29 AM Tejun Heo <tj@...nel.org> wrote:
> + */
> +static int wq_node_max_active(struct workqueue_struct *wq, int node)
> +{
> +       int min_active = READ_ONCE(wq->min_active);
> +       int max_active = READ_ONCE(wq->max_active);
> +       int node_max_active;
> +
> +       if (node == NUMA_NO_NODE)
> +               return min_active;
> +
> +       node_max_active = DIV_ROUND_UP(max_active * node_nr_cpus[node],
> +                                      num_online_cpus());

node_nr_cpus[node] and num_online_cpus() are global values, they might
not suitable
for this particular workqueue and might cause skewed proportions.

the cache values:

pwq->pool->attrs->pool_nr_online_cpus =
cpumask_weight_and(pwq->pool->attrs->__pod_cpumask, cpu_online_mask);

wq->wq_nr_online_cpus =
cpumask_weight_and(wq->unbound_attrs->cpumask,  cpu_online_mask);

can be used instead. They can be calculated at creation and cpuhotplug.
pool_nr_online_cpus doesn't contribute to the pool's hash value.

Or the result of wq_node_max_active() can be cached in struct wq_node_nr_active,
see the comment next.

> -static bool pwq_tryinc_nr_active(struct pool_workqueue *pwq)
> +static bool pwq_tryinc_nr_active(struct pool_workqueue *pwq, bool fill)
>  {
>         struct workqueue_struct *wq = pwq->wq;
>         struct worker_pool *pool = pwq->pool;
>         struct wq_node_nr_active *nna = wq_node_nr_active(wq, pool->node);
> -       bool obtained;
> +       bool obtained = false;
> +       int node_max_active;
>
>         lockdep_assert_held(&pool->lock);
>
> -       obtained = pwq->nr_active < READ_ONCE(wq->max_active);
> +       if (!nna) {
> +               /* per-cpu workqueue, pwq->nr_active is sufficient */
> +               obtained = pwq->nr_active < READ_ONCE(wq->max_active);
> +               goto out;
> +       }
> +
> +       /*
> +        * Unbound workqueue uses per-node shared nr_active $nna. If @pwq is
> +        * already waiting on $nna, pwq_dec_nr_active() will maintain the
> +        * concurrency level. Don't jump the line.
> +        *
> +        * We need to ignore the pending test after max_active has increased as
> +        * pwq_dec_nr_active() can only maintain the concurrency level but not
> +        * increase it. This is indicated by @fill.
> +        */
> +       if (!list_empty(&pwq->pending_node) && likely(!fill))
> +               goto out;
> +
> +       node_max_active = wq_node_max_active(wq, pool->node);

It is a hot path for unbound workqueues, I think the result of
wq_node_max_active()
should be cached in struct wq_node_nr_active.

The result be calculated at creation, cpuhotplug, and changing max_active.


>
>  /**
>   * pwq_activate_first_inactive - Activate the first inactive work item on a pwq
>   * @pwq: pool_workqueue of interest
> + * @fill: max_active may have increased, try to increase concurrency level

I think it is also legitimate to increase the concurrency level ASAP
when called from try_to_grab_pending() path.

Thanks
Lai

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ