From 89b5ef8d35918eb26ca0a19b4739163287520d56 Mon Sep 17 00:00:00 2001
From: Gregory Nutt <gnutt@nuttx.org>
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,
-- 
GitLab