If we run out of pre-allocated watchdog times, the logic will allocate additional timers from the heap. A reserve of pre-allocated watchdog timers is maintained so that there will always be timers available for interrupt handlers.
This commit is contained in:
parent
e1d29d8718
commit
952d87587f
@ -188,8 +188,23 @@ config PREALLOC_WDOGS
|
||||
int "Number of pre-allocated watchdog timers"
|
||||
default 32
|
||||
---help---
|
||||
The number of pre-allocated watchdog structures. The system manages a
|
||||
pool of preallocated watchdog structures to minimize dynamic allocations
|
||||
The number of pre-allocated watchdog structures. The system manages
|
||||
a pool of preallocated watchdog structures to minimize dynamic
|
||||
allocations. Dynamic allocations will still be made if this pool is
|
||||
exhausted. You will, however, get better performance and memory
|
||||
usage if this value is tuned to minimize such allocations.
|
||||
|
||||
config WDOG_INTRESERVE
|
||||
int "Watchdog structures reserved for interrupt handlers"
|
||||
default 4
|
||||
---help---
|
||||
Watchdog structures may be allocated from normal task and also from
|
||||
interrupt handlers. Interrupt handlers, however, can only use pre-
|
||||
allocated watchdog timer. So, in order to keep normal task
|
||||
allocations from exhausting all watchdog structures, a small number
|
||||
of pre-allocated watchdog timers must be reserved for exclusive use
|
||||
by interrupt handler. This setting determines that number of
|
||||
reserved watchdogs.
|
||||
|
||||
config PREALLOC_TIMERS
|
||||
int "Number of pre-allocated POSIX timers"
|
||||
|
@ -79,7 +79,7 @@
|
||||
* timers may be cancelled from the interrupt level.
|
||||
*
|
||||
* Parameters:
|
||||
* wdid - ID of the watchdog to cancel.
|
||||
* wdog - ID of the watchdog to cancel.
|
||||
*
|
||||
* Return Value:
|
||||
* OK or ERROR
|
||||
@ -88,7 +88,7 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int wd_cancel(WDOG_ID wdid)
|
||||
int wd_cancel(WDOG_ID wdog)
|
||||
{
|
||||
wdog_t *curr;
|
||||
wdog_t *prev;
|
||||
@ -101,9 +101,11 @@ int wd_cancel(WDOG_ID wdid)
|
||||
|
||||
saved_state = irqsave();
|
||||
|
||||
/* Make sure that the watchdog is initialized (non-NULL) and is still active */
|
||||
/* Make sure that the watchdog is initialized (non-NULL) and is still
|
||||
* active.
|
||||
*/
|
||||
|
||||
if (wdid && wdid->active)
|
||||
if (wdog && 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
|
||||
@ -113,7 +115,7 @@ int wd_cancel(WDOG_ID wdid)
|
||||
prev = NULL;
|
||||
curr = (wdog_t*)g_wdactivelist.head;
|
||||
|
||||
while ((curr) && (curr != wdid))
|
||||
while ((curr) && (curr != wdog))
|
||||
{
|
||||
prev = curr;
|
||||
curr = curr->next;
|
||||
@ -157,8 +159,8 @@ int wd_cancel(WDOG_ID wdid)
|
||||
|
||||
/* Mark the watchdog inactive */
|
||||
|
||||
wdid->next = NULL;
|
||||
wdid->active = false;
|
||||
wdog->next = NULL;
|
||||
WDOG_CLRACTIVE(wdog);
|
||||
|
||||
/* Return success */
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* sched/wdog/wd_create.c
|
||||
*
|
||||
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2009, 2014 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -44,6 +44,7 @@
|
||||
#include <queue.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
|
||||
#include "wdog/wdog.h"
|
||||
|
||||
@ -92,18 +93,63 @@
|
||||
WDOG_ID wd_create (void)
|
||||
{
|
||||
FAR wdog_t *wdog;
|
||||
irqstate_t saved_state;
|
||||
irqstate_t state;
|
||||
|
||||
saved_state = irqsave();
|
||||
wdog = (FAR wdog_t*)sq_remfirst(&g_wdfreelist);
|
||||
irqrestore(saved_state);
|
||||
/* These actions must be atomic with respect to other tasks and also with
|
||||
* respect to interrupt handlers that may be allocating or freeing watchdog
|
||||
* timers.
|
||||
*/
|
||||
|
||||
/* Indicate that the watchdog is not actively timing */
|
||||
state = irqsave();
|
||||
|
||||
if (wdog)
|
||||
/* If we are in an interrupt handler -OR- if the number of pre-allocated
|
||||
* timer structures exceeds the reserve, then take the the next timer from
|
||||
* the head of the free list.
|
||||
*/
|
||||
|
||||
if (g_wdnfree > CONFIG_WDOG_INTRESERVE || !up_interrupt_context())
|
||||
{
|
||||
wdog->next = NULL;
|
||||
wdog->active = false;
|
||||
/* Remove the watchdog timer from the free list and decrement the
|
||||
* count of free timers all with interrupts disabled.
|
||||
*/
|
||||
|
||||
wdog = (FAR wdog_t*)sq_remfirst(&g_wdfreelist);
|
||||
DEBUGASSERT(g_wdnfree > 0);
|
||||
g_wdnfree--;
|
||||
irqrestore(state);
|
||||
|
||||
/* Did we get one? */
|
||||
|
||||
if (wdog)
|
||||
{
|
||||
/* Yes.. Clear the forward link and all flags */
|
||||
|
||||
wdog->next = NULL;
|
||||
wdog->flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* We are in a normal tasking context AND there are not enough unreserved,
|
||||
* pre-allocated watchdog timers. We need to allocate one from the kernel
|
||||
* heap.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* We do not require that interrupts be disabled to do this. */
|
||||
|
||||
irqrestore(state);
|
||||
wdog = (FAR wdog_t *)kmalloc(sizeof(wdog_t));
|
||||
|
||||
/* Did we get one? */
|
||||
|
||||
if (wdog)
|
||||
{
|
||||
/* Yes.. Clear the forward link and set the allocated flag */
|
||||
|
||||
wdog->next = NULL;
|
||||
wdog->flags = WDOGF_ALLOCED;
|
||||
}
|
||||
}
|
||||
|
||||
return (WDOG_ID)wdog;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* sched/wdog/wd_delete.c
|
||||
*
|
||||
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2009, 2014 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -41,9 +41,11 @@
|
||||
|
||||
#include <wdog.h>
|
||||
#include <queue.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
|
||||
#include "wdog/wdog.h"
|
||||
|
||||
@ -80,7 +82,7 @@
|
||||
* queue if has been started.
|
||||
*
|
||||
* Parameters:
|
||||
* wdId - The watchdog ID to delete. This is actually a pointer to a
|
||||
* wdog - The watchdog ID to delete. This is actually a pointer to a
|
||||
* watchdog structure.
|
||||
*
|
||||
* Return Value:
|
||||
@ -91,35 +93,58 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int wd_delete(WDOG_ID wdId)
|
||||
int wd_delete(WDOG_ID wdog)
|
||||
{
|
||||
irqstate_t saved_state;
|
||||
irqstate_t state;
|
||||
|
||||
/* Verify that a valid watchdog was provided */
|
||||
|
||||
if (!wdId)
|
||||
{
|
||||
set_errno(EINVAL);
|
||||
return ERROR;
|
||||
}
|
||||
DEBUGASSERT(wdog);
|
||||
|
||||
/* The following steps are atomic... the watchdog must not be active when
|
||||
* it is being deallocated.
|
||||
*/
|
||||
|
||||
saved_state = irqsave();
|
||||
state = irqsave();
|
||||
|
||||
/* Check if the watchdog has been started. */
|
||||
|
||||
if (wdId->active)
|
||||
if (WDOG_ISACTIVE(wdog))
|
||||
{
|
||||
wd_cancel(wdId);
|
||||
/* Yes.. stop it */
|
||||
|
||||
wd_cancel(wdog);
|
||||
}
|
||||
|
||||
/* Put the watchdog back on the free list */
|
||||
/* Did this watchdog come from the pool of pre-allocated timers? Or, was
|
||||
* it allocated from the heap?
|
||||
*/
|
||||
|
||||
sq_addlast((FAR sq_entry_t*)wdId, &g_wdfreelist);
|
||||
irqrestore(saved_state);
|
||||
if (WDOG_ISALLOCED(wdog))
|
||||
{
|
||||
/* It was allocated from the heap. Use sched_kfree() to release the
|
||||
* memory. If the timer was released from an interrupt handler,
|
||||
* sched_kfree() will defer the actual deallocation of the memory
|
||||
* until a more appropriate time.
|
||||
*
|
||||
* We don't need interrupts disabled to do this.
|
||||
*/
|
||||
|
||||
irqrestore(state);
|
||||
sched_kfree(wdog);
|
||||
}
|
||||
|
||||
/* This was a pre-allocated timer. */
|
||||
|
||||
else
|
||||
{
|
||||
/* Put the timer back on the free list and increment the count of free
|
||||
* timers, all with interrupts disabled.
|
||||
*/
|
||||
|
||||
sq_addlast((FAR sq_entry_t*)wdog, &g_wdfreelist);
|
||||
g_wdnfree++;
|
||||
DEBUGASSERT(g_wdnfree <= CONFIG_PREALLOC_WDOGS);
|
||||
irqrestore(state);
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/********************************************************************************
|
||||
* sched/wdog/wd_gettime.c
|
||||
*
|
||||
* Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2009, 2014 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -92,7 +92,7 @@ int wd_gettime(WDOG_ID wdog)
|
||||
/* Verify the wdog */
|
||||
|
||||
flags = irqsave();
|
||||
if (wdog && wdog->active)
|
||||
if (wdog && WDOG_ISACTIVE(wdog))
|
||||
{
|
||||
/* Traverse the watchdog list accumulating lag times until we find the wdog
|
||||
* that we are looking for
|
||||
|
@ -1,7 +1,7 @@
|
||||
/************************************************************************
|
||||
* sched/wdog/wd_initialize.c
|
||||
*
|
||||
* Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2009, 2014 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -40,12 +40,11 @@
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <queue.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
|
||||
#include "wdog/wdog.h"
|
||||
|
||||
/************************************************************************
|
||||
* Definitions
|
||||
* Pre-processor Definitions
|
||||
************************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
@ -53,7 +52,7 @@
|
||||
************************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Global Variables
|
||||
* Public Variables
|
||||
************************************************************************/
|
||||
|
||||
/* The g_wdfreelist data structure is a singly linked list of watchdogs
|
||||
@ -62,12 +61,6 @@
|
||||
|
||||
sq_queue_t g_wdfreelist;
|
||||
|
||||
/* g_wdpool is a pointer to a list of pre-allocated watchdogs. The number
|
||||
* of watchdogs in the pool is a configuration item.
|
||||
*/
|
||||
|
||||
FAR wdog_t *g_wdpool;
|
||||
|
||||
/* The g_wdactivelist data structure is a singly linked list ordered by
|
||||
* watchdog expiration time. When watchdog timers expire,the functions on
|
||||
* this linked list are removed and the function is called.
|
||||
@ -75,10 +68,23 @@ FAR wdog_t *g_wdpool;
|
||||
|
||||
sq_queue_t g_wdactivelist;
|
||||
|
||||
/* This is the number of free, pre-allocated watchdog structures in the
|
||||
* g_wdfreelist. This value is used to enforce a reserve for interrupt
|
||||
* handlers.
|
||||
*/
|
||||
|
||||
uint16_t g_wdnfree;
|
||||
|
||||
/************************************************************************
|
||||
* Private Variables
|
||||
* Private Data
|
||||
************************************************************************/
|
||||
|
||||
/* g_wdpool is a list of pre-allocated watchdogs. The number of watchdogs
|
||||
* in the pool is a configuration item.
|
||||
*/
|
||||
|
||||
static FAR wdog_t g_wdpool[CONFIG_PREALLOC_WDOGS];
|
||||
|
||||
/************************************************************************
|
||||
* Private Functions
|
||||
************************************************************************/
|
||||
@ -108,27 +114,24 @@ sq_queue_t g_wdactivelist;
|
||||
|
||||
void wd_initialize(void)
|
||||
{
|
||||
/* Initialize the free watchdog list */
|
||||
FAR wdog_t *wdog = g_wdpool;
|
||||
int i;
|
||||
|
||||
/* Initialize watchdog lists */
|
||||
|
||||
sq_init(&g_wdfreelist);
|
||||
sq_init(&g_wdactivelist);
|
||||
|
||||
/* The g_wdfreelist must be loaded at initialization time to hold the
|
||||
* configured number of watchdogs.
|
||||
*/
|
||||
|
||||
g_wdpool = (FAR wdog_t*)kmalloc(sizeof(wdog_t) * CONFIG_PREALLOC_WDOGS);
|
||||
if (g_wdpool)
|
||||
for (i = 0; i < CONFIG_PREALLOC_WDOGS; i++)
|
||||
{
|
||||
FAR wdog_t *wdog = g_wdpool;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CONFIG_PREALLOC_WDOGS; i++)
|
||||
{
|
||||
sq_addlast((FAR sq_entry_t*)wdog++, &g_wdfreelist);
|
||||
}
|
||||
sq_addlast((FAR sq_entry_t*)wdog++, &g_wdfreelist);
|
||||
}
|
||||
|
||||
/* The g_wdactivelist queue must be reset at initialization time. */
|
||||
/* All watchdogs are free */
|
||||
|
||||
sq_init(&g_wdactivelist);
|
||||
g_wdnfree = CONFIG_PREALLOC_WDOGS;
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ static inline void wd_expiration(void)
|
||||
|
||||
/* Indicate that the watchdog is no longer active. */
|
||||
|
||||
wdog->active = false;
|
||||
WDOG_CLRACTIVE(wdog);
|
||||
|
||||
/* Execute the watchdog function */
|
||||
|
||||
@ -250,7 +250,7 @@ int wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, int argc, ...)
|
||||
*/
|
||||
|
||||
saved_state = irqsave();
|
||||
if (wdog->active)
|
||||
if (WDOG_ISACTIVE(wdog))
|
||||
{
|
||||
wd_cancel(wdog);
|
||||
}
|
||||
@ -382,8 +382,8 @@ int wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, int argc, ...)
|
||||
|
||||
/* Put the lag into the watchdog structure and mark it as active. */
|
||||
|
||||
wdog->lag = delay;
|
||||
wdog->active = true;
|
||||
wdog->lag = delay;
|
||||
WDOG_SETACTIVE(wdog);
|
||||
|
||||
#ifdef CONFIG_SCHED_TICKLESS
|
||||
/* Resume the interval timer that will generate the next interval event.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/************************************************************************
|
||||
* sched/wdog/wdog.h
|
||||
*
|
||||
* Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2009, 2014 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -51,6 +51,40 @@
|
||||
/************************************************************************
|
||||
* Pre-processor Definitions
|
||||
************************************************************************/
|
||||
/* Configuration ********************************************************/
|
||||
|
||||
#ifndef CONFIG_PREALLOC_WDOGS
|
||||
# define CONFIG_PREALLOC_WDOGS 32
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_WDOG_INTRESERVE
|
||||
# if CONFIG_PREALLOC_WDOGS > 16
|
||||
# define CONFIG_WDOG_INTRESERVE 4
|
||||
# elif CONFIG_PREALLOC_WDOGS > 8
|
||||
# define CONFIG_WDOG_INTRESERVE 2
|
||||
# else
|
||||
# define CONFIG_WDOG_INTRESERVE 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if CONFIG_WDOG_INTRESERVE >= CONFIG_PREALLOC_WDOGS
|
||||
# error CONFIG_WDOG_INTRESERVE >= CONFIG_PREALLOC_WDOGS
|
||||
#endif
|
||||
|
||||
/* Watchdog Definitions *************************************************/
|
||||
/* Flag bits for the flags field of struct wdog_s */
|
||||
|
||||
#define WDOGF_ACTIVE (1 << 0) /* Watchdog is actively timing */
|
||||
#define WDOGF_ALLOCED (1 << 1) /* 0:Pre-allocated, 1:Allocated */
|
||||
|
||||
#define WDOG_SETACTIVE(w) do { (w)->flags |= WDOGF_ACTIVE; } while (0)
|
||||
#define WDOG_SETALLOCED(w) do { (w)->flags |= WDOGF_ALLOCED; } while (0)
|
||||
|
||||
#define WDOG_CLRACTIVE(w) do { (w)->flags &= ~WDOGF_ACTIVE; } while (0)
|
||||
#define WDOG_CLRALLOCED(w) do { (w)->flags &= ~WDOGF_ALLOCED; } while (0)
|
||||
|
||||
#define WDOG_ISACTIVE(w) (((w)->flags & WDOGF_ACTIVE) != 0)
|
||||
#define WDOG_ISALLOCED(w) (((w)->flags & WDOGF_ALLOCED) != 0)
|
||||
|
||||
/************************************************************************
|
||||
* Public Type Declarations
|
||||
@ -68,7 +102,7 @@ struct wdog_s
|
||||
FAR void *picbase; /* PIC base address */
|
||||
#endif
|
||||
int lag; /* Timer associated with the delay */
|
||||
bool active; /* true if the watchdog is actively timing */
|
||||
uint8_t flags; /* See WDOGF_* definitions above */
|
||||
uint8_t argc; /* The number of parameters to pass */
|
||||
uint32_t parm[CONFIG_MAX_WDOGPARMS];
|
||||
};
|
||||
@ -92,12 +126,6 @@ extern "C"
|
||||
|
||||
extern sq_queue_t g_wdfreelist;
|
||||
|
||||
/* g_wdpool is a pointer to a list of pre-allocated watchdogs. The number
|
||||
* of watchdogs in the pool is a configuration item.
|
||||
*/
|
||||
|
||||
extern FAR wdog_t *g_wdpool;
|
||||
|
||||
/* The g_wdactivelist data structure is a singly linked list ordered by
|
||||
* watchdog expiration time. When watchdog timers expire,the functions on
|
||||
* this linked list are removed and the function is called.
|
||||
@ -105,6 +133,13 @@ extern FAR wdog_t *g_wdpool;
|
||||
|
||||
extern sq_queue_t g_wdactivelist;
|
||||
|
||||
/* This is the number of free, pre-allocated watchdog structures in the
|
||||
* g_wdfreelist. This value is used to enforce a reserve for interrupt
|
||||
* handlers.
|
||||
*/
|
||||
|
||||
extern uint16_t g_wdnfree;
|
||||
|
||||
/************************************************************************
|
||||
* Public Function Prototypes
|
||||
************************************************************************/
|
||||
|
Loading…
Reference in New Issue
Block a user