diff --git a/sched/semaphore/sem_holder.c b/sched/semaphore/sem_holder.c index d012c78fe5..9e0f2c607a 100644 --- a/sched/semaphore/sem_holder.c +++ b/sched/semaphore/sem_holder.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "sched/sched.h" #include "semaphore/semaphore.h" @@ -1058,4 +1059,62 @@ void nxsem_release_all(FAR struct tcb_s *htcb) } } +/**************************************************************************** + * Name: nxsem_isholder + * + * Assertion helper for sem_post(). If priority inheritance is enabled + * assure that the calling thread is the same as the holder thread. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_ASSERTIONS +bool nxsem_checkholder(FAR sem_t *sem) +{ + FAR struct tcb_s *htcb; + pid_t tid; + + /* Is priorty inheritance selected? */ + + if ((sem->flags & SEM_PRIO_MASK) != SEM_PRIO_INHERIT) + { + return true; + } + + /* Get the thread ID. Skip thread ID 0; that is the IDLE thread which + * normally does not take semaphores but may do so initially as part of + * OS bringup. + */ + + tid = gettid(); + if (tid == 0) + { + return true; + } + + /* A semaphore with priority inheritance enabled cannot be called from an + * interrupt handler. There is no valid holder information available in + * the interrupt context. + */ + + if (up_interrupt_context()) + { + return false; + } + + /* Get the TCB associated with this thread */ + + htcb = nxsched_get_tcb(tid); + if (htcb == NULL) + { + return false; + } + + /* Return FALSE is the thread of this TCB is not a holder of this + * semaphore. + */ + + return nxsem_findholder(sem, htcb) != NULL; +} +#endif /* CONFIG_DEBUG_ASSERTIONS */ + #endif /* CONFIG_PRIORITY_INHERITANCE */ diff --git a/sched/semaphore/sem_post.c b/sched/semaphore/sem_post.c index 6c721d27b0..f6c5e92393 100644 --- a/sched/semaphore/sem_post.c +++ b/sched/semaphore/sem_post.c @@ -78,6 +78,12 @@ int nxsem_post(FAR sem_t *sem) DEBUGASSERT(sem != NULL); + /* If priority inheritance is enabled assure that the calling thread is + * the same as the holder thread. + */ + + DEBUGASSERT(nxsem_checkholder(sem)); + /* The following operations must be performed with interrupts * disabled because sem_post() may be called from an interrupt * handler. diff --git a/sched/semaphore/semaphore.h b/sched/semaphore/semaphore.h index 7a24f5e696..3f7b4a9375 100644 --- a/sched/semaphore/semaphore.h +++ b/sched/semaphore/semaphore.h @@ -91,6 +91,12 @@ void nxsem_release_all(FAR struct tcb_s *stcb); # define nxsem_release_all(stcb) #endif +#if defined(CONFIG_DEBUG_ASSERTIONS) && defined(CONFIG_PRIORITY_INHERITANCE) +bool nxsem_checkholder(FAR sem_t *sem); +#else +# define nxsem_checkholder(sem) true +#endif /* CONFIG_DEBUG_ASSERTIONS */ + #undef EXTERN #ifdef __cplusplus }