semaphore: Improve the nxsem_release_holder function.

1. The task which called nxsem_release_holder may not be a holder of the semaphore,
   counts of the holder would not be decreamented.
   This commit try to resolve the problem if there is only one holder.
2. Avoid counts overflow.

Signed-off-by: Zeng Zhaoxiu <walker.zeng@transtekcorp.com>
This commit is contained in:
Zeng Zhaoxiu 2022-02-08 16:52:30 +08:00 committed by Xiang Xiao
parent ea8f5f565e
commit fc4ab4fd94

View File

@ -275,16 +275,11 @@ static int nxsem_foreachholder(FAR sem_t *sem, holderhandler_t handler,
next = pholder->flink;
/* Check if there is a handler... there should always be one
* in this configuration.
*/
DEBUGASSERT(pholder->htcb != NULL);
if (pholder->htcb != NULL)
{
/* Call the handler */
/* Call the handler */
ret = handler(pholder, sem, arg);
}
ret = handler(pholder, sem, arg);
}
#else
int i;
@ -871,7 +866,7 @@ void nxsem_add_holder_tcb(FAR struct tcb_s *htcb, FAR sem_t *sem)
/* Find or allocate a container for this new holder */
pholder = nxsem_findorallocateholder(sem, htcb);
if (pholder != NULL)
if (pholder != NULL && pholder->counts < SEM_VALUE_MAX)
{
/* Increment the number of counts held by this holder */
@ -951,18 +946,60 @@ void nxsem_release_holder(FAR sem_t *sem)
{
FAR struct tcb_s *rtcb = this_task();
FAR struct semholder_s *pholder;
FAR struct semholder_s *candidate = NULL;
unsigned int total = 0;
/* Find the container for this holder */
pholder = nxsem_findholder(sem, rtcb);
if (pholder != NULL && pholder->counts > 0)
#if CONFIG_SEM_PREALLOCHOLDERS > 0
for (pholder = sem->hhead; pholder; pholder = pholder->flink)
#else
int i;
/* We have two hard-allocated holder structures in sem_t */
for (i = 0; i < 2; i++)
#endif
{
/* Decrement the counts on this holder -- the holder will be freed
* later in nxsem_restore_baseprio.
#if CONFIG_SEM_PREALLOCHOLDERS == 0
pholder = &sem->holder[i];
if (pholder->htcb == NULL)
{
continue;
}
#endif
DEBUGASSERT(pholder->counts > 0);
if (pholder->htcb == rtcb)
{
/* Decrement the counts on this holder -- the holder will be freed
* later in nxsem_restore_baseprio.
*/
pholder->counts--;
return;
}
total++;
candidate = pholder;
}
/* The current task is not a holder */
if (total == 1)
{
/* If the sempahore has only one holder, we can decrement the counts
* simply.
*/
pholder->counts--;
candidate->counts--;
return;
}
/* TODO:
* How do we choose the holder to decrement it's counts?
*/
}
/****************************************************************************