summaryrefslogtreecommitdiffstats
path: root/cpukit/score/include/rtems/score/smplock.h
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2014-02-13 15:43:03 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2014-02-17 08:46:38 +0100
commit0344ce0385fb2ff4f55d4154ae38b438c2168340 (patch)
treec183563bb9be2aea7c350af62321e928b58b44bd /cpukit/score/include/rtems/score/smplock.h
parentsmptests/smplock01: Use atomic operations (diff)
downloadrtems-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.h51
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)
/**@}*/