summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorLai Jiangshan <jiangshan.ljs@antgroup.com>2025-12-08 21:25:19 +0800
committerTejun Heo <tj@kernel.org>2025-12-08 09:18:02 -1000
commit51cd2d2decf365a248ddc304b7aa6f0cadc748c3 (patch)
tree6c81b3485285c390b1b2880479fb46424faabc7a /kernel
parente5a30c303b07a4d6083e0f7f051b53add6d93c5d (diff)
workqueue: Process extra works in rescuer on memory pressure
Make the rescuer process more work on the last pwq when there are no more to rescue for the whole workqueue to help the regular workers in case it is a temporary memory pressure relief and to reduce relapse. Signed-off-by: Lai Jiangshan <jiangshan.ljs@antgroup.com> Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/workqueue.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 7f9225936cd9..64fe81f30e85 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -3461,10 +3461,37 @@ static bool assign_rescuer_work(struct pool_workqueue *pwq, struct worker *rescu
struct work_struct *cursor = &pwq->mayday_cursor;
struct work_struct *work, *n;
- /* need rescue? */
- if (!pwq->nr_active || !need_to_create_worker(pool))
+ /* have work items to rescue? */
+ if (!pwq->nr_active)
return false;
+ /* need rescue? */
+ if (!need_to_create_worker(pool)) {
+ /*
+ * The pool has idle workers and doesn't need the rescuer, so it
+ * could simply return false here.
+ *
+ * However, the memory pressure might not be fully relieved.
+ * In PERCPU pool with concurrency enabled, having idle workers
+ * does not necessarily mean memory pressure is gone; it may
+ * simply mean regular workers have woken up, completed their
+ * work, and gone idle again due to concurrency limits.
+ *
+ * In this case, those working workers may later sleep again,
+ * the pool may run out of idle workers, and it will have to
+ * allocate new ones and wait for the timer to send mayday,
+ * causing unnecessary delay - especially if memory pressure
+ * was never resolved throughout.
+ *
+ * Do more work if memory pressure is still on to reduce
+ * relapse, using (pool->flags & POOL_MANAGER_ACTIVE), though
+ * not precisely, unless there are other PWQs needing help.
+ */
+ if (!(pool->flags & POOL_MANAGER_ACTIVE) ||
+ !list_empty(&pwq->wq->maydays))
+ return false;
+ }
+
/* search from the start or cursor if available */
if (list_empty(&cursor->entry))
work = list_first_entry(&pool->worklist, struct work_struct, entry);