[PATCH 2/6] add smprwlock implementation based on phase-fairness lock

WeiY wei.a.yang at gmail.com
Sun Aug 25 13:45:42 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 c9d2d47..c0b7939 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -86,6 +86,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..e35ec83
--- /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_INITIALIZER_UINT( 0 ), \
+                                 ATOMIC_INITIALIZER_UINT( 0 ), \
+                                 ATOMIC_INITIALIZER_UINT( 0 ), \
+                                 ATOMIC_INITIALIZER_UINT( 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 79a18b5..3c22c8e 100644
--- a/cpukit/score/preinstall.am
+++ b/cpukit/score/preinstall.am
@@ -323,6 +323,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