diff --git a/sched/Kconfig b/sched/Kconfig
index 25aeff8895a545770c460a290e7a527b24a781ac..57e96e5712bf1b3049bd879bb018290b8ad4cb17 100644
--- a/sched/Kconfig
+++ b/sched/Kconfig
@@ -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"
diff --git a/sched/wdog/wd_cancel.c b/sched/wdog/wd_cancel.c
index 9093deed86362884f6db5587fe4f4a101ea6ec91..44fc95ab477d497270461840318cfa3b2e01dc01 100644
--- a/sched/wdog/wd_cancel.c
+++ b/sched/wdog/wd_cancel.c
@@ -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 */
 
diff --git a/sched/wdog/wd_create.c b/sched/wdog/wd_create.c
index f766aca9cd55399fb1d861f9284d9a6fe7afe551..fb57d86b1c24607ee637bfbdd55ea1b940121b1e 100644
--- a/sched/wdog/wd_create.c
+++ b/sched/wdog/wd_create.c
@@ -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;
diff --git a/sched/wdog/wd_delete.c b/sched/wdog/wd_delete.c
index 8a1be3006b951b77563f464af9d2917679812d23..a98caa20e8dcba5b8e914526eecbea75ddce55cf 100644
--- a/sched/wdog/wd_delete.c
+++ b/sched/wdog/wd_delete.c
@@ -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 */
 
diff --git a/sched/wdog/wd_gettime.c b/sched/wdog/wd_gettime.c
index a2983527b232c80495b75f23aa81dbfea427f4de..4f69bfeb99d9e6495d406855d63619c5ff7ebd41 100644
--- a/sched/wdog/wd_gettime.c
+++ b/sched/wdog/wd_gettime.c
@@ -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
diff --git a/sched/wdog/wd_initialize.c b/sched/wdog/wd_initialize.c
index dd81a74be19407c9988693f7f7644c0859056ad6..eba4ebacdb9cd96d8bedbff254f200791f4e84db 100644
--- a/sched/wdog/wd_initialize.c
+++ b/sched/wdog/wd_initialize.c
@@ -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;
 }
diff --git a/sched/wdog/wd_start.c b/sched/wdog/wd_start.c
index 9cf7edc3529558a821426c607f98dd1906b42c13..009a5d5ee7624d07fc1461701bcfa8c9d2a13d6c 100644
--- a/sched/wdog/wd_start.c
+++ b/sched/wdog/wd_start.c
@@ -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.
diff --git a/sched/wdog/wdog.h b/sched/wdog/wdog.h
index 01c993bdc4270d1689d862b6d74ae3623101faff..73a73f1ad3da35d2bd9a255092d0c38722d59464 100644
--- a/sched/wdog/wdog.h
+++ b/sched/wdog/wdog.h
@@ -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
  ************************************************************************/