diff --git a/libs/libc/wqueue/work_queue.c b/libs/libc/wqueue/work_queue.c index f3d94cb8949..c80e02e677e 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 c03c7b06fe1..3d84dd2d3ed 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 7628670b037..c6ecb95883f 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; } /****************************************************************************