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:
parent
16df0dba4d
commit
7dabc6ff2f
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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().
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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().
|
||||
|
Loading…
Reference in New Issue
Block a user