diff options
| author | Tejun Heo <tj@kernel.org> | 2026-09-01 11:09:28 -1000 |
|---|---|---|
| committer | Tejun Heo <tj@kernel.org> | 2026-09-08 07:31:23 -1000 |
| commit | 31e33de1f4e159c7c6c44001fbd3398d53b0311d (patch) | |
| tree | 0c729485dd6ec6c30528d5786e2e33eac6175e47 | |
| parent | 84a42d3829f0088967411106b81e942a67d0b53c (diff) | |
| download | linux-next-31e33de1f4e159c7c6c44001fbd3398d53b0311d.tar.gz linux-next-31e33de1f4e159c7c6c44001fbd3398d53b0311d.zip | |
workqueue: Maintain pwq->total_in_flight
pwq_busy() scans all of pwq->nr_in_flight[] to tell whether anything is in
flight. Maintain the sum in pwq->total_in_flight, which fits in existing
padding, and test that instead.
Signed-off-by: Tejun Heo <tj@kernel.org>
| -rw-r--r-- | kernel/workqueue.c | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 298f22c4caad..322de4f74e2f 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -275,6 +275,7 @@ struct pool_workqueue { int work_color; /* L: current color */ int flush_color; /* L: flushing color */ int refcnt; /* L: reference count */ + int total_in_flight; /* L: sum of nr_in_flight[] */ int nr_in_flight[WORK_NR_COLORS]; /* L: nr of in_flight works */ bool plugged; /* L: execution suspended */ @@ -2090,6 +2091,22 @@ static void pwq_dec_nr_active(struct pool_workqueue *pwq) } /** + * pwq_inc_nr_in_flight - increment pwq's nr_in_flight + * @pwq: pwq of interest + * @work_color: color of the work item being queued + * + * A work item or a barrier with @work_color is being queued to @pwq. + * + * CONTEXT: + * raw_spin_lock_irq(pool->lock). + */ +static void pwq_inc_nr_in_flight(struct pool_workqueue *pwq, int work_color) +{ + pwq->nr_in_flight[work_color]++; + pwq->total_in_flight++; +} + +/** * pwq_dec_nr_in_flight - decrement pwq's nr_in_flight * @pwq: pwq of interest * @work_data: work_data of work which left the queue @@ -2113,6 +2130,7 @@ static void pwq_dec_nr_in_flight(struct pool_workqueue *pwq, unsigned long work_ pwq_dec_nr_active(pwq); pwq->nr_in_flight[color]--; + pwq->total_in_flight--; /* is flush in progress and are we at the flushing tip? */ if (likely(pwq->flush_color != color)) @@ -2462,7 +2480,7 @@ retry: if (WARN_ON(!list_empty(&work->entry))) goto out; - pwq->nr_in_flight[pwq->work_color]++; + pwq_inc_nr_in_flight(pwq, pwq->work_color); work_flags = work_color_to_flags(pwq->work_color); /* @@ -4062,7 +4080,7 @@ static void insert_wq_barrier(struct pool_workqueue *pwq, __set_bit(WORK_STRUCT_LINKED_BIT, bits); } - pwq->nr_in_flight[work_color]++; + pwq_inc_nr_in_flight(pwq, work_color); work_flags |= work_color_to_flags(work_color); insert_work(pwq, &barr->work, head, work_flags); @@ -6129,11 +6147,8 @@ EXPORT_SYMBOL_GPL(alloc_workqueue_lockdep_map); static bool pwq_busy(struct pool_workqueue *pwq) { - int i; - - for (i = 0; i < WORK_NR_COLORS; i++) - if (pwq->nr_in_flight[i]) - return true; + if (pwq->total_in_flight) + return true; if ((pwq != rcu_access_pointer(pwq->wq->dfl_pwq)) && (pwq->refcnt > 1)) return true; |
