mirror of
https://github.com/apache/nuttx.git
synced 2026-06-05 15:58:59 +08:00
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:
@@ -275,16 +275,11 @@ static int nxsem_foreachholder(FAR sem_t *sem, holderhandler_t handler,
|
|||||||
|
|
||||||
next = pholder->flink;
|
next = pholder->flink;
|
||||||
|
|
||||||
/* Check if there is a handler... there should always be one
|
DEBUGASSERT(pholder->htcb != NULL);
|
||||||
* in this configuration.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (pholder->htcb != NULL)
|
/* Call the handler */
|
||||||
{
|
|
||||||
/* Call the handler */
|
|
||||||
|
|
||||||
ret = handler(pholder, sem, arg);
|
ret = handler(pholder, sem, arg);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int i;
|
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 */
|
/* Find or allocate a container for this new holder */
|
||||||
|
|
||||||
pholder = nxsem_findorallocateholder(sem, htcb);
|
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 */
|
/* 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 tcb_s *rtcb = this_task();
|
||||||
FAR struct semholder_s *pholder;
|
FAR struct semholder_s *pholder;
|
||||||
|
FAR struct semholder_s *candidate = NULL;
|
||||||
|
unsigned int total = 0;
|
||||||
|
|
||||||
/* Find the container for this holder */
|
/* Find the container for this holder */
|
||||||
|
|
||||||
pholder = nxsem_findholder(sem, rtcb);
|
#if CONFIG_SEM_PREALLOCHOLDERS > 0
|
||||||
if (pholder != NULL && pholder->counts > 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
|
#if CONFIG_SEM_PREALLOCHOLDERS == 0
|
||||||
* later in nxsem_restore_baseprio.
|
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?
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
Reference in New Issue
Block a user