]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: sched: do not punish self-waking tasklets if TASK_WOKEN_ANY
authorWilly Tarreau <wtarreau@haproxy.com>
Sat, 21 Mar 2026 14:58:59 +0000 (14:58 +0000)
committerWilly Tarreau <w@1wt.eu>
Mon, 23 Mar 2026 05:57:12 +0000 (06:57 +0100)
Self-waking tasklets are currently punished and go to the BULK list.
However it's a problem with muxes or the stick-table purge that just
yield and wake themselves up to limit the latency they cause to the
rest of the process, because by doing so to help others, they punish
themselves. Let's check if any TASK_WOKEN_ANY flag is present on
the tasklet and stop sending tasks presenting such a flag to TL_BULK.
Since tasklet_wakeup() by default passes TASK_WOKEN_OTHER, it means
that such tasklets will no longer be punished. However, tasks which
only want a best-effort wakeup can simply pass 0.

It's worth noting that a comparison was made between going into
TL_BULK at all and only setting the TASK_SELF_WAKING flag, and
it shows that the average latencies are ~10% better when entirely
avoiding TL_BULK in this case.

src/task.c

index 4761e7b7adce0ee8ac6f90fb02a53226f4ceff47..7d0a1db9c6ac33e29022b7a5087ef0c179167b2f 100644 (file)
@@ -147,7 +147,7 @@ void __tasklet_wakeup_on(struct tasklet *tl, int thr)
                        LIST_APPEND(&th_ctx->tasklets[TL_BULK], &tl->list);
                        th_ctx->tl_class_mask |= 1 << TL_BULK;
                }
-               else if ((struct task *)tl == th_ctx->current) {
+               else if ((struct task *)tl == th_ctx->current && !(tl->state & TASK_WOKEN_ANY)) {
                        LIST_APPEND(&th_ctx->tasklets[TL_BULK], &tl->list);
                        th_ctx->tl_class_mask |= 1 << TL_BULK;
                }
@@ -185,7 +185,7 @@ struct list *__tasklet_wakeup_after(struct list *head, struct tasklet *tl)
                        LIST_INSERT(&th_ctx->tasklets[TL_BULK], &tl->list);
                        th_ctx->tl_class_mask |= 1 << TL_BULK;
                }
-               else if ((struct task *)tl == th_ctx->current) {
+               else if ((struct task *)tl == th_ctx->current && !(tl->state & TASK_WOKEN_ANY)) {
                        LIST_INSERT(&th_ctx->tasklets[TL_BULK], &tl->list);
                        th_ctx->tl_class_mask |= 1 << TL_BULK;
                }