diff --git a/arch/arm/include/spinlock.h b/arch/arm/include/spinlock.h index 44e405e6303..84800fbf8dc 100644 --- a/arch/arm/include/spinlock.h +++ b/arch/arm/include/spinlock.h @@ -48,9 +48,31 @@ * Pre-processor Definitions ****************************************************************************/ +/* Spinlock states */ + #define SP_UNLOCKED 0 /* The Un-locked state */ #define SP_LOCKED 1 /* The Locked state */ +/* Memory barriers for use with NuttX spinlock logic */ + +#ifndef arm_isb +# define arm_isb(n) __asm__ __volatile__ ("isb " #n : : : "memory") +#endif + +#define SP_ISB() arm_isb(15) + +#ifndef arm_dsb +# define arm_dsb(n) __asm__ __volatile__ ("dsb " #n : : : "memory") +#endif + +#define SP_DSB() arm_dsb(15) + +#ifndef arm_dmb +# define arm_dmb(n) __asm__ __volatile__ ("dmb " #n : : : "memory") +#endif + +#define SP_DMB() arm_dmb(15) + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/include/nuttx/spinlock.h b/include/nuttx/spinlock.h index 65786a0c6d5..0a9cc88a5ea 100644 --- a/include/nuttx/spinlock.h +++ b/include/nuttx/spinlock.h @@ -203,8 +203,11 @@ void spin_lockr(FAR struct spinlock_s *lock); * ****************************************************************************/ -/* void spin_unlock(FAR spinlock_t *lock); */ -#define spin_unlock(l) do { *(l) = SP_UNLOCKED; } while (0) +#ifdef SP_DMB +void spin_unlock(FAR volatile spinlock_t *lock); +#else +# define spin_unlock(l) do { *(l) = SP_UNLOCKED; } while (0) +#endif /**************************************************************************** * Name: spin_unlockr diff --git a/sched/semaphore/spinlock.c b/sched/semaphore/spinlock.c index 79d904e7efc..a3c5225adf4 100644 --- a/sched/semaphore/spinlock.c +++ b/sched/semaphore/spinlock.c @@ -65,6 +65,22 @@ #undef CONFIG_SPINLOCK_LOCKDOWN /* Feature not yet available */ +/* Memory barriers may be provided in arch/spinlock.h + * + * DMB - Data memory barrier. Assures writes are completed to memory. + * DSB - Data syncrhonization barrier. + */ + +#define HAVE_DMB 1 +#ifndef SP_DMB +# define SP_DMB() +# undef HAVE_DMB +#endif + +#ifndef SP_DSB +# define SP_DSB() +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -121,12 +137,37 @@ void spin_lock(FAR volatile spinlock_t *lock) { while (up_testset(lock) == SP_LOCKED) { -#if 0 /* Would recurse */ - sched_yield(); -#endif + SP_DSB(); } + + SP_DMB(); } +/**************************************************************************** + * Name: spin_unlock + * + * Description: + * Release one count on a non-reentrant spinlock. + * + * Input Parameters: + * lock - A reference to the spinlock object to unlock. + * + * Returned Value: + * None. + * + * Assumptions: + * Not running at the interrupt level. + * + ****************************************************************************/ + +#ifdef HAVE_DMB +void spin_unlock(FAR volatile spinlock_t *lock) +{ + *lock = SP_UNLOCKED; + SP_DMB(); +} +#endif + /**************************************************************************** * Name: spin_lockr *