forked from Imagelibrary/rtems
score: Use atomic API for SMP lock
Use a ticket lock implementation based on atomic operations. Delete CPU port specific SMP lock implementations.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 <rtems/score/cpu.h>
|
||||
|
||||
#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 */
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 <rtems/score/cpu.h>
|
||||
|
||||
#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 */
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 <rtems/score/cpu.h>
|
||||
|
||||
#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 */
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 <rtems/score/cpu.h>
|
||||
|
||||
#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 */
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 <rtems/score/cpu.h>
|
||||
|
||||
#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 */
|
||||
@@ -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 <rtems/score/cpusmplock.h>
|
||||
#include <rtems/score/atomic.h>
|
||||
#include <rtems/score/isrlevel.h>
|
||||
|
||||
#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)
|
||||
|
||||
/**@}*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user