sched/wdog: Change sq to list

Before wdog module refactoring, we change the sq to double linked list.

Signed-off-by: ligd <liguiding1@xiaomi.com>
This commit is contained in:
ligd 2024-06-11 23:23:44 +08:00 committed by Xiang Xiao
parent 16df0dba4d
commit 7dabc6ff2f
7 changed files with 69 additions and 104 deletions

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -24,7 +24,7 @@
#include <nuttx/config.h>
#include <nuttx/queue.h>
#include <nuttx/list.h>
#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().

View File

@ -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 */

View File

@ -34,11 +34,16 @@
#include <nuttx/clock.h>
#include <nuttx/queue.h>
#include <nuttx/wdog.h>
#include <nuttx/list.h>
/****************************************************************************
* 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().