[PATCH 2/2] add smprwlock implementation based on phase-fairness lock
WeiY
wei.a.yang at gmail.com
Sat Aug 31 01:49:18 UTC 2013
---
cpukit/score/Makefile.am | 1 +
cpukit/score/include/rtems/score/smprwlock.h | 219 ++++++++++++++++++++++++++
cpukit/score/preinstall.am | 4 +
3 files changed, 224 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..0781f80
--- /dev/null
+++ b/cpukit/score/include/rtems/score/smprwlock.h
@@ -0,0 +1,219 @@
+/**
+ * @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.
+ *
+ * Phase-fair reader writer locks is a new class of reader-writer locks.
+ * Phase-fair rw lock has the following properties:
+ * 1. Reader phases and writer phases alternate.
+ * 2. Writers are subject to FIFO ordering, but only with regard to other
+ * writers.
+ * 3. At the start of each reader phase, all currently-unsatisfied read
+ * requests are satisfied (exactly one write request is satisfied at
+ * the start of a writer phase)
+ * 4. And during a reader phase, newly-issued read requests are satisfied
+ * only if there are no unsatisfied write requests pending.
+ *
+ * In some sense, phase-fair locks can be understood as being a reader
+ * preference lock when held by a writer, and being a writer preference
+ * lock when held by readers, i.e., readers and writers are “polite” and
+ * yield to each other. For example:
+ *
+ * 1. T1-> thread1 issues a read request then satisfied.
+ * 2. T2-> thread2 issues a write request then unsatisfied(because thread1
+ * in read phase).
+ * 3. T3-> thread3 issues a read request then unsatisfied(because thread2
+ * writer already wait).
+ * 4. T4-> thread4 issues a write request then unsatisfied(wait in FIFO order
+ * regard to thread2)
+ * 5. T5-> thread1 releases read lock and then thread2 write request satisfied.
+ * 6. T6-> thread5 issues a read request then unsatisfied.
+ * 7. T7-> thread2 releases write lock and then thread3 and thread5 read
+ * request satisfied at the same time.
+ * 8. T8-> thread3 and thread5 release their read lock, then thread1 write
+ * request satisfied.
+ *
+ * Reference:
+ *
+ * 1: http://www.mpi-sws.org/~bbb/papers/pdf/rtsj11.pdf
+ * Brandenburg, B. and Anderson, J. 2010. Spin-Based
+ * Reader-Writer Synchronization for Multiprocessor Real-Time Systems
+ *
+ * 2: http://concurrencykit.org/cgit/cgit.cgi/ck/tree/include/ck_pflock.h
+ *
+ * @{
+ */
+
+/**
+ * @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