From: Willy Tarreau Date: Tue, 6 Sep 2022 14:31:30 +0000 (+0200) Subject: BUG/MINOR: task: make task_instant_wakeup() work on a task not a tasklet X-Git-Tag: v2.7-dev6~90 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0fae3a0360314285a17153cac76413184143ee74;p=thirdparty%2Fhaproxy.git BUG/MINOR: task: make task_instant_wakeup() work on a task not a tasklet There's a subtle (harmless) bug in task_instant_wakeup(). As it uses some tasklet code instead of some task code, the debug part also acts on the tasklet equivalent, and the call_date is only set when DEBUG_TASK is set instead of inconditionally like with tasks. As such, without this debugging macro, call dates are not updated for tasks woken this way. There isn't any impact yet because this function was introduced in 2.6 to solve certain classes of issues and is not used yet, and in the worst case it would only affect the reported latency time. This may be backported to 2.6 in case a future fix would depend on it but currently will not fix existing code. --- diff --git a/include/haproxy/task.h b/include/haproxy/task.h index f2ff7e7cbe..7a58e3ed9c 100644 --- a/include/haproxy/task.h +++ b/include/haproxy/task.h @@ -384,7 +384,6 @@ static inline void _tasklet_wakeup_on(struct tasklet *tl, int thr, const char *f #define task_instant_wakeup(t, f) _task_instant_wakeup(t, f, __FILE__, __LINE__) static inline void _task_instant_wakeup(struct task *t, unsigned int f, const char *file, int line) { - struct tasklet *tl = (struct tasklet *)t; int thr = t->tid; unsigned int state; @@ -392,7 +391,7 @@ static inline void _task_instant_wakeup(struct task *t, unsigned int f, const ch thr = tid; /* first, let's update the task's state with the wakeup condition */ - state = _HA_ATOMIC_OR_FETCH(&tl->state, f); + state = _HA_ATOMIC_OR_FETCH(&t->state, f); /* next we need to make sure the task was not/will not be added to the * run queue because the tasklet list's mt_list uses the same storage @@ -402,21 +401,21 @@ static inline void _task_instant_wakeup(struct task *t, unsigned int f, const ch /* do nothing if someone else already added it */ if (state & (TASK_QUEUED|TASK_RUNNING)) return; - } while (!_HA_ATOMIC_CAS(&tl->state, &state, state | TASK_QUEUED)); + } while (!_HA_ATOMIC_CAS(&t->state, &state, state | TASK_QUEUED)); BUG_ON_HOT(task_in_rq(t)); /* at this point we're the first ones to add this task to the list */ #ifdef DEBUG_TASK - if ((unsigned int)tl->debug.caller_idx > 1) + if ((unsigned int)t->debug.caller_idx > 1) ABORT_NOW(); - tl->debug.caller_idx = !tl->debug.caller_idx; - tl->debug.caller_file[tl->debug.caller_idx] = file; - tl->debug.caller_line[tl->debug.caller_idx] = line; - if (_HA_ATOMIC_LOAD(&th_ctx->flags) & TH_FL_TASK_PROFILING) - tl->call_date = now_mono_time(); + t->debug.caller_idx = !t->debug.caller_idx; + t->debug.caller_file[t->debug.caller_idx] = file; + t->debug.caller_line[t->debug.caller_idx] = line; #endif - __tasklet_wakeup_on(tl, thr); + if (_HA_ATOMIC_LOAD(&th_ctx->flags) & TH_FL_TASK_PROFILING) + t->call_date = now_mono_time(); + __tasklet_wakeup_on((struct tasklet *)t, thr); } /* schedules tasklet to run immediately after the current one is done