[PATCH 2/6] add smprwlock implementation based on phase-fairness lock
WeiY
wei.a.yang at gmail.com
Mon Aug 19 15:39:44 UTC 2013
---
cpukit/score/Makefile.am | 1 +
cpukit/score/include/rtems/score/smprwlock.h | 181 ++++++++++++++++++++++++++
cpukit/score/preinstall.am | 4 +
3 files changed, 186 insertions(+)
create mode 100644 cpukit/score/include/rtems/score/smprwlock.h
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index 7cde82c..dbbaad9 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -82,6 +82,7 @@ include_rtems_score_HEADERS += include/rtems/score/basedefs.h
if ATOMIC
include_rtems_score_HEADERS += include/rtems/score/atomic.h
include_rtems_score_HEADERS += include/rtems/score/cpustdatomic.h
+include_rtems_score_HEADERS += include/rtems/score/smprwlock.h
endif
if HAS_PTHREADS
diff --git a/cpukit/score/include/rtems/score/smprwlock.h b/cpukit/score/include/rtems/score/smprwlock.h
new file mode 100644
index 0000000..a38b26e
--- /dev/null
+++ b/cpukit/score/include/rtems/score/smprwlock.h
@@ -0,0 +1,181 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreSMPRWlock
+ *
+ * @brief SMP Lock API
+ */
+
+/*
+ * COPYRIGHT (c) 2012-2013 Deng Hengyi.
+ *
+ * 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_SMPRWLOCK_H
+#define _RTEMS_SCORE_SMPRWLOCK_H
+
+#include <rtems/score/cpuopts.h>
+
+#if defined( RTEMS_SMP )
+
+#include <rtems/rtems/atomic.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup ScoreSMPRWlock SMP Locks
+ *
+ * @ingroup Score
+ *
+ * The SMP rw lock implementation is architecture dependent. Now the rw lock
+ * is based on the implementation of phase-fairness lock. The phase-fairness
+ * lock use atomic ops to implement. So the architectures which do not support
+ * atomic ops will not use it.
+ *
+ * @{
+ */
+
+/**
+ * @brief SMP rw lock control.
+ *
+ * This is used by phase-fairness lock.
+ */
+typedef struct {
+ Atomic_Uint rin;
+ Atomic_Uint rout;
+ Atomic_Uint win;
+ Atomic_Uint wout;
+} SMP_rwlock_Control;
+
+/**
+ * @brief SMP rw lock control macro.
+ */
+#define SMP_RWLOCK_LSB 0xFFFFFFF0
+#define SMP_RWLOCK_RINC 0x100 /* Reader increment value. */
+#define SMP_RWLOCK_WBITS 0x3 /* Writer bits in reader. */
+#define SMP_RWLOCK_PRES 0x2 /* Writer present bit. */
+#define SMP_RWLOCK_PHID 0x1 /* Phase ID bit. */
+
+/**
+ * @brief SMP rwlock control initializer for static initialization.
+ */
+#define SMP_RWLOCK_INITIALIZER { ATOMIC_VAR_INITIALIZER( 0 ), \
+ ATOMIC_VAR_INITIALIZER( 0 ), \
+ ATOMIC_VAR_INITIALIZER( 0 ), \
+ ATOMIC_VAR_INITIALIZER( 0 ) }
+
+/**
+ * @brief Initializes a SMP rwlock control.
+ *
+ * Concurrent initialization leads to unpredictable results.
+ *
+ * @param[out] lock The SMP rwlock control.
+ */
+static inline void _SMP_rwlock_Initialize( SMP_rwlock_Control *lock )
+{
+ _Atomic_Init_uint( &(lock->rin), 0 );
+ _Atomic_Init_uint( &(lock->rout), 0 );
+ _Atomic_Init_uint( &(lock->win), 0 );
+ _Atomic_Init_uint( &(lock->wout), 0 );
+}
+
+/**
+ * @brief Acquires a SMP rwlock for read.
+ *
+ * This function will implementation phase-fairness read lock.
+ *
+ * @param[in,out] lock The SMP rwlock control.
+ */
+static inline void _SMP_rwlock_Acquire_read( SMP_rwlock_Control *lock )
+{
+ uint_fast32_t w;
+
+ /*
+ * If no writer is present, then the operation has completed
+ * successfully.
+ */
+ w = _Atomic_Fetch_add_uint(&lock->rin, SMP_RWLOCK_RINC, ATOMIC_ORDER_ACQUIRE)
+ & SMP_RWLOCK_WBITS;
+ if (w == 0)
+ return;
+
+ /* Wait for current write phase to complete. */
+ while ((_Atomic_Load_uint(&lock->rin, ATOMIC_ORDER_ACQUIRE)
+ & SMP_RWLOCK_WBITS) == w);
+
+ return;
+}
+
+/**
+ * @brief Releases a SMP rwlock for read.
+ *
+ * @param[in,out] lock The SMP rwlock control.
+ */
+static inline void _SMP_rwlock_Release_read( SMP_rwlock_Control *lock )
+{
+ _Atomic_Fetch_add_uint(&lock->rout, SMP_RWLOCK_RINC, ATOMIC_ORDER_RELEASE);
+
+ return;
+}
+
+/**
+ * @brief Acquires a SMP rwlock for write.
+ *
+ * This function will implementation phase-fairness write lock.
+ *
+ * @param[in,out] lock The SMP rwlock control.
+ */
+static inline void _SMP_rwlock_Acquire_write( SMP_rwlock_Control *lock )
+{
+ uint_fast32_t ticket;
+
+ /* Acquire ownership of write-phase. */
+ ticket = _Atomic_Fetch_add_uint(&lock->win, 1, ATOMIC_ORDER_RELEASE);
+
+ while (_Atomic_Load_uint(&lock->wout, ATOMIC_ORDER_ACQUIRE) != ticket);
+
+ /*
+ * Acquire ticket on read-side in order to allow them
+ * to flush. Indicates to any incoming reader that a
+ * write-phase is pending.
+ */
+ ticket = _Atomic_Fetch_add_uint(&lock->rin,
+ (ticket & SMP_RWLOCK_PHID) | SMP_RWLOCK_PRES,
+ ATOMIC_ORDER_RELEASE);
+
+ /* Wait for any pending readers to flush. */
+ while (_Atomic_Load_uint(&lock->rout, ATOMIC_ORDER_ACQUIRE) != ticket);
+
+ return;
+}
+
+/**
+ * @brief Releases a SMP rwlock for write.
+ *
+ * @param[in,out] lock The SMP rwlock control.
+ */
+static inline void _SMP_rwlock_Release_write( SMP_rwlock_Control *lock )
+{
+ /* Migrate from write phase to read phase. */
+ _Atomic_Fetch_and_uint(&lock->rin, SMP_RWLOCK_LSB, ATOMIC_ORDER_RELEASE);
+
+ /* Allow other writers to continue. */
+ _Atomic_Fetch_add_uint(&lock->wout, 1, ATOMIC_ORDER_RELEASE);
+
+ return;
+}
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* defined( RTEMS_SMP ) */
+
+#endif /* _RTEMS_SCORE_SMPRWLOCK_H */
diff --git a/cpukit/score/preinstall.am b/cpukit/score/preinstall.am
index 80fad5b..22659af 100644
--- a/cpukit/score/preinstall.am
+++ b/cpukit/score/preinstall.am
@@ -307,6 +307,10 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/atomic.h
$(PROJECT_INCLUDE)/rtems/score/cpustdatomic.h: include/rtems/score/cpustdatomic.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpustdatomic.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpustdatomic.h
+
+$(PROJECT_INCLUDE)/rtems/score/smprwlock.h: include/rtems/score/smprwlock.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/smprwlock.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/smprwlock.h
endif
if HAS_PTHREADS
$(PROJECT_INCLUDE)/rtems/score/corespinlock.h: include/rtems/score/corespinlock.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
--
1.7.9.5
More information about the devel
mailing list