From 01774e7a3014998cbd519933fc902d8664347a77 Mon Sep 17 00:00:00 2001 From: chao an Date: Sun, 4 Aug 2024 20:14:27 +0800 Subject: [PATCH] spinlock: inline no trace implement to remove duplicate logic minor changes to remove duplicate logic Signed-off-by: chao an --- include/nuttx/spinlock.h | 175 +++++++++++++++------------------------ 1 file changed, 65 insertions(+), 110 deletions(-) diff --git a/include/nuttx/spinlock.h b/include/nuttx/spinlock.h index dd5216430ed93..0e0b84bc18456 100644 --- a/include/nuttx/spinlock.h +++ b/include/nuttx/spinlock.h @@ -223,15 +223,14 @@ static inline spinlock_t up_testset(FAR volatile spinlock_t *lock) #ifdef CONFIG_HAVE_INLINE_SPINLOCK /**************************************************************************** - * Name: spin_lock + * Name: spin_lock_wo_note * * Description: * If this CPU does not already hold the spinlock, then loop until the * spinlock is successfully locked. * - * This implementation is non-reentrant and is prone to deadlocks in - * the case that any logic on the same CPU attempts to take the lock - * more than once. + * This implementation is the same as the above spin_lock() except that + * it does not perform instrumentation logic. * * Input Parameters: * lock - A reference to the spinlock object to lock. @@ -245,20 +244,13 @@ static inline spinlock_t up_testset(FAR volatile spinlock_t *lock) * ****************************************************************************/ -static inline_function void spin_lock(FAR volatile spinlock_t *lock) +static inline_function void spin_lock_wo_note(FAR volatile spinlock_t *lock) { -#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS - - /* Notify that we are waiting for a spinlock */ - - sched_note_spinlock_lock(lock); -#endif - #ifdef CONFIG_TICKET_SPINLOCK unsigned short ticket = atomic_fetch_add((FAR atomic_ushort *)&lock->tickets.next, 1); while (atomic_load((FAR atomic_ushort *)&lock->tickets.owner) != ticket) -#else /* CONFIG_SPINLOCK */ +#else /* CONFIG_TICKET_SPINLOCK */ while (up_testset(lock) == SP_LOCKED) #endif { @@ -266,23 +258,19 @@ static inline_function void spin_lock(FAR volatile spinlock_t *lock) SP_WFE(); } -#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS - /* Notify that we have the spinlock */ - - sched_note_spinlock_locked(lock); -#endif SP_DMB(); } /**************************************************************************** - * Name: spin_lock_wo_note + * Name: spin_lock * * Description: * If this CPU does not already hold the spinlock, then loop until the * spinlock is successfully locked. * - * This implementation is the same as the above spin_lock() except that - * it does not perform instrumentation logic. + * This implementation is non-reentrant and is prone to deadlocks in + * the case that any logic on the same CPU attempts to take the lock + * more than once. * * Input Parameters: * lock - A reference to the spinlock object to lock. @@ -296,30 +284,31 @@ static inline_function void spin_lock(FAR volatile spinlock_t *lock) * ****************************************************************************/ -static inline_function void spin_lock_wo_note(FAR volatile spinlock_t *lock) +static inline_function void spin_lock(FAR volatile spinlock_t *lock) { -#ifdef CONFIG_TICKET_SPINLOCK - unsigned short ticket = - atomic_fetch_add((FAR atomic_ushort *)&lock->tickets.next, 1); - while (atomic_load((FAR atomic_ushort *)&lock->tickets.owner) != ticket) -#else /* CONFIG_TICKET_SPINLOCK */ - while (up_testset(lock) == SP_LOCKED) -#endif - { - SP_DSB(); - SP_WFE(); - } + /* Notify that we are waiting for a spinlock */ - SP_DMB(); + sched_note_spinlock_lock(lock); + + /* Lock without trace note */ + + spin_lock_wo_note(lock); + + /* Notify that we have the spinlock */ + + sched_note_spinlock_locked(lock); } /**************************************************************************** - * Name: spin_trylock + * 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. * @@ -332,15 +321,9 @@ static inline_function void spin_lock_wo_note(FAR volatile spinlock_t *lock) * ****************************************************************************/ -static inline_function bool spin_trylock(FAR volatile spinlock_t *lock) +static inline_function bool +spin_trylock_wo_note(FAR volatile spinlock_t *lock) { -#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS - - /* Notify that we are waiting for a spinlock */ - - sched_note_spinlock_lock(lock); -#endif - #ifdef CONFIG_TICKET_SPINLOCK unsigned short ticket = atomic_load((FAR atomic_ushort *)&lock->tickets.next); @@ -365,34 +348,21 @@ static inline_function bool spin_trylock(FAR volatile spinlock_t *lock) if (up_testset(lock) == SP_LOCKED) #endif /* CONFIG_TICKET_SPINLOCK */ { -#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS - /* Notify that we abort for a spinlock */ - - sched_note_spinlock_abort(lock); -#endif SP_DSB(); return false; } -#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS - /* Notify that we have the spinlock */ - - sched_note_spinlock_locked(lock); -#endif SP_DMB(); return true; } /**************************************************************************** - * Name: spin_trylock_wo_note + * Name: spin_trylock * * 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. * @@ -405,47 +375,42 @@ static inline_function bool spin_trylock(FAR volatile spinlock_t *lock) * ****************************************************************************/ -static inline_function bool -spin_trylock_wo_note(FAR volatile spinlock_t *lock) +static inline_function bool spin_trylock(FAR volatile spinlock_t *lock) { -#ifdef CONFIG_TICKET_SPINLOCK - unsigned short ticket = - atomic_load((FAR atomic_ushort *)&lock->tickets.next); + bool locked; - spinlock_t oldval = - { - { - ticket, ticket - } - }; + /* Notify that we are waiting for a spinlock */ - spinlock_t newval = + sched_note_spinlock_lock(lock); + + /* Try lock without trace note */ + + locked = spin_trylock_wo_note(lock); + if (locked) { - { - ticket, ticket + 1 - } - }; + /* Notify that we have the spinlock */ - if (!atomic_compare_exchange_strong((FAR atomic_uint *)&lock->value, - &oldval.value, newval.value)) -#else /* CONFIG_TICKET_SPINLOCK */ - if (up_testset(lock) == SP_LOCKED) -#endif /* CONFIG_TICKET_SPINLOCK */ + sched_note_spinlock_locked(lock); + } + else { - SP_DSB(); - return false; + /* Notify that we abort for a spinlock */ + + sched_note_spinlock_abort(lock); } - SP_DMB(); - return true; + return locked; } /**************************************************************************** - * Name: spin_unlock + * Name: spin_unlock_wo_note * * Description: * Release one count on a non-reentrant spinlock. * + * This implementation is the same as the above spin_unlock() except that + * it does not perform instrumentation logic. + * * Input Parameters: * lock - A reference to the spinlock object to unlock. * @@ -457,37 +422,25 @@ spin_trylock_wo_note(FAR volatile spinlock_t *lock) * ****************************************************************************/ -#ifdef __SP_UNLOCK_FUNCTION -static inline_function void spin_unlock(FAR volatile spinlock_t *lock) +static inline_function void +spin_unlock_wo_note(FAR volatile spinlock_t *lock) { -# ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS - /* Notify that we are unlocking the spinlock */ - - sched_note_spinlock_unlock(lock); -# endif - SP_DMB(); -# ifdef CONFIG_TICKET_SPINLOCK +#ifdef CONFIG_TICKET_SPINLOCK atomic_fetch_add((FAR atomic_ushort *)&lock->tickets.owner, 1); -# else +#else *lock = SP_UNLOCKED; -# endif +#endif SP_DSB(); SP_SEV(); } -#else -# define spin_unlock(l) do { *(l) = SP_UNLOCKED; } while (0) -#endif /**************************************************************************** - * Name: spin_unlock_wo_note + * Name: spin_unlock * * Description: * Release one count on a non-reentrant spinlock. * - * This implementation is the same as the above spin_unlock() except that - * it does not perform instrumentation logic. - * * Input Parameters: * lock - A reference to the spinlock object to unlock. * @@ -499,18 +452,20 @@ static inline_function void spin_unlock(FAR volatile spinlock_t *lock) * ****************************************************************************/ -static inline_function void -spin_unlock_wo_note(FAR volatile spinlock_t *lock) +#ifdef __SP_UNLOCK_FUNCTION +static inline_function void spin_unlock(FAR volatile spinlock_t *lock) { - SP_DMB(); -#ifdef CONFIG_TICKET_SPINLOCK - atomic_fetch_add((FAR atomic_ushort *)&lock->tickets.owner, 1); + /* Unlock without trace note */ + + spin_unlock_wo_note(lock); + + /* Notify that we are unlocking the spinlock */ + + sched_note_spinlock_unlock(lock); +} #else - *lock = SP_UNLOCKED; +# define spin_unlock(l) do { *(l) = SP_UNLOCKED; } while (0) #endif - SP_DSB(); - SP_SEV(); -} /**************************************************************************** * Name: spin_is_locked