summaryrefslogtreecommitdiffstats
path: root/cpukit/include/rtems/score/smplock.h
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/include/rtems/score/smplock.h')
-rw-r--r--cpukit/include/rtems/score/smplock.h327
1 files changed, 327 insertions, 0 deletions
diff --git a/cpukit/include/rtems/score/smplock.h b/cpukit/include/rtems/score/smplock.h
new file mode 100644
index 0000000000..a156edfd92
--- /dev/null
+++ b/cpukit/include/rtems/score/smplock.h
@@ -0,0 +1,327 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreSMPLock
+ *
+ * @brief SMP Lock API
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Copyright (c) 2013, 2016 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.org/license/LICENSE.
+ */
+
+#ifndef _RTEMS_SCORE_SMPLOCK_H
+#define _RTEMS_SCORE_SMPLOCK_H
+
+#include <rtems/score/cpuopts.h>
+
+#if defined(RTEMS_SMP)
+
+#include <rtems/score/smplockstats.h>
+#include <rtems/score/smplockticket.h>
+#include <rtems/score/isrlevel.h>
+
+#if defined(RTEMS_DEBUG)
+#include <rtems/score/assert.h>
+#include <rtems/score/smp.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup ScoreSMPLock SMP Locks
+ *
+ * @ingroup Score
+ *
+ * @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 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.
+ *
+ * @{
+ */
+
+#if defined(RTEMS_DEBUG) || defined(RTEMS_PROFILING)
+#define RTEMS_SMP_LOCK_DO_NOT_INLINE
+#endif
+
+/**
+ * @brief SMP lock control.
+ */
+typedef struct {
+ SMP_ticket_lock_Control Ticket_lock;
+#if defined(RTEMS_DEBUG)
+ /**
+ * @brief The index of the owning processor of this lock.
+ *
+ * The processor index is used instead of the executing thread, so that this
+ * works in interrupt and system initialization context. It is assumed that
+ * thread dispatching is disabled in SMP lock critical sections.
+ *
+ * In case the lock is free, then the value of this field is
+ * SMP_LOCK_NO_OWNER.
+ *
+ * @see _SMP_lock_Is_owner().
+ */
+ uint32_t owner;
+#endif
+#if defined(RTEMS_PROFILING)
+ SMP_lock_Stats Stats;
+#endif
+} SMP_lock_Control;
+
+/**
+ * @brief Local SMP lock context for acquire and release pairs.
+ */
+typedef struct {
+ ISR_Level isr_level;
+#if defined(RTEMS_DEBUG)
+ SMP_lock_Control *lock_used_for_acquire;
+#endif
+#if defined(RTEMS_PROFILING)
+ SMP_lock_Stats_context Stats_context;
+#endif
+} SMP_lock_Context;
+
+#if defined(RTEMS_DEBUG)
+#define SMP_LOCK_NO_OWNER 0
+#endif
+
+/**
+ * @brief SMP lock control initializer for static initialization.
+ */
+#if defined(RTEMS_DEBUG) && defined(RTEMS_PROFILING)
+ #define SMP_LOCK_INITIALIZER( name ) \
+ { \
+ SMP_TICKET_LOCK_INITIALIZER, \
+ SMP_LOCK_NO_OWNER, \
+ SMP_LOCK_STATS_INITIALIZER( name ) \
+ }
+#elif defined(RTEMS_DEBUG)
+ #define SMP_LOCK_INITIALIZER( name ) \
+ { SMP_TICKET_LOCK_INITIALIZER, SMP_LOCK_NO_OWNER }
+#elif defined(RTEMS_PROFILING)
+ #define SMP_LOCK_INITIALIZER( name ) \
+ { SMP_TICKET_LOCK_INITIALIZER, SMP_LOCK_STATS_INITIALIZER( name ) }
+#else
+ #define SMP_LOCK_INITIALIZER( name ) { SMP_TICKET_LOCK_INITIALIZER }
+#endif
+
+static inline void _SMP_lock_Initialize_inline(
+ SMP_lock_Control *lock,
+ const char *name
+)
+{
+ _SMP_ticket_lock_Initialize( &lock->Ticket_lock );
+#if defined(RTEMS_DEBUG)
+ lock->owner = SMP_LOCK_NO_OWNER;
+#endif
+#if defined(RTEMS_PROFILING)
+ _SMP_lock_Stats_initialize( &lock->Stats, name );
+#else
+ (void) name;
+#endif
+}
+
+/**
+ * @brief Initializes an SMP lock.
+ *
+ * Concurrent initialization leads to unpredictable results.
+ *
+ * @param[in] lock The SMP lock control.
+ * @param[in] name The name for the SMP lock statistics. This name must be
+ * persistent throughout the life time of this statistics block.
+ */
+#if defined(RTEMS_SMP_LOCK_DO_NOT_INLINE)
+void _SMP_lock_Initialize(
+ SMP_lock_Control *lock,
+ const char * name
+);
+#else
+#define _SMP_lock_Initialize( lock, name ) \
+ _SMP_lock_Initialize_inline( lock, name )
+#endif
+
+static inline void _SMP_lock_Destroy_inline( SMP_lock_Control *lock )
+{
+ _SMP_ticket_lock_Destroy( &lock->Ticket_lock );
+ _SMP_lock_Stats_destroy( &lock->Stats );
+}
+
+/**
+ * @brief Destroys an SMP lock.
+ *
+ * Concurrent destruction leads to unpredictable results.
+ *
+ * @param[in] lock The SMP lock control.
+ */
+#if defined(RTEMS_SMP_LOCK_DO_NOT_INLINE)
+void _SMP_lock_Destroy( SMP_lock_Control *lock );
+#else
+#define _SMP_lock_Destroy( lock ) \
+ _SMP_lock_Destroy_inline( lock )
+#endif
+
+#if defined(RTEMS_DEBUG)
+static inline uint32_t _SMP_lock_Who_am_I( void )
+{
+ /*
+ * The CPU index starts with zero. Increment it by one, to allow global SMP
+ * locks to reside in the BSS section.
+ */
+ return _SMP_Get_current_processor() + 1;
+}
+#endif
+
+static inline void _SMP_lock_Acquire_inline(
+ SMP_lock_Control *lock,
+ SMP_lock_Context *context
+)
+{
+#if defined(RTEMS_DEBUG)
+ context->lock_used_for_acquire = lock;
+#else
+ (void) context;
+#endif
+ _SMP_ticket_lock_Acquire(
+ &lock->Ticket_lock,
+ &lock->Stats,
+ &context->Stats_context
+ );
+#if defined(RTEMS_DEBUG)
+ lock->owner = _SMP_lock_Who_am_I();
+#endif
+}
+
+/**
+ * @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] lock The SMP lock control.
+ * @param[in] context The local SMP lock context for an acquire and release
+ * pair.
+ */
+void _SMP_lock_Acquire(
+ SMP_lock_Control *lock,
+ SMP_lock_Context *context
+);
+
+static inline void _SMP_lock_Release_inline(
+ SMP_lock_Control *lock,
+ SMP_lock_Context *context
+)
+{
+#if defined(RTEMS_DEBUG)
+ _Assert( context->lock_used_for_acquire == lock );
+ context->lock_used_for_acquire = NULL;
+ _Assert( lock->owner == _SMP_lock_Who_am_I() );
+ lock->owner = SMP_LOCK_NO_OWNER;
+#else
+ (void) context;
+#endif
+ _SMP_ticket_lock_Release(
+ &lock->Ticket_lock,
+ &context->Stats_context
+ );
+}
+
+/**
+ * @brief Releases an SMP lock.
+ *
+ * @param[in] lock The SMP lock control.
+ * @param[in] context The local SMP lock context for an acquire and release
+ * pair.
+ */
+#if defined(RTEMS_SMP_LOCK_DO_NOT_INLINE)
+void _SMP_lock_Release(
+ SMP_lock_Control *lock,
+ SMP_lock_Context *context
+);
+#else
+#define _SMP_lock_Release( lock, context ) \
+ _SMP_lock_Release_inline( lock, context )
+#endif
+
+static inline void _SMP_lock_ISR_disable_and_acquire_inline(
+ SMP_lock_Control *lock,
+ SMP_lock_Context *context
+)
+{
+ _ISR_Local_disable( context->isr_level );
+ _SMP_lock_Acquire_inline( lock, context );
+}
+
+/**
+ * @brief Disables interrupts and acquires the SMP lock.
+ *
+ * @param[in] lock The SMP lock control.
+ * @param[in] context The local SMP lock context for an acquire and release
+ * pair.
+ */
+void _SMP_lock_ISR_disable_and_acquire(
+ SMP_lock_Control *lock,
+ SMP_lock_Context *context
+);
+
+static inline void _SMP_lock_Release_and_ISR_enable_inline(
+ SMP_lock_Control *lock,
+ SMP_lock_Context *context
+)
+{
+ _SMP_lock_Release_inline( lock, context );
+ _ISR_Local_enable( context->isr_level );
+}
+
+/**
+ * @brief Releases the SMP lock and enables interrupts.
+ *
+ * @param[in] lock The SMP lock control.
+ * @param[in] context The local SMP lock context for an acquire and release
+ * pair.
+ */
+#if defined(RTEMS_SMP_LOCK_DO_NOT_INLINE)
+void _SMP_lock_Release_and_ISR_enable(
+ SMP_lock_Control *lock,
+ SMP_lock_Context *context
+);
+#else
+#define _SMP_lock_Release_and_ISR_enable( lock, context ) \
+ _SMP_lock_Release_and_ISR_enable_inline( lock, context )
+#endif
+
+#if defined(RTEMS_DEBUG)
+/**
+ * @brief Returns true, if the SMP lock is owned by the current processor,
+ * otherwise false.
+ *
+ * @param[in] lock The SMP lock control.
+ */
+bool _SMP_lock_Is_owner( const SMP_lock_Control *lock );
+#endif
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* RTEMS_SMP */
+
+#endif /* _RTEMS_SCORE_SMPLOCK_H */