From 0344ce0385fb2ff4f55d4154ae38b438c2168340 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 13 Feb 2014 15:43:03 +0100 Subject: score: Use atomic API for SMP lock Use a ticket lock implementation based on atomic operations. Delete CPU port specific SMP lock implementations. --- cpukit/score/cpu/arm/Makefile.am | 1 - cpukit/score/cpu/arm/preinstall.am | 4 - cpukit/score/cpu/arm/rtems/score/cpusmplock.h | 101 ------------------ cpukit/score/cpu/i386/Makefile.am | 1 - cpukit/score/cpu/i386/preinstall.am | 4 - cpukit/score/cpu/i386/rtems/score/cpusmplock.h | 100 ------------------ cpukit/score/cpu/no_cpu/Makefile.am | 1 - cpukit/score/cpu/no_cpu/preinstall.am | 4 - cpukit/score/cpu/no_cpu/rtems/score/cpusmplock.h | 118 ---------------------- cpukit/score/cpu/powerpc/Makefile.am | 1 - cpukit/score/cpu/powerpc/preinstall.am | 4 - cpukit/score/cpu/powerpc/rtems/score/cpusmplock.h | 95 ----------------- cpukit/score/cpu/sparc/Makefile.am | 1 - cpukit/score/cpu/sparc/preinstall.am | 4 - cpukit/score/cpu/sparc/rtems/score/cpusmplock.h | 105 ------------------- cpukit/score/include/rtems/score/smplock.h | 51 +++++++--- 16 files changed, 36 insertions(+), 559 deletions(-) delete mode 100644 cpukit/score/cpu/arm/rtems/score/cpusmplock.h delete mode 100644 cpukit/score/cpu/i386/rtems/score/cpusmplock.h delete mode 100644 cpukit/score/cpu/no_cpu/rtems/score/cpusmplock.h delete mode 100644 cpukit/score/cpu/powerpc/rtems/score/cpusmplock.h delete mode 100644 cpukit/score/cpu/sparc/rtems/score/cpusmplock.h diff --git a/cpukit/score/cpu/arm/Makefile.am b/cpukit/score/cpu/arm/Makefile.am index fe97e03e29..c051a4894f 100644 --- a/cpukit/score/cpu/arm/Makefile.am +++ b/cpukit/score/cpu/arm/Makefile.am @@ -10,7 +10,6 @@ include_rtems_score_HEADERS += rtems/score/armv4.h include_rtems_score_HEADERS += rtems/score/armv7m.h include_rtems_score_HEADERS += rtems/score/types.h include_rtems_score_HEADERS += rtems/score/cpuatomic.h -include_rtems_score_HEADERS += rtems/score/cpusmplock.h noinst_LIBRARIES = libscorecpu.a libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS) diff --git a/cpukit/score/cpu/arm/preinstall.am b/cpukit/score/cpu/arm/preinstall.am index 5c9c821ed1..4213c552ab 100644 --- a/cpukit/score/cpu/arm/preinstall.am +++ b/cpukit/score/cpu/arm/preinstall.am @@ -55,7 +55,3 @@ $(PROJECT_INCLUDE)/rtems/score/cpuatomic.h: rtems/score/cpuatomic.h $(PROJECT_IN $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpuatomic.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpuatomic.h -$(PROJECT_INCLUDE)/rtems/score/cpusmplock.h: rtems/score/cpusmplock.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpusmplock.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpusmplock.h - diff --git a/cpukit/score/cpu/arm/rtems/score/cpusmplock.h b/cpukit/score/cpu/arm/rtems/score/cpusmplock.h deleted file mode 100644 index 46592f432b..0000000000 --- a/cpukit/score/cpu/arm/rtems/score/cpusmplock.h +++ /dev/null @@ -1,101 +0,0 @@ -/** - * @file - * - * @ingroup ScoreSMPLockARM - * - * @brief ARM SMP Lock Implementation - */ - -/* - * Copyright (c) 2013 embedded brains GmbH - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.com/license/LICENSE. - */ - -#ifndef _RTEMS_SCORE_ARM_SMPLOCK_H -#define _RTEMS_SCORE_ARM_SMPLOCK_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/** - * @defgroup ScoreSMPLockARM ARM SMP Locks - * - * @ingroup ScoreSMPLock - * - * A ticket lock implementation is used. - * - * @{ - */ - -typedef struct { - uint32_t next_ticket; - uint32_t now_serving; -} CPU_SMP_lock_Control; - -#define CPU_SMP_LOCK_INITIALIZER { 0, 0 } - -static inline void _CPU_SMP_lock_Initialize( CPU_SMP_lock_Control *lock ) -{ - lock->next_ticket = 0; - lock->now_serving = 0; -} - -static inline void _CPU_SMP_lock_Acquire( CPU_SMP_lock_Control *lock ) -{ - uint32_t my_ticket; - uint32_t next_ticket; - uint32_t status; - - __asm__ volatile ( - "1: ldrex %[my_ticket], [%[next_ticket_addr]]\n" - "add %[next_ticket], %[my_ticket], #1\n" - "strex %[status], %[next_ticket], [%[next_ticket_addr]]\n" - "teq %[status], #0\n" - "bne 1b" - : [my_ticket] "=&r" (my_ticket), - [next_ticket] "=&r" (next_ticket), - [status] "=&r" (status) - : [next_ticket_addr] "r" (&lock->next_ticket) - : "cc", "memory" - ); - - while ( my_ticket != lock->now_serving ) { - _ARM_Wait_for_event(); - } - - _ARM_Data_memory_barrier(); -} - -static inline void _CPU_SMP_lock_Release( CPU_SMP_lock_Control *lock ) -{ - _ARM_Data_memory_barrier(); - ++lock->now_serving; - _ARM_Data_synchronization_barrier(); - _ARM_Send_event(); -} - -#define _CPU_SMP_lock_ISR_disable_and_acquire( lock, isr_cookie ) \ - do { \ - _CPU_ISR_Disable( isr_cookie ); \ - _CPU_SMP_lock_Acquire( lock ); \ - } while (0) - -#define _CPU_SMP_lock_Release_and_ISR_enable( lock, isr_cookie ) \ - do { \ - _CPU_SMP_lock_Release( lock ); \ - _CPU_ISR_Enable( isr_cookie ); \ - } while (0) - -/**@}*/ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _RTEMS_SCORE_ARM_SMPLOCK_H */ diff --git a/cpukit/score/cpu/i386/Makefile.am b/cpukit/score/cpu/i386/Makefile.am index bfc45c56e6..494cd679e8 100644 --- a/cpukit/score/cpu/i386/Makefile.am +++ b/cpukit/score/cpu/i386/Makefile.am @@ -11,7 +11,6 @@ include_rtems_score_HEADERS += rtems/score/interrupts.h include_rtems_score_HEADERS += rtems/score/registers.h include_rtems_score_HEADERS += rtems/score/idtr.h include_rtems_score_HEADERS += rtems/score/cpuatomic.h -include_rtems_score_HEADERS += rtems/score/cpusmplock.h noinst_LIBRARIES = libscorecpu.a libscorecpu_a_SOURCES = cpu.c cpu_asm.S diff --git a/cpukit/score/cpu/i386/preinstall.am b/cpukit/score/cpu/i386/preinstall.am index f9faf87157..060176be04 100644 --- a/cpukit/score/cpu/i386/preinstall.am +++ b/cpukit/score/cpu/i386/preinstall.am @@ -55,7 +55,3 @@ $(PROJECT_INCLUDE)/rtems/score/cpuatomic.h: rtems/score/cpuatomic.h $(PROJECT_IN $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpuatomic.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpuatomic.h -$(PROJECT_INCLUDE)/rtems/score/cpusmplock.h: rtems/score/cpusmplock.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpusmplock.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpusmplock.h - diff --git a/cpukit/score/cpu/i386/rtems/score/cpusmplock.h b/cpukit/score/cpu/i386/rtems/score/cpusmplock.h deleted file mode 100644 index f9d36e63fe..0000000000 --- a/cpukit/score/cpu/i386/rtems/score/cpusmplock.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @file - * - * @ingroup ScoreSMPLockI386 - * - * @brief i386 SMP Lock Implementation - */ - -/* - * COPYRIGHT (c) 1989-2011. - * On-Line Applications Research Corporation (OAR). - * - * Copyright (c) 2013 embedded brains GmbH - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.com/license/LICENSE. - */ - -#ifndef _RTEMS_SCORE_I386_SMPLOCK_H -#define _RTEMS_SCORE_I386_SMPLOCK_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/** - * @defgroup ScoreSMPLockI386 i386 SMP Locks - * - * @ingroup ScoreSMPLock - * - * The implementation is Test and Swap. - * - * @{ - */ - -typedef struct { - uint32_t locked; -} CPU_SMP_lock_Control; - -#define CPU_SMP_LOCK_INITIALIZER { 0 } - -static inline void _CPU_SMP_lock_Initialize( CPU_SMP_lock_Control *lock ) -{ - lock->locked = 0; -} - -static inline uint32_t _I386_Atomic_swap( - volatile uint32_t *address, - uint32_t value -) -{ - uint32_t previous; - - asm volatile( - "lock; xchgl %0, %1" - : "+m" (*address), "=a" (previous) - : "1" (value) - : "cc" - ); - - return previous; -} - -static inline void _CPU_SMP_lock_Acquire( CPU_SMP_lock_Control *lock ) -{ - do { - while ( lock->locked ) { - RTEMS_COMPILER_MEMORY_BARRIER(); - } - } while ( _I386_Atomic_swap( &lock->locked, 1 ) ); -} - -static inline void _CPU_SMP_lock_Release( CPU_SMP_lock_Control *lock ) -{ - RTEMS_COMPILER_MEMORY_BARRIER(); - lock->locked = 0; -} - -#define _CPU_SMP_lock_ISR_disable_and_acquire( lock, isr_cookie ) \ - do { \ - _CPU_ISR_Disable( isr_cookie ); \ - _CPU_SMP_lock_Acquire( lock ); \ - } while (0) - -#define _CPU_SMP_lock_Release_and_ISR_enable( lock, isr_cookie ) \ - do { \ - _CPU_SMP_lock_Release( lock ); \ - _CPU_ISR_Enable( isr_cookie ); \ - } while (0) - -/**@}*/ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _RTEMS_SCORE_I386_SMPLOCK_H */ diff --git a/cpukit/score/cpu/no_cpu/Makefile.am b/cpukit/score/cpu/no_cpu/Makefile.am index 4c812575e9..9d89bc8c0f 100644 --- a/cpukit/score/cpu/no_cpu/Makefile.am +++ b/cpukit/score/cpu/no_cpu/Makefile.am @@ -8,7 +8,6 @@ include_rtems_score_HEADERS = rtems/score/cpu.h include_rtems_score_HEADERS += rtems/score/no_cpu.h include_rtems_score_HEADERS += rtems/score/cpu_asm.h include_rtems_score_HEADERS += rtems/score/types.h -include_rtems_score_HEADERS += rtems/score/cpusmplock.h noinst_LIBRARIES = libscorecpu.a libscorecpu_a_SOURCES = cpu.c cpu_asm.c diff --git a/cpukit/score/cpu/no_cpu/preinstall.am b/cpukit/score/cpu/no_cpu/preinstall.am index a46f8b0bfd..a56caeafd8 100644 --- a/cpukit/score/cpu/no_cpu/preinstall.am +++ b/cpukit/score/cpu/no_cpu/preinstall.am @@ -43,7 +43,3 @@ $(PROJECT_INCLUDE)/rtems/score/types.h: rtems/score/types.h $(PROJECT_INCLUDE)/r $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/types.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/types.h -$(PROJECT_INCLUDE)/rtems/score/cpusmplock.h: rtems/score/cpusmplock.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpusmplock.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpusmplock.h - diff --git a/cpukit/score/cpu/no_cpu/rtems/score/cpusmplock.h b/cpukit/score/cpu/no_cpu/rtems/score/cpusmplock.h deleted file mode 100644 index 41e68af2ff..0000000000 --- a/cpukit/score/cpu/no_cpu/rtems/score/cpusmplock.h +++ /dev/null @@ -1,118 +0,0 @@ -/** - * @file - * - * @ingroup ScoreSMPLockCPU - * - * @brief CPU SMP Lock Implementation - */ - -/* - * Copyright (c) 2013 embedded brains GmbH - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.com/license/LICENSE. - */ - -#ifndef _RTEMS_SCORE_NO_CPU_SMPLOCK_H -#define _RTEMS_SCORE_NO_CPU_SMPLOCK_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/** - * @defgroup ScoreSMPLockCPU CPU SMP Locks - * - * @ingroup ScoreSMPLock - * - * This example will implement a ticket lock. - * - * @{ - */ - -/** - * @brief CPU SMP lock control. - */ -typedef struct { - unsigned int next_ticket; - unsigned int now_serving; -} CPU_SMP_lock_Control; - -/** - * @brief CPU SMP lock control initializer for static initialization. - */ -#define CPU_SMP_LOCK_INITIALIZER { 0, 0 } - -/** - * @brief Initializes a CPU SMP lock control. - * - * @param[out] lock The CPU SMP lock control. - */ -static inline void _CPU_SMP_lock_Initialize( CPU_SMP_lock_Control *lock ) -{ - lock->next_ticket = 0; - lock->now_serving = 0; -} - -/** - * @brief Acquires a CPU SMP lock. - * - * @param[in,out] lock The CPU SMP lock control. - */ -static inline void _CPU_SMP_lock_Acquire( CPU_SMP_lock_Control *lock ) -{ -#if 0 - unsigned int my_ticket = _Atomic_Fetch_and_increment( &lock->next_ticket ); - - while ( _Atomic_Load_and_acquire( &lock->now_serving ) != my_ticket ) { - _Wait_some_time(); - } -#endif -} - -/** - * @brief Releases a CPU SMP lock. - * - * @param[in,out] lock The CPU SMP lock control. - */ -static inline void _CPU_SMP_lock_Release( CPU_SMP_lock_Control *lock ) -{ -#if 0 - _Atomic_Store_and_release( &lock->now_serving, lock->now_serving + 1 ); -#endif -} - -/** - * @brief Disables interrupts and acquires the CPU SMP lock. - * - * @param[in,out] lock The CPU SMP lock control. - * @param[out] isr_cookie The ISR cookie. - */ -#define _CPU_SMP_lock_ISR_disable_and_acquire( lock, isr_cookie ) \ - do { \ - _CPU_ISR_Disable( isr_cookie ); \ - _CPU_SMP_lock_Acquire( lock ); \ - } while (0) - -/** - * @brief Releases the CPU SMP lock and enables interrupts. - * - * @param[in,out] lock The CPU SMP lock control. - * @param[in] isr_cookie The ISR cookie. - */ -#define _CPU_SMP_lock_Release_and_ISR_enable( lock, isr_cookie ) \ - do { \ - _CPU_SMP_lock_Release( lock ); \ - _CPU_ISR_Enable( isr_cookie ); \ - } while (0) - -/**@}*/ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _RTEMS_SCORE_NO_CPU_SMPLOCK_H */ diff --git a/cpukit/score/cpu/powerpc/Makefile.am b/cpukit/score/cpu/powerpc/Makefile.am index f5664a3ace..b205762674 100644 --- a/cpukit/score/cpu/powerpc/Makefile.am +++ b/cpukit/score/cpu/powerpc/Makefile.am @@ -8,7 +8,6 @@ include_rtems_score_HEADERS = rtems/score/powerpc.h include_rtems_score_HEADERS += rtems/score/cpu.h include_rtems_score_HEADERS += rtems/score/types.h include_rtems_score_HEADERS += rtems/score/cpuatomic.h -include_rtems_score_HEADERS += rtems/score/cpusmplock.h include_rtems_powerpcdir = $(includedir)/rtems/powerpc include_rtems_powerpc_HEADERS = rtems/powerpc/registers.h diff --git a/cpukit/score/cpu/powerpc/preinstall.am b/cpukit/score/cpu/powerpc/preinstall.am index 1d7fd8b48d..32934982f4 100644 --- a/cpukit/score/cpu/powerpc/preinstall.am +++ b/cpukit/score/cpu/powerpc/preinstall.am @@ -43,10 +43,6 @@ $(PROJECT_INCLUDE)/rtems/score/cpuatomic.h: rtems/score/cpuatomic.h $(PROJECT_IN $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpuatomic.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpuatomic.h -$(PROJECT_INCLUDE)/rtems/score/cpusmplock.h: rtems/score/cpusmplock.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpusmplock.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpusmplock.h - $(PROJECT_INCLUDE)/rtems/powerpc/$(dirstamp): @$(MKDIR_P) $(PROJECT_INCLUDE)/rtems/powerpc @: > $(PROJECT_INCLUDE)/rtems/powerpc/$(dirstamp) diff --git a/cpukit/score/cpu/powerpc/rtems/score/cpusmplock.h b/cpukit/score/cpu/powerpc/rtems/score/cpusmplock.h deleted file mode 100644 index f5ff9622f4..0000000000 --- a/cpukit/score/cpu/powerpc/rtems/score/cpusmplock.h +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @file - * - * @ingroup ScoreSMPLockPowerPC - * - * @brief PowerPC SMP Lock Implementation - */ - -/* - * Copyright (c) 2013 embedded brains GmbH - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.com/license/LICENSE. - */ - -#ifndef _RTEMS_SCORE_POWERPC_SMPLOCK_H -#define _RTEMS_SCORE_POWERPC_SMPLOCK_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/** - * @defgroup ScoreSMPLockPowerPC PowerPC SMP Locks - * - * @ingroup ScoreSMPLock - * - * A ticket lock implementation is used. - * - * @{ - */ - -typedef struct { - uint32_t next_ticket; - uint32_t now_serving; -} CPU_SMP_lock_Control; - -#define CPU_SMP_LOCK_INITIALIZER { 0, 0 } - -static inline void _CPU_SMP_lock_Initialize( CPU_SMP_lock_Control *lock ) -{ - lock->next_ticket = 0; - lock->now_serving = 0; -} - -static inline void _CPU_SMP_lock_Acquire( CPU_SMP_lock_Control *lock ) -{ - uint32_t my_ticket; - uint32_t next_ticket; - - __asm__ volatile ( - "1: lwarx %[my_ticket], 0, %[next_ticket_addr]\n" - "addi %[next_ticket], %[my_ticket], 1\n" - "stwcx. %[next_ticket], 0, [%[next_ticket_addr]]\n" - "bne 1b\n" - "isync" - : [my_ticket] "=&r" (my_ticket), - [next_ticket] "=&r" (next_ticket) - : [next_ticket_addr] "r" (&lock->next_ticket) - : "cc", "memory" - ); - - while ( my_ticket != lock->now_serving ) { - __asm__ volatile ( "" : : : "memory" ); - } -} - -static inline void _CPU_SMP_lock_Release( CPU_SMP_lock_Control *lock ) -{ - __asm__ volatile ( "msync" : : : "memory" ); - ++lock->now_serving; -} - -#define _CPU_SMP_lock_ISR_disable_and_acquire( lock, isr_cookie ) \ - do { \ - _CPU_ISR_Disable( isr_cookie ); \ - _CPU_SMP_lock_Acquire( lock ); \ - } while (0) - -#define _CPU_SMP_lock_Release_and_ISR_enable( lock, isr_cookie ) \ - do { \ - _CPU_SMP_lock_Release( lock ); \ - _CPU_ISR_Enable( isr_cookie ); \ - } while (0) - -/**@}*/ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _RTEMS_SCORE_POWERPC_SMPLOCK_H */ diff --git a/cpukit/score/cpu/sparc/Makefile.am b/cpukit/score/cpu/sparc/Makefile.am index 6e248a2a4c..504a5752fe 100644 --- a/cpukit/score/cpu/sparc/Makefile.am +++ b/cpukit/score/cpu/sparc/Makefile.am @@ -8,7 +8,6 @@ include_rtems_score_HEADERS = rtems/score/sparc.h include_rtems_score_HEADERS += rtems/score/cpu.h include_rtems_score_HEADERS += rtems/score/types.h include_rtems_score_HEADERS += rtems/score/cpuatomic.h -include_rtems_score_HEADERS += rtems/score/cpusmplock.h noinst_LIBRARIES = libscorecpu.a libscorecpu_a_SOURCES = cpu.c cpu_asm.S diff --git a/cpukit/score/cpu/sparc/preinstall.am b/cpukit/score/cpu/sparc/preinstall.am index e497b48f7f..a2bb01bfd2 100644 --- a/cpukit/score/cpu/sparc/preinstall.am +++ b/cpukit/score/cpu/sparc/preinstall.am @@ -43,7 +43,3 @@ $(PROJECT_INCLUDE)/rtems/score/cpuatomic.h: rtems/score/cpuatomic.h $(PROJECT_IN $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpuatomic.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpuatomic.h -$(PROJECT_INCLUDE)/rtems/score/cpusmplock.h: rtems/score/cpusmplock.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpusmplock.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpusmplock.h - diff --git a/cpukit/score/cpu/sparc/rtems/score/cpusmplock.h b/cpukit/score/cpu/sparc/rtems/score/cpusmplock.h deleted file mode 100644 index 63b11b4d69..0000000000 --- a/cpukit/score/cpu/sparc/rtems/score/cpusmplock.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file - * - * @ingroup ScoreSMPLockSPARC - * - * @brief SPARC SMP Lock Implementation - */ - -/* - * COPYRIGHT (c) 1989-2011. - * On-Line Applications Research Corporation (OAR). - * - * Copyright (c) 2013 embedded brains GmbH - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.com/license/LICENSE. - */ - -#ifndef _RTEMS_SCORE_SPARC_SMPLOCK_H -#define _RTEMS_SCORE_SPARC_SMPLOCK_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/** - * @defgroup ScoreSMPLockSPARC SPARC SMP Locks - * - * @ingroup ScoreSMPLock - * - * The implementation is Test and Swap. - * - * @{ - */ - -typedef struct { - uint32_t locked; -} CPU_SMP_lock_Control; - -#define CPU_SMP_LOCK_INITIALIZER { 0 } - -static inline void _CPU_SMP_lock_Initialize( CPU_SMP_lock_Control *lock ) -{ - lock->locked = 0; -} - -/* - * Function to access memory and bypass the cache. - * - * NOTE: address space 1 is uncacheable - * - * FIXME: This implementation uses specific Leon features. - */ -static inline uint32_t _SPARC_Atomic_swap( - volatile uint32_t *address, - uint32_t value -) -{ - asm volatile ( - "swapa [%2] %3, %0" - : "=r" (value) - : "0" (value), "r" (address), "i" (1) - : "memory" - ); - - return value; -} - -static inline void _CPU_SMP_lock_Acquire( CPU_SMP_lock_Control *lock ) -{ - do { - while ( lock->locked ) { - RTEMS_COMPILER_MEMORY_BARRIER(); - } - } while ( _SPARC_Atomic_swap( &lock->locked, 1 ) ); -} - -static inline void _CPU_SMP_lock_Release( CPU_SMP_lock_Control *lock ) -{ - RTEMS_COMPILER_MEMORY_BARRIER(); - lock->locked = 0; -} - -#define _CPU_SMP_lock_ISR_disable_and_acquire( lock, isr_cookie ) \ - do { \ - _CPU_ISR_Disable( isr_cookie ); \ - _CPU_SMP_lock_Acquire( lock ); \ - } while (0) - -#define _CPU_SMP_lock_Release_and_ISR_enable( lock, isr_cookie ) \ - do { \ - _CPU_SMP_lock_Release( lock ); \ - _CPU_ISR_Enable( isr_cookie ); \ - } while (0) - -/**@}*/ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _RTEMS_SCORE_SPARC_SMPLOCK_H */ diff --git a/cpukit/score/include/rtems/score/smplock.h b/cpukit/score/include/rtems/score/smplock.h index 6b77114ede..25efbfa8f3 100644 --- a/cpukit/score/include/rtems/score/smplock.h +++ b/cpukit/score/include/rtems/score/smplock.h @@ -10,7 +10,7 @@ * COPYRIGHT (c) 1989-2011. * On-Line Applications Research Corporation (OAR). * - * Copyright (c) 2013 embedded brains GmbH + * Copyright (c) 2013-2014 embedded brains GmbH * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at @@ -24,7 +24,7 @@ #if defined( RTEMS_SMP ) -#include +#include #include #ifdef __cplusplus @@ -36,9 +36,11 @@ extern "C" { * * @ingroup Score * - * The SMP lock implementation is architecture dependent. The implementation - * should provide fairness in case of concurrent lock attempts. A ticket lock - * is probably the most likely implementation. + * @brief The SMP lock provides mutual exclusion for SMP systems at the lowest + * level. + * + * The SMP lock is implemented as a ticket lock. This provides fairness in + * case of concurrent lock attempts. * * This SMP lock API has a flaw. It does not provide the ability to use a * local context for acquire and release pairs. Such a context is necessary to @@ -53,16 +55,17 @@ extern "C" { /** * @brief SMP lock control. - * - * This is an opaque type. The SMP lock implementation is architecture - * dependent. */ -typedef CPU_SMP_lock_Control SMP_lock_Control; +typedef struct { + Atomic_Uint next_ticket; + Atomic_Uint now_serving; +} SMP_lock_Control; /** * @brief SMP lock control initializer for static initialization. */ -#define SMP_LOCK_INITIALIZER CPU_SMP_LOCK_INITIALIZER +#define SMP_LOCK_INITIALIZER \ + { ATOMIC_INITIALIZER_UINT( 0U ), ATOMIC_INITIALIZER_UINT( 0U ) } /** * @brief Initializes a SMP lock control. @@ -73,7 +76,8 @@ typedef CPU_SMP_lock_Control SMP_lock_Control; */ static inline void _SMP_lock_Initialize( SMP_lock_Control *lock ) { - _CPU_SMP_lock_Initialize( lock ); + _Atomic_Init_uint( &lock->next_ticket, 0U ); + _Atomic_Init_uint( &lock->now_serving, 0U ); } /** @@ -87,7 +91,14 @@ static inline void _SMP_lock_Initialize( SMP_lock_Control *lock ) */ static inline void _SMP_lock_Acquire( SMP_lock_Control *lock ) { - _CPU_SMP_lock_Acquire( lock ); + unsigned int my_ticket = + _Atomic_Fetch_add_uint( &lock->next_ticket, 1U, ATOMIC_ORDER_RELAXED ); + unsigned int now_serving; + + do { + now_serving = + _Atomic_Load_uint( &lock->now_serving, ATOMIC_ORDER_ACQUIRE ); + } while ( now_serving != my_ticket ); } /** @@ -97,7 +108,11 @@ static inline void _SMP_lock_Acquire( SMP_lock_Control *lock ) */ static inline void _SMP_lock_Release( SMP_lock_Control *lock ) { - _CPU_SMP_lock_Release( lock ); + unsigned int current_ticket = + _Atomic_Load_uint( &lock->now_serving, ATOMIC_ORDER_RELAXED ); + unsigned int next_ticket = current_ticket + 1U; + + _Atomic_Store_uint( &lock->now_serving, next_ticket, ATOMIC_ORDER_RELEASE ); } /** @@ -107,7 +122,10 @@ static inline void _SMP_lock_Release( SMP_lock_Control *lock ) * @param[out] isr_cookie The ISR cookie. */ #define _SMP_lock_ISR_disable_and_acquire( lock, isr_cookie ) \ - _CPU_SMP_lock_ISR_disable_and_acquire( lock, isr_cookie ) + do { \ + _ISR_Disable_without_giant( isr_cookie ); \ + _SMP_lock_Acquire( lock ); \ + } while (0) /** * @brief Releases the SMP lock and enables interrupts. @@ -116,7 +134,10 @@ static inline void _SMP_lock_Release( SMP_lock_Control *lock ) * @param[in] isr_cookie The ISR cookie. */ #define _SMP_lock_Release_and_ISR_enable( lock, isr_cookie ) \ - _CPU_SMP_lock_Release_and_ISR_enable( lock, isr_cookie ) + do { \ + _SMP_lock_Release( lock ); \ + _ISR_Enable_without_giant( isr_cookie ); \ + } while (0) /**@}*/ -- cgit v1.2.3