diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2014-02-13 15:43:03 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2014-02-17 08:46:38 +0100 |
commit | 0344ce0385fb2ff4f55d4154ae38b438c2168340 (patch) | |
tree | c183563bb9be2aea7c350af62321e928b58b44bd /cpukit/score/include/rtems/score/smplock.h | |
parent | smptests/smplock01: Use atomic operations (diff) | |
download | rtems-0344ce0385fb2ff4f55d4154ae38b438c2168340.tar.bz2 |
score: Use atomic API for SMP lock
Use a ticket lock implementation based on atomic operations. Delete CPU
port specific SMP lock implementations.
Diffstat (limited to 'cpukit/score/include/rtems/score/smplock.h')
-rw-r--r-- | cpukit/score/include/rtems/score/smplock.h | 51 |
1 files changed, 36 insertions, 15 deletions
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 <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) /**@}*/ |