diff --git a/include/haproxy/task-t.h b/include/haproxy/task-t.h index a6807a5dd2..2a914c6b21 100644 --- a/include/haproxy/task-t.h +++ b/include/haproxy/task-t.h @@ -60,11 +60,13 @@ #define TASK_F_USR1 0x00010000 /* preserved user flag 1, application-specific, def:0 */ #define TASK_F_UEVT1 0x00020000 /* one-shot user event type 1, application specific, def:0 */ #define TASK_F_UEVT2 0x00040000 /* one-shot user event type 2, application specific, def:0 */ -/* unused: 0x80000..0x80000000 */ +#define TASK_F_WANTS_TIME 0x00080000 /* task/tasklet wants th_ctx->sched_call_date to be set */ +/* unused: 0x100000..0x80000000 */ /* These flags are persistent across scheduler calls */ #define TASK_PERSISTENT (TASK_SELF_WAKING | TASK_KILLED | \ - TASK_HEAVY | TASK_F_TASKLET | TASK_F_USR1) + TASK_HEAVY | TASK_F_TASKLET | TASK_F_USR1 | \ + TASK_F_WANTS_TIME) /* This function is used to report state in debugging tools. Please reflect * below any single-bit flag addition above in the same order via the diff --git a/include/haproxy/task.h b/include/haproxy/task.h index 1c9c45f496..dbbb0a8b51 100644 --- a/include/haproxy/task.h +++ b/include/haproxy/task.h @@ -193,6 +193,12 @@ static inline int thread_has_tasks(void) (int)!MT_LIST_ISEMPTY(&th_ctx->shared_tasklet_list)); } +/* returns the most recent known date of the task's call from the scheduler */ +static inline uint64_t task_mono_time(void) +{ + return th_ctx->sched_call_date; +} + /* puts the task in run queue with reason flags , and returns */ /* This will put the task in the local runqueue if the task is only runnable * by the current thread, in the global runqueue otherwies. With DEBUG_TASK, diff --git a/src/task.c b/src/task.c index 1ab5212018..9b6beb8ad7 100644 --- a/src/task.c +++ b/src/task.c @@ -567,17 +567,24 @@ unsigned int run_tasks_from_lists(unsigned int budgets[]) t->calls++; th_ctx->sched_wake_date = t->wake_date; - if (th_ctx->sched_wake_date) { - uint32_t now_ns = now_mono_time(); - uint32_t lat = now_ns - th_ctx->sched_wake_date; + if (th_ctx->sched_wake_date || (t->state & TASK_F_WANTS_TIME)) { + /* take the most accurate clock we have, either + * mono_time() or last now_ns (monotonic but only + * incremented once per poll loop). + */ + th_ctx->sched_call_date = now_mono_time(); + if (unlikely(!th_ctx->sched_call_date)) + th_ctx->sched_call_date = now_ns; + } + if (th_ctx->sched_wake_date) { t->wake_date = 0; - th_ctx->sched_call_date = now_ns; profile_entry = sched_activity_entry(sched_activity, t->process, t->caller); th_ctx->sched_profile_entry = profile_entry; - HA_ATOMIC_ADD(&profile_entry->lat_time, lat); + HA_ATOMIC_ADD(&profile_entry->lat_time, (uint32_t)(th_ctx->sched_call_date - th_ctx->sched_wake_date)); HA_ATOMIC_INC(&profile_entry->calls); } + __ha_barrier_store(); th_ctx->current = t;