diff --git a/include/proto/task.h b/include/proto/task.h index ca963a1d3..53119b9d0 100644 --- a/include/proto/task.h +++ b/include/proto/task.h @@ -245,10 +245,16 @@ static inline void tasklet_wakeup(struct tasklet *tl) if (likely(tl->tid < 0)) { /* this tasklet runs on the caller thread */ if (LIST_ISEMPTY(&tl->list)) { - if (tl->state & TASK_RUNNING) + if (tl->state & TASK_SELF_WAKING) { LIST_ADDQ(&task_per_thread[tid].tasklets[TL_BULK], &tl->list); - else + } + else if (tl->state & TASK_RUNNING) { + _HA_ATOMIC_OR(&tl->state, TASK_SELF_WAKING); + LIST_ADDQ(&task_per_thread[tid].tasklets[TL_BULK], &tl->list); + } + else { LIST_ADDQ(&task_per_thread[tid].tasklets[TL_URGENT], &tl->list); + } _HA_ATOMIC_ADD(&tasks_run_queue, 1); } } else { diff --git a/include/types/task.h b/include/types/task.h index 5f7ae61e8..6ca97671f 100644 --- a/include/types/task.h +++ b/include/types/task.h @@ -36,6 +36,7 @@ #define TASK_QUEUED 0x0004 /* The task has been (re-)added to the run queue */ #define TASK_SHARED_WQ 0x0008 /* The task's expiration may be updated by other * threads, must be set before first queue/wakeup */ +#define TASK_SELF_WAKING 0x0010 /* task/tasklet found waking itself */ #define TASK_WOKEN_INIT 0x0100 /* woken up for initialisation purposes */ #define TASK_WOKEN_TIMER 0x0200 /* woken up because of expired timer */ diff --git a/src/task.c b/src/task.c index 3eaa9b4f6..f1f36a914 100644 --- a/src/task.c +++ b/src/task.c @@ -329,7 +329,7 @@ static int run_tasks_from_list(struct list *list, int max) while (done < max && !LIST_ISEMPTY(list)) { t = (struct task *)LIST_ELEM(list->n, struct tasklet *, list); - state = (t->state & TASK_SHARED_WQ) | TASK_RUNNING; + state = (t->state & (TASK_SHARED_WQ|TASK_SELF_WAKING)) | TASK_RUNNING; state = _HA_ATOMIC_XCHG(&t->state, state); __ha_barrier_atomic_store(); __tasklet_remove_from_tasklet_list((struct tasklet *)t);