This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit fb592064cb22ef7f1c30a457912e6a30546d9892 Author: ouyangxiangzhen <ouyangxiangz...@xiaomi.com> AuthorDate: Tue May 6 17:49:43 2025 +0800 sched: Improved the wdog and wq list insertion. For the watchdog list and the workqueue list, we wonder whether the list head has changed after the insertion. In the original implementation, we have to access the list->next field and compare the result to the currently inserted node. In this commit, we mark the list head before the insertion and comparing the current traversed node with the list head we marked, which can avoid accessing the list->next and is more cache-friendly. Signed-off-by: ouyangxiangzhen <ouyangxiangz...@xiaomi.com> --- libs/libc/wqueue/work_queue.c | 5 ++++- sched/wdog/wd_start.c | 18 ++++++++++++------ sched/wqueue/wqueue.h | 13 +++++++++++-- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/libs/libc/wqueue/work_queue.c b/libs/libc/wqueue/work_queue.c index f3d94cb894..c80e02e677 100644 --- a/libs/libc/wqueue/work_queue.c +++ b/libs/libc/wqueue/work_queue.c @@ -77,6 +77,7 @@ static int work_qqueue(FAR struct usr_wqueue_s *wqueue, FAR void *arg, clock_t delay) { FAR struct work_s *curr; + FAR struct work_s *head; int semcount; /* Get exclusive access to the work queue */ @@ -101,6 +102,8 @@ static int work_qqueue(FAR struct usr_wqueue_s *wqueue, /* Insert the work into the wait queue sorted by the expired time. */ + head = list_first_entry(&wqueue->q, struct work_s, node); + list_for_every_entry(&wqueue->q, curr, struct work_s, node) { if (!clock_compare(curr->qtime, work->qtime)) @@ -122,7 +125,7 @@ static int work_qqueue(FAR struct usr_wqueue_s *wqueue, * We should wake up the worker thread. */ - if (list_is_head(&wqueue->q, &work->node)) + if (curr == head) { nxsem_get_value(&wqueue->wake, &semcount); if (semcount < 1) diff --git a/sched/wdog/wd_start.c b/sched/wdog/wd_start.c index c03c7b06fe..3d84dd2d3e 100644 --- a/sched/wdog/wd_start.c +++ b/sched/wdog/wd_start.c @@ -226,18 +226,21 @@ static inline_function void wd_expiration(clock_t ticks) * wdog and wdentry is not NULL. * * Returned Value: - * None. + * Whether the head of the watchdog list has changed. * ****************************************************************************/ static inline_function -void wd_insert(FAR struct wdog_s *wdog, clock_t expired, +bool wd_insert(FAR struct wdog_s *wdog, clock_t expired, wdentry_t wdentry, wdparm_t arg) { FAR struct wdog_s *curr; + FAR struct wdog_s *head; /* Traverse the watchdog list */ + head = list_first_entry(&g_wdactivelist, struct wdog_s, node); + list_for_every_entry(&g_wdactivelist, curr, struct wdog_s, node) { /* Until curr->expired has not timed out relative to expired */ @@ -261,6 +264,10 @@ void wd_insert(FAR struct wdog_s *wdog, clock_t expired, up_getpicbase(&wdog->picbase); wdog->arg = arg; wdog->expired = expired; + + /* Return whether the head of the watchdog list has changed. */ + + return head == curr; } /**************************************************************************** @@ -287,7 +294,7 @@ void wd_insert(FAR struct wdog_s *wdog, clock_t expired, * * Input Parameters: * wdog - Watchdog ID - * ticks - Absoulute time in clock ticks + * ticks - Absolute time in clock ticks * wdentry - Function to call on timeout * arg - Parameter to pass to wdentry. * @@ -349,10 +356,9 @@ int wd_start_abstick(FAR struct wdog_s *wdog, clock_t ticks, wdog->func = NULL; } - wd_insert(wdog, ticks, wdentry, arg); + reassess |= wd_insert(wdog, ticks, wdentry, arg); - if (!g_wdtimernested && - (reassess || list_is_head(&g_wdactivelist, &wdog->node))) + if (!g_wdtimernested && reassess) { /* Resume the interval timer that will generate the next * interval event. If the timer at the head of the list changed, diff --git a/sched/wqueue/wqueue.h b/sched/wqueue/wqueue.h index 7628670b03..c6ecb95883 100644 --- a/sched/wqueue/wqueue.h +++ b/sched/wqueue/wqueue.h @@ -168,12 +168,15 @@ static inline_function bool work_insert_pending(FAR struct kwork_wqueue_s *wqueue, FAR struct work_s *work) { - struct work_s *curr; + FAR struct work_s *curr; + FAR struct work_s *head; DEBUGASSERT(wqueue != NULL && work != NULL); /* Insert the work into the wait queue sorted by the expired time. */ + head = list_first_entry(&wqueue->pending, struct work_s, node); + list_for_every_entry(&wqueue->pending, curr, struct work_s, node) { if (!clock_compare(curr->qtime, work->qtime)) @@ -191,7 +194,13 @@ bool work_insert_pending(FAR struct kwork_wqueue_s *wqueue, list_add_before(&curr->node, &work->node); - return list_is_head(&wqueue->pending, &work->node); + /* Return list_is_head(&wqueue->pending, &work->node) + * However, there is fast path that we can check if `curr` + * is the `head` we cached before, which is cache-friendly and + * can reduce one memory access. + */ + + return curr == head; } /****************************************************************************