Messages in this thread Patch in this message | | | From | Valentin Schneider <> | Subject | [PATCH v5 3/5] workqueue: Make too_many_workers() return the worker excess | Date | Tue, 22 Nov 2022 19:29:35 +0000 |
| |
Later patches will need the logic implemented within too_many_workers() to get the amount of workers to delete. Rather than duplicate the logic, rework too_many_workers() to return the count of workers to delete - its return value can be used as a boolean value, so no change in behaviour intended.
The function currently returns true when (nr_idle - 2) * MAX_IDLE_WORKERS_RATIO >= nr_busy thus, the desired number of idle workers is expressed by (nr_idle - 2) * MAX_IDLE_WORKERS_RATIO == nr_busy - 1 IOW nr_idle == ((nr_busy - 1) / MAX_IDLE_WORKERS_RATIO) + 2
MAX_IDLE_WORKERS_RATIO being a compile-time power of 2, we can leave that as a division.
While at it, rename too_many_workers() to worker_cull_count().
Signed-off-by: Valentin Schneider <vschneid@redhat.com> --- kernel/workqueue.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 8185a42848c50..4fc8085f3fe17 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -816,14 +816,20 @@ static bool need_to_create_worker(struct worker_pool *pool) return need_more_worker(pool) && !may_start_working(pool); } -/* Do we have too many workers and should some go away? */ -static bool too_many_workers(struct worker_pool *pool) +/* How many idle workers should we get rid of, if any? */ +static unsigned int worker_cull_count(struct worker_pool *pool) { bool managing = pool->flags & POOL_MANAGER_ACTIVE; int nr_idle = pool->nr_idle + managing; /* manager is considered idle */ int nr_busy = pool->nr_workers - nr_idle; - return nr_idle > 2 && (nr_idle - 2) * MAX_IDLE_WORKERS_RATIO >= nr_busy; + lockdep_assert_held(&pool->lock); + + /* + * We keep at least 2 spare idle workers, but overall aim to keep at + * most (1 / MAX_IDLE_WORKERS_RATIO) workers idle. + */ + return max(0, nr_idle - 2 - ((nr_busy - 1) / MAX_IDLE_WORKERS_RATIO)); } /* @@ -1806,7 +1812,7 @@ static void worker_enter_idle(struct worker *worker) /* idle_list is LIFO */ list_add(&worker->entry, &pool->idle_list); - if (too_many_workers(pool) && !timer_pending(&pool->idle_timer)) + if (worker_cull_count(pool) && !timer_pending(&pool->idle_timer)) mod_timer(&pool->idle_timer, jiffies + IDLE_WORKER_TIMEOUT); /* Sanity check nr_running. */ @@ -2025,7 +2031,7 @@ static void idle_worker_timeout(struct timer_list *t) raw_spin_lock_irq(&pool->lock); - while (too_many_workers(pool)) { + while (worker_cull_count(pool)) { struct worker *worker; unsigned long expires; -- 2.31.1
| |