From 89b5ef8d35918eb26ca0a19b4739163287520d56 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 21 Aug 2015 11:30:22 -0600 Subject: [PATCH] wdogs: Fix counting of free, pre-allocated wdog timers. The could could get decremented below zero in some situations --- ChangeLog | 4 ++++ net/socket/recvfrom.c | 4 ++-- sched/wdog/wd_create.c | 24 +++++++++++++++++------- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index cad1af1cb5..577712b511 100755 --- a/ChangeLog +++ b/ChangeLog @@ -10854,3 +10854,7 @@ state.rf_recvlen == -1. I have not checked if data are accumulated to the right position in the buffer however. From Pavel Pisa (2015-08-15). + * sched/wdog/wd_create.c: Correct a counting error in the number + of available watchdog timers. When the number of free timers is + low, the counter could be incremented below zero (2015-08-15). + diff --git a/net/socket/recvfrom.c b/net/socket/recvfrom.c index 09bf4626e1..f6519de186 100644 --- a/net/socket/recvfrom.c +++ b/net/socket/recvfrom.c @@ -916,11 +916,11 @@ static uint16_t recvfrom_tcpinterrupt(FAR struct net_driver_s *dev, /* Report an error only if no data has been received. (If * CONFIG_NET_TCP_RECVDELAY then rf_recvlen should always be - * zero). + * less than or equal to zero). */ #if CONFIG_NET_TCP_RECVDELAY > 0 - if (pstate->rf_recvlen == 0) + if (pstate->rf_recvlen <= 0) #endif { /* Report the timeout error */ diff --git a/sched/wdog/wd_create.c b/sched/wdog/wd_create.c index 2c04724a40..f4b3962b72 100644 --- a/sched/wdog/wd_create.c +++ b/sched/wdog/wd_create.c @@ -109,24 +109,34 @@ WDOG_ID wd_create (void) if (g_wdnfree > CONFIG_WDOG_INTRESERVE || up_interrupt_context()) { - /* Remove the watchdog timer from the free list and decrement the - * count of free timers all with interrupts disabled. - */ + /* Remove the watchdog timer from the free list */ wdog = (FAR struct wdog_s *)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 */ + /* Yes.. decrement the count of free, pre-allocated timers (all + * with interrupts disabled). + */ + + DEBUGASSERT(g_wdnfree > 0 && wdog != NULL); + g_wdnfree--; + + /* Clear the forward link and all flags */ wdog->next = NULL; wdog->flags = 0; } + else + { + /* We didn't get one... The count should then be exactly zero */ + + DEBUGASSERT(g_wdnfree == 0); + } + + irqrestore(state); } /* We are in a normal tasking context AND there are not enough unreserved,