mirror of
https://github.com/apache/nuttx.git
synced 2026-06-05 07:12:54 +08:00
semaphore: Cleanup, merge public code.
Signed-off-by: Zeng Zhaoxiu <walker.zeng@transtekcorp.com>
This commit is contained in:
+69
-108
@@ -129,8 +129,8 @@ nxsem_allocholder(FAR sem_t *sem, FAR struct tcb_s *htcb)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static FAR struct semholder_s *nxsem_findholder(sem_t *sem,
|
static FAR struct semholder_s *
|
||||||
FAR struct tcb_s *htcb)
|
nxsem_findholder(FAR sem_t *sem, FAR struct tcb_s *htcb)
|
||||||
{
|
{
|
||||||
FAR struct semholder_s *pholder;
|
FAR struct semholder_s *pholder;
|
||||||
|
|
||||||
@@ -175,7 +175,7 @@ static FAR struct semholder_s *nxsem_findholder(sem_t *sem,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline FAR struct semholder_s *
|
static inline FAR struct semholder_s *
|
||||||
nxsem_findorallocateholder(sem_t *sem, FAR struct tcb_s *htcb)
|
nxsem_findorallocateholder(FAR sem_t *sem, FAR struct tcb_s *htcb)
|
||||||
{
|
{
|
||||||
FAR struct semholder_s *pholder = nxsem_findholder(sem, htcb);
|
FAR struct semholder_s *pholder = nxsem_findholder(sem, htcb);
|
||||||
if (!pholder)
|
if (!pholder)
|
||||||
@@ -237,22 +237,23 @@ static inline void nxsem_freeholder(FAR sem_t *sem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nxsem_findandfreeholder
|
* Name: nxsem_freecount0holder
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void nxsem_findandfreeholder(sem_t *sem,
|
static int nxsem_freecount0holder(FAR struct semholder_s *pholder,
|
||||||
FAR struct tcb_s *htcb)
|
FAR sem_t *sem, FAR void *arg)
|
||||||
{
|
{
|
||||||
FAR struct semholder_s *pholder = nxsem_findholder(sem, htcb);
|
|
||||||
|
|
||||||
/* When no more counts are held, remove the holder from the list. The
|
/* When no more counts are held, remove the holder from the list. The
|
||||||
* count was decremented in nxsem_release_holder.
|
* count was decremented in nxsem_release_holder.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (pholder != NULL && pholder->counts <= 0)
|
if (pholder->counts <= 0)
|
||||||
{
|
{
|
||||||
nxsem_freeholder(sem, pholder);
|
nxsem_freeholder(sem, pholder);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -473,9 +474,10 @@ static int nxsem_dumpholder(FAR struct semholder_s *pholder, FAR sem_t *sem,
|
|||||||
* Name: nxsem_restoreholderprio
|
* Name: nxsem_restoreholderprio
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int nxsem_restoreholderprio(FAR struct tcb_s *htcb,
|
static int nxsem_restoreholderprio(FAR struct semholder_s *pholder,
|
||||||
FAR sem_t *sem, FAR void *arg)
|
FAR sem_t *sem, FAR void *arg)
|
||||||
{
|
{
|
||||||
|
FAR struct tcb_s *htcb = pholder->htcb;
|
||||||
#if CONFIG_SEM_NNESTPRIO > 0
|
#if CONFIG_SEM_NNESTPRIO > 0
|
||||||
FAR struct tcb_s *stcb = (FAR struct tcb_s *)arg;
|
FAR struct tcb_s *stcb = (FAR struct tcb_s *)arg;
|
||||||
int rpriority;
|
int rpriority;
|
||||||
@@ -483,6 +485,15 @@ static int nxsem_restoreholderprio(FAR struct tcb_s *htcb,
|
|||||||
int j;
|
int j;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Release the holder if all counts have been given up
|
||||||
|
* before reprioritizing causes a context switch.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (pholder->counts <= 0)
|
||||||
|
{
|
||||||
|
nxsem_freeholder(sem, pholder);
|
||||||
|
}
|
||||||
|
|
||||||
/* Was the priority of the holder thread boosted? If so, then drop its
|
/* Was the priority of the holder thread boosted? If so, then drop its
|
||||||
* priority back to the correct level. What is the correct level?
|
* priority back to the correct level. What is the correct level?
|
||||||
*/
|
*/
|
||||||
@@ -599,20 +610,6 @@ static int nxsem_restoreholderprio(FAR struct tcb_s *htcb,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: nxsem_restoreholderprioall
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Reprioritize all holders
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static int nxsem_restoreholderprioall(FAR struct semholder_s *pholder,
|
|
||||||
FAR sem_t *sem, FAR void *arg)
|
|
||||||
{
|
|
||||||
return nxsem_restoreholderprio(pholder->htcb, sem, arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nxsem_restoreholderprio_others
|
* Name: nxsem_restoreholderprio_others
|
||||||
*
|
*
|
||||||
@@ -627,7 +624,7 @@ static int nxsem_restoreholderprio_others(FAR struct semholder_s *pholder,
|
|||||||
FAR struct tcb_s *rtcb = this_task();
|
FAR struct tcb_s *rtcb = this_task();
|
||||||
if (pholder->htcb != rtcb)
|
if (pholder->htcb != rtcb)
|
||||||
{
|
{
|
||||||
return nxsem_restoreholderprio(pholder->htcb, sem, arg);
|
return nxsem_restoreholderprio(pholder, sem, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -650,16 +647,7 @@ static int nxsem_restoreholderprio_self(FAR struct semholder_s *pholder,
|
|||||||
{
|
{
|
||||||
/* The running task has given up a count on the semaphore */
|
/* The running task has given up a count on the semaphore */
|
||||||
|
|
||||||
#if CONFIG_SEM_PREALLOCHOLDERS == 0
|
nxsem_restoreholderprio(pholder, sem, arg);
|
||||||
/* In the case where there are only 2 holders. This step
|
|
||||||
* is necessary to ensure we have space. Release the holder
|
|
||||||
* if all counts have been given up before reprioritizing
|
|
||||||
* causes a context switch.
|
|
||||||
*/
|
|
||||||
|
|
||||||
nxsem_findandfreeholder(sem, rtcb);
|
|
||||||
#endif
|
|
||||||
nxsem_restoreholderprio(rtcb, sem, arg);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -701,30 +689,9 @@ static int nxsem_restoreholderprio_self(FAR struct semholder_s *pholder,
|
|||||||
static inline void nxsem_restore_baseprio_irq(FAR struct tcb_s *stcb,
|
static inline void nxsem_restore_baseprio_irq(FAR struct tcb_s *stcb,
|
||||||
FAR sem_t *sem)
|
FAR sem_t *sem)
|
||||||
{
|
{
|
||||||
/* Perform the following actions only if a new thread was given a count.
|
/* Drop the priority of all holder threads */
|
||||||
* The thread that received the count should be the highest priority
|
|
||||||
* of all threads waiting for a count from the semaphore. So in that
|
|
||||||
* case, the priority of all holder threads should be dropped to the
|
|
||||||
* next highest pending priority.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (stcb != NULL)
|
nxsem_foreachholder(sem, nxsem_restoreholderprio, stcb);
|
||||||
{
|
|
||||||
/* Drop the priority of all holder threads */
|
|
||||||
|
|
||||||
nxsem_foreachholder(sem, nxsem_restoreholderprioall, stcb);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If there are no tasks waiting for available counts, then all holders
|
|
||||||
* should be at their base priority.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_ASSERTIONS
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nxsem_foreachholder(sem, nxsem_verifyholder, NULL);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -762,50 +729,20 @@ static inline void nxsem_restore_baseprio_irq(FAR struct tcb_s *stcb,
|
|||||||
static inline void nxsem_restore_baseprio_task(FAR struct tcb_s *stcb,
|
static inline void nxsem_restore_baseprio_task(FAR struct tcb_s *stcb,
|
||||||
FAR sem_t *sem)
|
FAR sem_t *sem)
|
||||||
{
|
{
|
||||||
FAR struct tcb_s *rtcb = this_task();
|
/* The currently executed thread should be the lower priority
|
||||||
|
* thread that just posted the count and caused this action.
|
||||||
/* Perform the following actions only if a new thread was given a count.
|
* However, we cannot drop the priority of the currently running
|
||||||
* The thread that received the count should be the highest priority
|
* thread -- because that will cause it to be suspended.
|
||||||
* of all threads waiting for a count from the semaphore. So in that
|
*
|
||||||
* case, the priority of all holder threads should be dropped to the
|
* So, do this in two passes. First, reprioritizing all holders
|
||||||
* next highest pending priority.
|
* except for the running thread.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (stcb != NULL)
|
nxsem_foreachholder(sem, nxsem_restoreholderprio_others, stcb);
|
||||||
{
|
|
||||||
/* The currently executed thread should be the lower priority
|
|
||||||
* thread that just posted the count and caused this action.
|
|
||||||
* However, we cannot drop the priority of the currently running
|
|
||||||
* thread -- because that will cause it to be suspended.
|
|
||||||
*
|
|
||||||
* So, do this in two passes. First, reprioritizing all holders
|
|
||||||
* except for the running thread.
|
|
||||||
*/
|
|
||||||
|
|
||||||
nxsem_foreachholder(sem, nxsem_restoreholderprio_others, stcb);
|
/* Now, find an reprioritize only the ready to run task */
|
||||||
|
|
||||||
/* Now, find an reprioritize only the ready to run task */
|
nxsem_foreachholder(sem, nxsem_restoreholderprio_self, stcb);
|
||||||
|
|
||||||
nxsem_foreachholder(sem, nxsem_restoreholderprio_self, stcb);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If there are no tasks waiting for available counts, then all holders
|
|
||||||
* should be at their base priority.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_ASSERTIONS
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nxsem_foreachholder(sem, nxsem_verifyholder, NULL);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* In any case, the currently executing task should have an entry in the
|
|
||||||
* list. Its counts were previously decremented; if it now holds no
|
|
||||||
* counts, then we need to remove it from the list of holders.
|
|
||||||
*/
|
|
||||||
|
|
||||||
nxsem_findandfreeholder(sem, rtcb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -1070,21 +1007,45 @@ void nxsem_restore_baseprio(FAR struct tcb_s *stcb, FAR sem_t *sem)
|
|||||||
(sem->semcount <= 0 && stcb != NULL));
|
(sem->semcount <= 0 && stcb != NULL));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Handler semaphore counts posed from an interrupt handler differently
|
/* Perform the following actions only if a new thread was given a count.
|
||||||
* from interrupts posted from threads. The primary difference is that
|
* The thread that received the count should be the highest priority
|
||||||
* if the semaphore is posted from a thread, then the poster thread is
|
* of all threads waiting for a count from the semaphore. So in that
|
||||||
* a player in the priority inheritance scheme. The interrupt handler
|
* case, the priority of all holder threads should be dropped to the
|
||||||
* externally injects the new count without otherwise participating
|
* next highest pending priority.
|
||||||
* itself.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (up_interrupt_context())
|
if (stcb != NULL)
|
||||||
{
|
{
|
||||||
nxsem_restore_baseprio_irq(stcb, sem);
|
/* Handler semaphore counts posed from an interrupt handler differently
|
||||||
|
* from interrupts posted from threads. The primary difference is that
|
||||||
|
* if the semaphore is posted from a thread, then the poster thread is
|
||||||
|
* a player in the priority inheritance scheme. The interrupt handler
|
||||||
|
* externally injects the new count without otherwise participating
|
||||||
|
* itself.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (up_interrupt_context())
|
||||||
|
{
|
||||||
|
nxsem_restore_baseprio_irq(stcb, sem);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nxsem_restore_baseprio_task(stcb, sem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nxsem_restore_baseprio_task(stcb, sem);
|
/* Remove the holder from the list if it's counts is zero. */
|
||||||
|
|
||||||
|
nxsem_foreachholder(sem, nxsem_freecount0holder, NULL);
|
||||||
|
|
||||||
|
/* If there are no tasks waiting for available counts, then all holders
|
||||||
|
* should be at their base priority.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_ASSERTIONS
|
||||||
|
nxsem_foreachholder(sem, nxsem_verifyholder, NULL);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1115,7 +1076,7 @@ void nxsem_canceled(FAR struct tcb_s *stcb, FAR sem_t *sem)
|
|||||||
|
|
||||||
/* Adjust the priority of every holder as necessary */
|
/* Adjust the priority of every holder as necessary */
|
||||||
|
|
||||||
nxsem_foreachholder(sem, nxsem_restoreholderprioall, stcb);
|
nxsem_foreachholder(sem, nxsem_restoreholderprio, stcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
Reference in New Issue
Block a user