summaryrefslogtreecommitdiffstats
path: root/cpukit/score/include/rtems/score/smplock.h
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2014-03-10 08:25:32 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2014-03-11 10:58:09 +0100
commitd50acdbb6c8213114ce887a56daea02697c9e1a1 (patch)
treee48fb252786992308fa2dd6337c8a02db35bd10b /cpukit/score/include/rtems/score/smplock.h
parentsapi: Use one SMP lock for all chains (diff)
downloadrtems-d50acdbb6c8213114ce887a56daea02697c9e1a1.tar.bz2
score: Add local context to SMP lock API
Add a local context structure to the SMP lock API for acquire and release pairs. This context can be used to store the ISR level and profiling information. It may be later used to enable more sophisticated lock algorithms, e.g. MCS locks. There is only one lock that cannot be used with a local context. This is the per-CPU lock since here we would have to transfer the local context through a context switch which is very complicated.
Diffstat (limited to 'cpukit/score/include/rtems/score/smplock.h')
-rw-r--r--cpukit/score/include/rtems/score/smplock.h137
1 files changed, 104 insertions, 33 deletions
diff --git a/cpukit/score/include/rtems/score/smplock.h b/cpukit/score/include/rtems/score/smplock.h
index 25efbfa8f3..101aa0a6a1 100644
--- a/cpukit/score/include/rtems/score/smplock.h
+++ b/cpukit/score/include/rtems/score/smplock.h
@@ -42,54 +42,50 @@ extern "C" {
* 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
- * implement for example the Mellor-Crummey and Scott (MCS) locks. The SMP
- * lock is currently used in _Thread_Disable_dispatch() and
- * _Thread_Enable_dispatch() and makes them to a giant lock acquire and
- * release. Since these functions do not pass state information via a local
- * context there is currently no use case for such a feature.
+ * This SMP lock API uses a local context for acquire and release pairs. Such
+ * a context may be used to implement for example the Mellor-Crummey and Scott
+ * (MCS) locks in the future.
*
* @{
*/
/**
- * @brief SMP lock control.
+ * @brief SMP ticket lock control.
*/
typedef struct {
Atomic_Uint next_ticket;
Atomic_Uint now_serving;
-} SMP_lock_Control;
+} SMP_ticket_lock_Control;
/**
- * @brief SMP lock control initializer for static initialization.
+ * @brief SMP ticket lock control initializer for static initialization.
*/
-#define SMP_LOCK_INITIALIZER \
+#define SMP_TICKET_LOCK_INITIALIZER \
{ ATOMIC_INITIALIZER_UINT( 0U ), ATOMIC_INITIALIZER_UINT( 0U ) }
/**
- * @brief Initializes a SMP lock control.
+ * @brief Initializes an SMP ticket lock control.
*
* Concurrent initialization leads to unpredictable results.
*
- * @param[out] lock The SMP lock control.
+ * @param[out] lock The SMP ticket lock control.
*/
-static inline void _SMP_lock_Initialize( SMP_lock_Control *lock )
+static inline void _SMP_ticket_lock_Initialize( SMP_ticket_lock_Control *lock )
{
_Atomic_Init_uint( &lock->next_ticket, 0U );
_Atomic_Init_uint( &lock->now_serving, 0U );
}
/**
- * @brief Acquires a SMP lock.
+ * @brief Acquires an SMP ticket lock.
*
* This function will not disable interrupts. The caller must ensure that the
* current thread of execution is not interrupted indefinite once it obtained
- * the SMP lock.
+ * the SMP ticket lock.
*
- * @param[in,out] lock The SMP lock control.
+ * @param[in,out] lock The SMP ticket lock control.
*/
-static inline void _SMP_lock_Acquire( SMP_lock_Control *lock )
+static inline void _SMP_ticket_lock_Acquire( SMP_ticket_lock_Control *lock )
{
unsigned int my_ticket =
_Atomic_Fetch_add_uint( &lock->next_ticket, 1U, ATOMIC_ORDER_RELAXED );
@@ -102,11 +98,11 @@ static inline void _SMP_lock_Acquire( SMP_lock_Control *lock )
}
/**
- * @brief Releases a SMP lock.
+ * @brief Releases an SMP ticket lock.
*
- * @param[in,out] lock The SMP lock control.
+ * @param[in,out] lock The SMP ticket lock control.
*/
-static inline void _SMP_lock_Release( SMP_lock_Control *lock )
+static inline void _SMP_ticket_lock_Release( SMP_ticket_lock_Control *lock )
{
unsigned int current_ticket =
_Atomic_Load_uint( &lock->now_serving, ATOMIC_ORDER_RELAXED );
@@ -116,28 +112,103 @@ static inline void _SMP_lock_Release( SMP_lock_Control *lock )
}
/**
+ * @brief SMP lock control.
+ */
+typedef struct {
+ SMP_ticket_lock_Control ticket_lock;
+} SMP_lock_Control;
+
+/**
+ * @brief Local SMP lock context for acquire and release pairs.
+ */
+typedef struct {
+ ISR_Level isr_level;
+} SMP_lock_Context;
+
+/**
+ * @brief SMP lock control initializer for static initialization.
+ */
+#define SMP_LOCK_INITIALIZER { SMP_TICKET_LOCK_INITIALIZER }
+
+/**
+ * @brief Initializes an SMP lock control.
+ *
+ * Concurrent initialization leads to unpredictable results.
+ *
+ * @param[out] lock The SMP lock control.
+ */
+static inline void _SMP_lock_Initialize( SMP_lock_Control *lock )
+{
+ _SMP_ticket_lock_Initialize( &lock->ticket_lock );
+}
+
+/**
+ * @brief Acquires an SMP lock.
+ *
+ * This function will not disable interrupts. The caller must ensure that the
+ * current thread of execution is not interrupted indefinite once it obtained
+ * the SMP lock.
+ *
+ * @param[in,out] lock The SMP lock control.
+ * @param[in,out] context The local SMP lock context for an acquire and release
+ * pair.
+ */
+static inline void _SMP_lock_Acquire(
+ SMP_lock_Control *lock,
+ SMP_lock_Context *context
+)
+{
+ (void) context;
+ _SMP_ticket_lock_Acquire( &lock->ticket_lock );
+}
+
+/**
+ * @brief Releases an SMP lock.
+ *
+ * @param[in,out] lock The SMP lock control.
+ * @param[in,out] context The local SMP lock context for an acquire and release
+ * pair.
+ */
+static inline void _SMP_lock_Release(
+ SMP_lock_Control *lock,
+ SMP_lock_Context *context
+)
+{
+ (void) context;
+ _SMP_ticket_lock_Release( &lock->ticket_lock );
+}
+
+/**
* @brief Disables interrupts and acquires the SMP lock.
*
* @param[in,out] lock The SMP lock control.
- * @param[out] isr_cookie The ISR cookie.
+ * @param[in,out] context The local SMP lock context for an acquire and release
+ * pair.
*/
-#define _SMP_lock_ISR_disable_and_acquire( lock, isr_cookie ) \
- do { \
- _ISR_Disable_without_giant( isr_cookie ); \
- _SMP_lock_Acquire( lock ); \
- } while (0)
+static inline void _SMP_lock_ISR_disable_and_acquire(
+ SMP_lock_Control *lock,
+ SMP_lock_Context *context
+)
+{
+ _ISR_Disable_without_giant( context->isr_level );
+ _SMP_lock_Acquire( lock, context );
+}
/**
* @brief Releases the SMP lock and enables interrupts.
*
* @param[in,out] lock The SMP lock control.
- * @param[in] isr_cookie The ISR cookie.
+ * @param[in,out] context The local SMP lock context for an acquire and release
+ * pair.
*/
-#define _SMP_lock_Release_and_ISR_enable( lock, isr_cookie ) \
- do { \
- _SMP_lock_Release( lock ); \
- _ISR_Enable_without_giant( isr_cookie ); \
- } while (0)
+static inline void _SMP_lock_Release_and_ISR_enable(
+ SMP_lock_Control *lock,
+ SMP_lock_Context *context
+)
+{
+ _SMP_lock_Release( lock, context );
+ _ISR_Enable_without_giant( context->isr_level );
+}
/**@}*/