sched/semaphore/spinlock.c: spin_trylock handle memory barrier and instrumentation correctly.

This commit is contained in:
Xiang Xiao 2019-11-03 19:40:58 -06:00 committed by Gregory Nutt
parent e1a89d29ee
commit c397692532
3 changed files with 107 additions and 5 deletions

View File

@ -208,7 +208,31 @@ void spin_lock_wo_note(FAR volatile spinlock_t *lock);
*
****************************************************************************/
#define spin_trylock(l) up_testset(l)
spinlock_t spin_trylock(FAR volatile spinlock_t *lock);
/****************************************************************************
* Name: spin_trylock_wo_note
*
* Description:
* Try once to lock the spinlock. Do not wait if the spinlock is already
* locked.
*
* This implementation is the same as the above spin_trylock() except that
* it does not perform instrumentation logic.
*
* Input Parameters:
* lock - A reference to the spinlock object to lock.
*
* Returned Value:
* SP_LOCKED - Failure, the spinlock was already locked
* SP_UNLOCKED - Success, the spinlock was successfully locked
*
* Assumptions:
* Not running at the interrupt level.
*
****************************************************************************/
spinlock_t spin_trylock_wo_note(FAR volatile spinlock_t *lock);
/****************************************************************************
* Name: spin_unlock

View File

@ -134,7 +134,7 @@ static inline bool irq_waitlock(int cpu)
* for the deadlock condition.
*/
while (spin_trylock(&g_cpu_irqlock) == SP_LOCKED)
while (spin_trylock_wo_note(&g_cpu_irqlock) == SP_LOCKED)
{
/* Is a pause request pending? */
@ -152,8 +152,6 @@ static inline bool irq_waitlock(int cpu)
return false;
}
SP_DSB();
}
/* We have g_cpu_irqlock! */
@ -164,7 +162,6 @@ static inline bool irq_waitlock(int cpu)
sched_note_spinlocked(tcb, &g_cpu_irqlock);
#endif
SP_DMB();
return true;
}
#endif

View File

@ -131,6 +131,87 @@ void spin_lock_wo_note(FAR volatile spinlock_t *lock)
SP_DMB();
}
/****************************************************************************
* Name: spin_trylock
*
* Description:
* Try once to lock the spinlock. Do not wait if the spinlock is already
* locked.
*
* Input Parameters:
* lock - A reference to the spinlock object to lock.
*
* Returned Value:
* SP_LOCKED - Failure, the spinlock was already locked
* SP_UNLOCKED - Success, the spinlock was successfully locked
*
* Assumptions:
* Not running at the interrupt level.
*
****************************************************************************/
spinlock_t spin_trylock(FAR volatile spinlock_t *lock)
{
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
/* Notify that we are waiting for a spinlock */
sched_note_spinlock(this_task(), lock);
#endif
if (up_testset(lock) == SP_LOCKED)
{
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
/* Notify that we abort for a spinlock */
sched_note_spinabort(this_task(), &lock);
#endif
SP_DSB();
return SP_LOCKED;
}
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
/* Notify that we have the spinlock */
sched_note_spinlocked(this_task(), lock);
#endif
SP_DMB();
return SP_UNLOCKED;
}
/****************************************************************************
* Name: spin_trylock_wo_note
*
* Description:
* Try once to lock the spinlock. Do not wait if the spinlock is already
* locked.
*
* This implementation is the same as the above spin_trylock() except that
* it does not perform instrumentation logic.
*
* Input Parameters:
* lock - A reference to the spinlock object to lock.
*
* Returned Value:
* SP_LOCKED - Failure, the spinlock was already locked
* SP_UNLOCKED - Success, the spinlock was successfully locked
*
* Assumptions:
* Not running at the interrupt level.
*
****************************************************************************/
spinlock_t spin_trylock_wo_note(FAR volatile spinlock_t *lock)
{
if (up_testset(lock) == SP_LOCKED)
{
SP_DSB();
return SP_LOCKED;
}
SP_DMB();
return SP_UNLOCKED;
}
/****************************************************************************
* Name: spin_unlock
*