Assert if a thread attempts to post a semaphore incorrectly.

Assert in nxsem_post if:

- Priority inheritance is enabled on a semaphore
- A thread that does not hold the semaphore attempts to post it

This will detect an error condition described in https://cwiki.apache.org/confluence/display/NUTTX/Signaling+Semaphores+and+Priority+Inheritance

None.  The debug instrumentation is only enabled if CONFIG_DEBUG_ASSERTIONS is enabled.

Use sim:ostest.  Verify that no assertions occur.
This commit is contained in:
Gregory Nutt 2023-03-31 16:25:45 -06:00 committed by Alin Jerpelea
parent 4ff4562401
commit 758e88672b
3 changed files with 71 additions and 0 deletions

View File

@ -28,6 +28,7 @@
#include <assert.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <arch/irq.h>
#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 */

View File

@ -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.

View File

@ -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
}