From b72d7730514d8b8afba1cc664b50c6d4295292f2 Mon Sep 17 00:00:00 2001
From: patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>
Date: Fri, 13 Mar 2009 11:27:34 +0000
Subject: [PATCH] Free holder containers on sem_destroy

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1598 42af7a65-404d-4744-a932-0658087f49c3
---
 sched/sem_holder.c | 35 +++++++++++++++++++++++++++++------
 1 file changed, 29 insertions(+), 6 deletions(-)

diff --git a/sched/sem_holder.c b/sched/sem_holder.c
index 21440752f0..1388965be3 100644
--- a/sched/sem_holder.c
+++ b/sched/sem_holder.c
@@ -244,6 +244,15 @@ static int sem_foreachholder(FAR sem_t *sem, holderhandler_t handler, FAR void *
   return ret;
 }
 
+/****************************************************************************
+ * Name: sem_recoverholders
+ ****************************************************************************/
+
+static int sem_recoverholders(struct semholder_s *pholder, FAR sem_t *sem, FAR void *arg)
+{
+  sem_freeholder(sem, pholder);
+}
+
 /****************************************************************************
  * Name: sem_boostholderprio
  ****************************************************************************/
@@ -354,6 +363,11 @@ static int sem_verifyholder(struct semholder_s *pholder, FAR sem_t *sem, FAR voi
 {
   FAR _TCB *htcb = (FAR _TCB *)pholder->holder;
 
+  /* Called after a semaphore has been released (incremented), the semaphore
+   * could is non-negative, and there is no thread waiting for the count.
+   * In this case, the priority of the holder should not be boosted.
+   */
+
 #if CONFIG_SEM_NNESTPRIO > 0
   DEBUGASSERT(htcb->npend_reprio == 0);
 #endif
@@ -536,23 +550,32 @@ void sem_initholders(void)
 
 void sem_destroyholder(FAR sem_t *sem)
 {
-#if 0
   FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head;
 
   /* It is an error is a semaphore is destroyed while there are any holders
    * (except perhaps the thread releas the semaphore itself).  Hmmm.. but
    * we actually have to assume that the caller knows what it is doing because
    * could have killed another thread that is the actual holder of the semaphore.
+   * We cannot make any assumptions about the state of the semaphore or the
+   * state of any of the holder threads.
+   *
+   * So just recover any stranded holders and hope the task knows what it is
+   * doing.
    */
 
 #if CONFIG_SEM_PREALLOCHOLDERS > 0
-  DEBUGASSERT((!sem->hlist.holder || sem->hlist.holder == rtcb) && !sem->hlist.flink);
+  if (sem->hlist.holder || sem->hlist.flink)
+    {
+      sdbg("Semaphore destroyed with holders\n");
+      (void)sem_foreachholder(sem, sem_recoverholders, NULL);
+    }
 #else
-  DEBUGASSERT(!sem->hlist.holder || sem->hlist.holder == rtcb);
-#endif
-#endif
-
+  if (sem->hlist.holder)
+    {
+      sdbg("Semaphore destroyed with holder\n");
+    }
   sem->hlist.holder = NULL;
+#endif
 }
 
 /****************************************************************************
-- 
GitLab