diff --git a/doc/internals/api/scheduler.txt b/doc/internals/api/scheduler.txt index efdb34f40..2ff149bbe 100644 --- a/doc/internals/api/scheduler.txt +++ b/doc/internals/api/scheduler.txt @@ -272,6 +272,18 @@ application, both for tasks and tasklets: sense to reset this flag from the ->process() function itself. + - TASK_RT when set, indicates that the task has real-time + constraints (this is ignored for tasklets). Such a task + will bypass the priority ordering of the run queue in + order to guarantee a wakeup time as close as possible to + the scheduled one even under load. Only one such task + may be executed per round so this must be restricted to + a few timing-critical tasks only (those for which a one + millisecond skew is not acceptable). Such tasks are not + meant to be woken up by other threads than the one they + are supposed to run on, otherwise(their constraints may + not be honored. + - TASK_HEAVY when set, indicates that this task does so heavy processing that it will become mandatory to give back control to I/Os otherwise big latencies might occur. It diff --git a/include/haproxy/task-t.h b/include/haproxy/task-t.h index 787409f26..e4fa6654b 100644 --- a/include/haproxy/task-t.h +++ b/include/haproxy/task-t.h @@ -37,7 +37,7 @@ #define TASK_RUNNING 0x00000001 /* the task is currently running */ /* unused 0x00000002 */ #define TASK_QUEUED 0x00000004 /* The task has been (re-)added to the run queue */ -/* unused 0x00000008 */ +#define TASK_RT 0x00000008 /* This task always skips the priority queue */ #define TASK_SELF_WAKING 0x00000010 /* task/tasklet found waking itself */ #define TASK_KILLED 0x00000020 /* task/tasklet killed, may now be freed */ #define TASK_HEAVY 0x00000080 /* this task/tasklet is extremely heavy */ @@ -65,7 +65,7 @@ /* unused: 0x400000..0x80000000 */ /* These flags are persistent across scheduler calls */ -#define TASK_PERSISTENT (TASK_SELF_WAKING | TASK_KILLED | \ +#define TASK_PERSISTENT (TASK_SELF_WAKING | TASK_KILLED | TASK_RT | \ TASK_HEAVY | TASK_F_TASKLET | TASK_F_USR1 | \ TASK_F_WANTS_TIME) diff --git a/src/task.c b/src/task.c index f264e2644..1192ef2ef 100644 --- a/src/task.c +++ b/src/task.c @@ -242,6 +242,15 @@ void __task_wakeup(struct task *t) BUG_ON(t->tid == -1); + if (unlikely(_HA_ATOMIC_LOAD(&t->state) & TASK_RT)) { + /* real-time tasks must be super rare; they are woken up as tasklets. */ + if (thr < 0 || thr == tid) + __tasklet_wakeup_here((struct tasklet *)t); + else + __tasklet_wakeup_on((struct tasklet *)t, thr); + return; + } + #ifdef USE_THREAD if (thr != tid) { root = &ha_thread_ctx[thr].rqueue_shared;