From 7dabc6ff2fa61abba19c53106c4b61b12ebf3d6f Mon Sep 17 00:00:00 2001 From: ligd Date: Tue, 11 Jun 2024 23:23:44 +0800 Subject: [PATCH] sched/wdog: Change sq to list Before wdog module refactoring, we change the sq to double linked list. Signed-off-by: ligd --- include/nuttx/list.h | 2 + include/nuttx/wdog.h | 10 ++++- sched/wdog/wd_cancel.c | 56 +++++++----------------- sched/wdog/wd_gettime.c | 4 +- sched/wdog/wd_initialize.c | 4 +- sched/wdog/wd_start.c | 90 ++++++++++++++------------------------ sched/wdog/wdog.h | 7 ++- 7 files changed, 69 insertions(+), 104 deletions(-) diff --git a/include/nuttx/list.h b/include/nuttx/list.h index cadbccc335..80394ac351 100644 --- a/include/nuttx/list.h +++ b/include/nuttx/list.h @@ -90,6 +90,8 @@ } \ while (0) +#define list_is_head(list, item) ((list)->next == (item)) +#define list_is_tail(list, item) ((list)->prev == (item)) #define list_peek_head(list) ((list)->next != (list) ? (list)->next : NULL) #define list_peek_tail(list) ((list)->prev != (list) ? (list)->prev : NULL) diff --git a/include/nuttx/wdog.h b/include/nuttx/wdog.h index f69888f5fd..74ec26d043 100644 --- a/include/nuttx/wdog.h +++ b/include/nuttx/wdog.h @@ -60,6 +60,14 @@ typedef uint32_t wdparm_t; typedef CODE void (*wdentry_t)(wdparm_t arg); +/* Avoid the inclusion of nuttx/list.h */ + +struct wdlist_node +{ + FAR struct wdlist_node *prev; + FAR struct wdlist_node *next; +}; + /* This is the internal representation of the watchdog timer structure. * Notice !!! * Carefully with the struct wdog_s order, you may not directly modify @@ -69,7 +77,7 @@ typedef CODE void (*wdentry_t)(wdparm_t arg); struct wdog_s { - FAR struct wdog_s *next; /* Support for singly linked lists. */ + struct wdlist_node node; /* Supports a doubly linked list */ wdparm_t arg; /* Callback argument */ wdentry_t func; /* Function to execute when delay expires */ #ifdef CONFIG_PIC diff --git a/sched/wdog/wd_cancel.c b/sched/wdog/wd_cancel.c index ba1c8c1a3f..5a5a0555b2 100644 --- a/sched/wdog/wd_cancel.c +++ b/sched/wdog/wd_cancel.c @@ -57,8 +57,6 @@ int wd_cancel(FAR struct wdog_s *wdog) { - FAR struct wdog_s *curr; - FAR struct wdog_s *prev; irqstate_t flags; int ret = -EINVAL; @@ -74,60 +72,36 @@ int wd_cancel(FAR struct wdog_s *wdog) if (wdog != NULL && WDOG_ISACTIVE(wdog)) { - /* Search the g_wdactivelist for the target FCB. We can't use sq_rem - * to do this because there are additional operations that need to be - * done. - */ - - prev = NULL; - curr = (FAR struct wdog_s *)g_wdactivelist.head; - - while ((curr) && (curr != wdog)) - { - prev = curr; - curr = curr->next; - } - - /* Check if the watchdog was found in the list. If not, then an OS - * error has occurred because the watchdog is marked active! - */ - - DEBUGASSERT(curr); + bool head = list_is_head(&g_wdactivelist, &wdog->node); + FAR struct wdog_s *next = list_next_entry(wdog, struct wdog_s, node); /* If there is a watchdog in the timer queue after the one that * is being canceled, then it inherits the remaining ticks. */ - if (curr->next) + if (next) { - curr->next->lag += curr->lag; + next->lag += wdog->lag; } /* Now, remove the watchdog from the timer queue */ - if (prev) - { - /* Remove the watchdog from mid- or end-of-queue */ - - sq_remafter((FAR sq_entry_t *)prev, &g_wdactivelist); - } - else - { - /* Remove the watchdog at the head of the queue */ - - sq_remfirst(&g_wdactivelist); - - /* Reassess the interval timer that will generate the next - * interval event. - */ - - nxsched_reassess_timer(); - } + list_delete(&wdog->node); /* Mark the watchdog inactive */ wdog->func = NULL; + if (head) + { + /* If the watchdog is at the head of the timer queue, then + * we will need to re-adjust the interval timer that will + * generate the next interval event. + */ + + nxsched_reassess_timer(); + } + /* Return success */ ret = OK; diff --git a/sched/wdog/wd_gettime.c b/sched/wdog/wd_gettime.c index 9947293ac7..0803f49454 100644 --- a/sched/wdog/wd_gettime.c +++ b/sched/wdog/wd_gettime.c @@ -66,9 +66,7 @@ sclock_t wd_gettime(FAR struct wdog_s *wdog) FAR struct wdog_s *curr; sclock_t delay = 0; - for (curr = (FAR struct wdog_s *)g_wdactivelist.head; - curr != NULL; - curr = curr->next) + list_for_every_entry(&g_wdactivelist, curr, struct wdog_s, node) { delay += curr->lag; if (curr == wdog) diff --git a/sched/wdog/wd_initialize.c b/sched/wdog/wd_initialize.c index 8fe2aeef98..92bf6567b5 100644 --- a/sched/wdog/wd_initialize.c +++ b/sched/wdog/wd_initialize.c @@ -24,7 +24,7 @@ #include -#include +#include #include "wdog/wdog.h" @@ -37,7 +37,7 @@ * this linked list are removed and the function is called. */ -sq_queue_t g_wdactivelist; +struct list_node g_wdactivelist = LIST_INITIAL_VALUE(g_wdactivelist); /* This is wdog tickbase, for wd_gettime() may called many times * between 2 times of wd_timer(), we use it to update wd_gettime(). diff --git a/sched/wdog/wd_start.c b/sched/wdog/wd_start.c index 3a0fd5a831..361c9d0e71 100644 --- a/sched/wdog/wd_start.c +++ b/sched/wdog/wd_start.c @@ -91,26 +91,32 @@ static inline void wd_expiration(void) { FAR struct wdog_s *wdog; + FAR struct wdog_s *next; wdentry_t func; /* Process the watchdog at the head of the list as well as any * other watchdogs that became ready to run at this time */ - while (g_wdactivelist.head && - ((FAR struct wdog_s *)g_wdactivelist.head)->lag <= 0) + list_for_every_entry_safe(&g_wdactivelist, wdog, + next, struct wdog_s, node) { + if (wdog->lag > 0) + { + break; + } + /* Remove the watchdog from the head of the list */ - wdog = (FAR struct wdog_s *)sq_remfirst(&g_wdactivelist); + list_delete(&wdog->node); /* If there is another watchdog behind this one, update its * its lag (this shouldn't be necessary). */ - if (g_wdactivelist.head) + if (!list_is_empty(&g_wdactivelist)) { - ((FAR struct wdog_s *)g_wdactivelist.head)->lag += wdog->lag; + next->lag += wdog->lag; } /* Indicate that the watchdog is no longer active. */ @@ -169,10 +175,8 @@ int wd_start(FAR struct wdog_s *wdog, sclock_t delay, wdentry_t wdentry, wdparm_t arg) { FAR struct wdog_s *curr; - FAR struct wdog_s *prev; - FAR struct wdog_s *next; - sclock_t now; irqstate_t flags; + sclock_t now; /* Verify the wdog and setup parameters */ @@ -235,7 +239,7 @@ int wd_start(FAR struct wdog_s *wdog, sclock_t delay, /* Do the easy case first -- when the watchdog timer queue is empty. */ - if (g_wdactivelist.head == NULL) + if (list_is_empty(&g_wdactivelist)) { #ifdef CONFIG_SCHED_TICKLESS /* Update clock tickbase */ @@ -245,7 +249,7 @@ int wd_start(FAR struct wdog_s *wdog, sclock_t delay, /* Add the watchdog to the head == tail of the queue. */ - sq_addlast((FAR sq_entry_t *)wdog, &g_wdactivelist); + list_add_tail(&g_wdactivelist, &wdog->node); } /* There are other active watchdogs in the timer queue */ @@ -253,23 +257,16 @@ int wd_start(FAR struct wdog_s *wdog, sclock_t delay, else { now = 0; - prev = curr = (FAR struct wdog_s *)g_wdactivelist.head; - - /* Advance to positive time */ - - while ((now += curr->lag) < 0 && curr->next) - { - prev = curr; - curr = curr->next; - } /* Advance past shorter delays */ - while (now <= delay && curr->next) + list_for_every_entry(&g_wdactivelist, curr, struct wdog_s, node) { - prev = curr; - curr = curr->next; now += curr->lag; + if (now > delay) + { + break; + } } /* Check if the new wdog must be inserted before the curr. */ @@ -286,19 +283,7 @@ int wd_start(FAR struct wdog_s *wdog, sclock_t delay, /* Insert the new watchdog in the list */ - if (curr == (FAR struct wdog_s *)g_wdactivelist.head) - { - /* Insert the watchdog at the head of the list */ - - sq_addfirst((FAR sq_entry_t *)wdog, &g_wdactivelist); - } - else - { - /* Insert the watchdog in mid- or end-of-queue */ - - sq_addafter((FAR sq_entry_t *)prev, (FAR sq_entry_t *)wdog, - &g_wdactivelist); - } + list_add_before(&curr->node, &wdog->node); } /* The new watchdog delay time is greater than the curr delay time, @@ -309,17 +294,8 @@ int wd_start(FAR struct wdog_s *wdog, sclock_t delay, else { delay -= now; - if (!curr->next) - { - sq_addlast((FAR sq_entry_t *)wdog, &g_wdactivelist); - } - else - { - next = curr->next; - next->lag -= delay; - sq_addafter((FAR sq_entry_t *)curr, (FAR sq_entry_t *)wdog, - &g_wdactivelist); - } + + list_add_tail(&g_wdactivelist, &wdog->node); } } @@ -379,19 +355,21 @@ unsigned int wd_timer(int ticks, bool noswitches) /* Check if there are any active watchdogs to process */ - wdog = (FAR struct wdog_s *)g_wdactivelist.head; - while (wdog != NULL && ticks > 0) + list_for_every_entry(&g_wdactivelist, wdog, struct wdog_s, node) { + if (ticks <= 0) + { + break; + } + /* Decrement the lag for this watchdog. */ decr = MIN(wdog->lag, ticks); /* There are. Decrement the lag counter */ - wdog->lag -= decr; - ticks -= decr; - - wdog = wdog->next; + wdog->lag -= decr; + ticks -= decr; } /* Check if the watchdog at the head of the list is ready to run */ @@ -403,8 +381,8 @@ unsigned int wd_timer(int ticks, bool noswitches) /* Return the delay for the next watchdog to expire */ - ret = g_wdactivelist.head ? - MAX(((FAR struct wdog_s *)g_wdactivelist.head)->lag, 1) : 0; + ret = list_is_empty(&g_wdactivelist) ? 0 : + list_first_entry(&g_wdactivelist, struct wdog_s, node)->lag; /* Return the delay for the next watchdog to expire */ @@ -416,11 +394,11 @@ void wd_timer(void) { /* Check if there are any active watchdogs to process */ - if (g_wdactivelist.head) + if (!list_is_empty(&g_wdactivelist)) { /* There are. Decrement the lag counter */ - --(((FAR struct wdog_s *)g_wdactivelist.head)->lag); + --(list_first_entry(&g_wdactivelist, struct wdog_s, node)->lag); /* Check if the watchdog at the head of the list is ready to run */ diff --git a/sched/wdog/wdog.h b/sched/wdog/wdog.h index d4178a09e3..0807c0a5da 100644 --- a/sched/wdog/wdog.h +++ b/sched/wdog/wdog.h @@ -34,11 +34,16 @@ #include #include #include +#include /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +/* Redefine to the standard list */ + +#define list_node wdlist_node + /**************************************************************************** * Name: wd_elapse * @@ -73,7 +78,7 @@ extern "C" * this linked list are removed and the function is called. */ -extern sq_queue_t g_wdactivelist; +extern struct list_node g_wdactivelist; /* This is wdog tickbase, for wd_gettime() may called many times * between 2 times of wd_timer(), we use it to update wd_gettime().