[PATCH] score: Add an SMP sequence lock implementation

Sebastian Huber sebastian.huber at embedded-brains.de
Wed Jun 8 13:37:10 UTC 2016


---
 cpukit/score/Makefile.am                      |   1 +
 cpukit/score/include/rtems/score/smplockseq.h | 173 +++++++++++++++
 cpukit/score/preinstall.am                    |   4 +
 testsuites/smptests/smplock01/init.c          |  60 ++++-
 testsuites/smptests/smplock01/smplock01.scn   | 306 ++++++++++++++++++++++++--
 5 files changed, 520 insertions(+), 24 deletions(-)
 create mode 100644 cpukit/score/include/rtems/score/smplockseq.h

diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index 29e822d..cf63696 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -131,6 +131,7 @@ include_rtems_score_HEADERS += include/rtems/score/schedulerpriorityaffinitysmp.
 include_rtems_score_HEADERS += include/rtems/score/schedulersimplesmp.h
 include_rtems_score_HEADERS += include/rtems/score/schedulerstrongapa.h
 include_rtems_score_HEADERS += include/rtems/score/smplockmcs.h
+include_rtems_score_HEADERS += include/rtems/score/smplockseq.h
 include_rtems_score_HEADERS += include/rtems/score/smplockstats.h
 include_rtems_score_HEADERS += include/rtems/score/smplockticket.h
 endif
diff --git a/cpukit/score/include/rtems/score/smplockseq.h b/cpukit/score/include/rtems/score/smplockseq.h
new file mode 100644
index 0000000..6fe7b7a
--- /dev/null
+++ b/cpukit/score/include/rtems/score/smplockseq.h
@@ -0,0 +1,173 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreSMPLock
+ *
+ * @brief SMP Lock API
+ */
+
+/*
+ * Copyright (c) 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_SMPLOCKSEQ_H
+#define _RTEMS_SCORE_SMPLOCKSEQ_H
+
+#include <rtems/score/cpuopts.h>
+
+#if defined(RTEMS_SMP)
+
+#include <rtems/score/atomic.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @addtogroup ScoreSMPLock
+ *
+ * @{
+ */
+
+/**
+ * @brief SMP sequence lock control.
+ *
+ * The sequence lock offers a consistent data set for readers in the presence
+ * of at most one concurrent writer.  Due to the read-modify-write operation in
+ * _SMP_sequence_lock_Read_retry() the data corresponding to the last written
+ * sequence number is observed.  To allow multiple writers an additional SMP
+ * lock is necessary to serialize writes.
+ *
+ * See also Hans-J. Boehm, HP Laboratories,
+ * "Can Seqlocks Get Along With Programming Language Memory Models?",
+ * http://www.hpl.hp.com/techreports/2012/HPL-2012-68.pdf
+ */
+typedef struct {
+  /**
+   * @brief The sequence number.
+   *
+   * An odd value indicates that a write is in progress.
+   */
+  Atomic_Uint sequence;
+} SMP_sequence_lock_Control;
+
+/**
+ * @brief SMP sequence lock control initializer for static initialization.
+ */
+#define SMP_SEQUENCE_LOCK_INITIALIZER { ATOMIC_INITIALIZER_UINT( 0 ) }
+
+/**
+ * @brief Initializes an SMP sequence lock.
+ *
+ * Concurrent initialization leads to unpredictable results.
+ *
+ * @param lock The SMP sequence lock control.
+ */
+static inline void _SMP_sequence_lock_Initialize( SMP_sequence_lock_Control *lock )
+{
+  _Atomic_Init_uint( &lock->sequence, 0 );
+}
+
+/**
+ * @brief Destroys an SMP sequence lock.
+ *
+ * Concurrent destruction leads to unpredictable results.
+ *
+ * @param lock The SMP sequence lock control.
+ */
+static inline void _SMP_sequence_lock_Destroy( SMP_sequence_lock_Control *lock )
+{
+  (void) lock;
+}
+
+/**
+ * @brief Begins an SMP sequence lock write operation.
+ *
+ * This function will not disable interrupts.  The caller must ensure that the
+ * current thread of execution is not interrupted indefinite since this would
+ * starve readers.
+ *
+ * @param lock The SMP sequence lock control.
+ *
+ * @return The current sequence number.
+ */
+static inline unsigned int _SMP_sequence_lock_Write_begin(
+  SMP_sequence_lock_Control *lock
+)
+{
+  unsigned int seq;
+
+  seq = _Atomic_Load_uint( &lock->sequence, ATOMIC_ORDER_RELAXED );
+  _Atomic_Store_uint( &lock->sequence, seq + 1, ATOMIC_ORDER_RELAXED );
+
+  /* There is no atomic store with acquire/release semantics */
+  _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
+
+  return seq;
+}
+
+/**
+ * @brief Ends an SMP sequence lock write operation.
+ *
+ * @param lock The SMP sequence lock control.
+ * @param seq The sequence number returned by _SMP_sequence_lock_Write_begin().
+ */
+static inline void _SMP_sequence_lock_Write_end(
+  SMP_sequence_lock_Control *lock,
+  unsigned int               seq
+)
+{
+  _Atomic_Store_uint( &lock->sequence, seq + 2, ATOMIC_ORDER_RELEASE );
+}
+
+/**
+ * @brief Begins an SMP sequence lock read operation.
+ *
+ * This function will not disable interrupts.
+ *
+ * @param lock The SMP sequence lock control.
+ *
+ * @return The current sequence number.
+ */
+static inline unsigned int _SMP_sequence_lock_Read_begin(
+  const SMP_sequence_lock_Control *lock
+)
+{
+  return _Atomic_Load_uint( &lock->sequence, ATOMIC_ORDER_ACQUIRE );
+}
+
+/**
+ * @brief Ends an SMP sequence lock read operation and indicates if a retry is
+ * necessary.
+ *
+ * @param lock The SMP sequence lock control.
+ * @param seq The sequence number returned by _SMP_sequence_lock_Read_begin().
+ *
+ * @retval true The read operation must be retried with a call to
+ *   _SMP_sequence_lock_Read_begin().
+ * @retval false Otherwise.
+ */
+static inline bool _SMP_sequence_lock_Read_retry(
+  SMP_sequence_lock_Control *lock,
+  unsigned int               seq
+)
+{
+  unsigned int seq2;
+
+  seq2 = _Atomic_Fetch_add_uint( &lock->sequence, 0, ATOMIC_ORDER_RELEASE );
+  return seq != seq2 || seq % 2 != 0;
+}
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* RTEMS_SMP */
+
+#endif /* _RTEMS_SCORE_SMPLOCKSEQ_H */
diff --git a/cpukit/score/preinstall.am b/cpukit/score/preinstall.am
index 2ed07b9..308b502 100644
--- a/cpukit/score/preinstall.am
+++ b/cpukit/score/preinstall.am
@@ -459,6 +459,10 @@ $(PROJECT_INCLUDE)/rtems/score/smplockmcs.h: include/rtems/score/smplockmcs.h $(
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/smplockmcs.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/smplockmcs.h
 
+$(PROJECT_INCLUDE)/rtems/score/smplockseq.h: include/rtems/score/smplockseq.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/smplockseq.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/smplockseq.h
+
 $(PROJECT_INCLUDE)/rtems/score/smplockstats.h: include/rtems/score/smplockstats.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/smplockstats.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/smplockstats.h
diff --git a/testsuites/smptests/smplock01/init.c b/testsuites/smptests/smplock01/init.c
index 5eeb1ca..62397a3 100644
--- a/testsuites/smptests/smplock01/init.c
+++ b/testsuites/smptests/smplock01/init.c
@@ -18,6 +18,7 @@
 
 #include <rtems/score/smplock.h>
 #include <rtems/score/smplockmcs.h>
+#include <rtems/score/smplockseq.h>
 #include <rtems/score/smpbarrier.h>
 #include <rtems/score/atomic.h>
 #include <rtems.h>
@@ -30,7 +31,7 @@ const char rtems_test_name[] = "SMPLOCK 1";
 
 #define CPU_COUNT 32
 
-#define TEST_COUNT 10
+#define TEST_COUNT 11
 
 typedef enum {
   INITIAL,
@@ -50,6 +51,11 @@ typedef struct {
   SMP_lock_Stats mcs_stats;
 #endif
   SMP_MCS_lock_Control mcs_lock;
+  SMP_sequence_lock_Control seq_lock;
+  char unused_space_for_cache_line_separation_0[128];
+  int a;
+  char unused_space_for_cache_line_separation_1[128];
+  int b;
 } global_context;
 
 static global_context context = {
@@ -59,7 +65,8 @@ static global_context context = {
 #if defined(RTEMS_PROFILING)
   .mcs_stats = SMP_LOCK_STATS_INITIALIZER("global MCS"),
 #endif
-  .mcs_lock = SMP_MCS_LOCK_INITIALIZER
+  .mcs_lock = SMP_MCS_LOCK_INITIALIZER,
+  .seq_lock = SMP_SEQUENCE_LOCK_INITIALIZER
 };
 
 static const char * const test_names[TEST_COUNT] = {
@@ -72,7 +79,8 @@ static const char * const test_names[TEST_COUNT] = {
   "local ticket lock with global counter",
   "local MCS lock with global counter",
   "global ticket lock with busy section",
-  "global MCS lock with busy section"
+  "global MCS lock with busy section",
+  "sequence lock"
 };
 
 static void stop_test_timer(rtems_id timer_id, void *arg)
@@ -355,6 +363,49 @@ static void test_9_body(
   ctx->test_counter[test][cpu_self] = counter;
 }
 
+static void test_10_body(
+  int test,
+  global_context *ctx,
+  SMP_barrier_State *bs,
+  unsigned int cpu_count,
+  unsigned int cpu_self
+)
+{
+  unsigned long counter = 0;
+  unsigned long seq;
+
+  if (cpu_self == 0) {
+    while (assert_state(ctx, START_TEST)) {
+      seq = _SMP_sequence_lock_Write_begin(&ctx->seq_lock);
+
+      ctx->a = counter;
+      ctx->b = counter;
+
+      _SMP_sequence_lock_Write_end(&ctx->seq_lock, seq);
+
+      ++counter;
+    }
+  } else {
+    while (assert_state(ctx, START_TEST)) {
+      unsigned long a;
+      unsigned long b;
+
+      do {
+        seq = _SMP_sequence_lock_Read_begin(&ctx->seq_lock);
+
+        a = ctx->a;
+        b = ctx->b;
+
+      } while (_SMP_sequence_lock_Read_retry(&ctx->seq_lock, seq));
+
+      ++counter;
+      rtems_test_assert(a == b);
+    }
+  }
+
+  ctx->test_counter[test][cpu_self] = counter;
+}
+
 static const test_body test_bodies[TEST_COUNT] = {
   test_0_body,
   test_1_body,
@@ -365,7 +416,8 @@ static const test_body test_bodies[TEST_COUNT] = {
   test_6_body,
   test_7_body,
   test_8_body,
-  test_9_body
+  test_9_body,
+  test_10_body
 };
 
 static void run_tests(
diff --git a/testsuites/smptests/smplock01/smplock01.scn b/testsuites/smptests/smplock01/smplock01.scn
index d9189f9..b13bab0 100644
--- a/testsuites/smptests/smplock01/smplock01.scn
+++ b/testsuites/smptests/smplock01/smplock01.scn
@@ -1,22 +1,288 @@
 *** BEGIN OF TEST SMPLOCK 1 ***
-aquire global lock with local counter
-        processor 0, local counter 15964
-        processor 1, local counter 99982377
-        global counter 0, sum of local counter 99998341
-aquire global lock with global counter
-        processor 0, local counter 166073
-        processor 1, local counter 99569103
-        global counter 99735176, sum of local counter 99735176
-aquire local lock with local counter
-        processor 0, local counter 148133948
-        processor 1, local counter 148148108
-        global counter 0, sum of local counter 296282056
-aquire local lock with global counter
-        processor 0, local counter 55938783
-        processor 1, local counter 55951781
-        global counter 55951781, sum of local counter 111890564
-aquire global lock with busy section
-        processor 0, local counter 10694328
-        processor 1, local counter 10694346
-        global counter 0, sum of local counter 21388674
+global ticket lock with local counter
+        processor 0, local counter 830091
+        processor 1, local counter 830090
+        processor 2, local counter 830091
+        processor 3, local counter 830091
+        processor 4, local counter 830091
+        processor 5, local counter 830091
+        processor 6, local counter 830091
+        processor 7, local counter 830091
+        processor 8, local counter 830089
+        processor 9, local counter 830088
+        processor 10, local counter 830090
+        processor 11, local counter 830090
+        processor 12, local counter 830090
+        processor 13, local counter 830092
+        processor 14, local counter 830093
+        processor 15, local counter 830092
+        processor 16, local counter 830092
+        processor 17, local counter 830092
+        processor 18, local counter 830089
+        processor 19, local counter 830092
+        processor 20, local counter 830090
+        processor 21, local counter 830090
+        processor 22, local counter 830090
+        processor 23, local counter 830092
+        global counter 0, sum of local counter 19922178
+global MCS lock with local counter
+        processor 0, local counter 1579723
+        processor 1, local counter 1580054
+        processor 2, local counter 1579890
+        processor 3, local counter 1579777
+        processor 4, local counter 1579884
+        processor 5, local counter 1580005
+        processor 6, local counter 1578632
+        processor 7, local counter 1578637
+        processor 8, local counter 1578774
+        processor 9, local counter 1578759
+        processor 10, local counter 1580282
+        processor 11, local counter 1579885
+        processor 12, local counter 1580378
+        processor 13, local counter 1580043
+        processor 14, local counter 1580115
+        processor 15, local counter 1580113
+        processor 16, local counter 1579911
+        processor 17, local counter 1579993
+        processor 18, local counter 1580032
+        processor 19, local counter 1579588
+        processor 20, local counter 1580049
+        processor 21, local counter 1580048
+        processor 22, local counter 1578484
+        processor 23, local counter 1580013
+        global counter 0, sum of local counter 37913069
+global ticket lock with global counter
+        processor 0, local counter 784729
+        processor 1, local counter 784730
+        processor 2, local counter 784730
+        processor 3, local counter 784730
+        processor 4, local counter 784731
+        processor 5, local counter 784730
+        processor 6, local counter 784731
+        processor 7, local counter 784730
+        processor 8, local counter 784731
+        processor 9, local counter 784729
+        processor 10, local counter 784729
+        processor 11, local counter 784730
+        processor 12, local counter 784731
+        processor 13, local counter 784729
+        processor 14, local counter 784728
+        processor 15, local counter 784730
+        processor 16, local counter 784729
+        processor 17, local counter 784730
+        processor 18, local counter 784730
+        processor 19, local counter 784729
+        processor 20, local counter 784729
+        processor 21, local counter 784729
+        processor 22, local counter 784729
+        processor 23, local counter 784731
+        global counter 18833514, sum of local counter 18833514
+global MCS lock with global counter
+        processor 0, local counter 947856
+        processor 1, local counter 947857
+        processor 2, local counter 947857
+        processor 3, local counter 947855
+        processor 4, local counter 947858
+        processor 5, local counter 947857
+        processor 6, local counter 947856
+        processor 7, local counter 947856
+        processor 8, local counter 947856
+        processor 9, local counter 947856
+        processor 10, local counter 947857
+        processor 11, local counter 947856
+        processor 12, local counter 947855
+        processor 13, local counter 947857
+        processor 14, local counter 947857
+        processor 15, local counter 947855
+        processor 16, local counter 947856
+        processor 17, local counter 947855
+        processor 18, local counter 947858
+        processor 19, local counter 947857
+        processor 20, local counter 947858
+        processor 21, local counter 947857
+        processor 22, local counter 947857
+        processor 23, local counter 947857
+        global counter 22748556, sum of local counter 22748556
+local ticket lock with local counter
+        processor 0, local counter 77155869
+        processor 1, local counter 77158831
+        processor 2, local counter 77081105
+        processor 3, local counter 77082737
+        processor 4, local counter 77075777
+        processor 5, local counter 77076154
+        processor 6, local counter 77065268
+        processor 7, local counter 77066500
+        processor 8, local counter 77106686
+        processor 9, local counter 77107321
+        processor 10, local counter 77060207
+        processor 11, local counter 77062079
+        processor 12, local counter 77059638
+        processor 13, local counter 77059931
+        processor 14, local counter 77056750
+        processor 15, local counter 77057813
+        processor 16, local counter 76659137
+        processor 17, local counter 76659205
+        processor 18, local counter 76669140
+        processor 19, local counter 76670415
+        processor 20, local counter 76674221
+        processor 21, local counter 76674630
+        processor 22, local counter 76434805
+        processor 23, local counter 76434361
+        global counter 0, sum of local counter 1846208580
+local MCS lock with local counter
+        processor 0, local counter 44963740
+        processor 1, local counter 45045357
+        processor 2, local counter 45023035
+        processor 3, local counter 45021994
+        processor 4, local counter 44912701
+        processor 5, local counter 44951749
+        processor 6, local counter 45090697
+        processor 7, local counter 45089463
+        processor 8, local counter 45015619
+        processor 9, local counter 45088716
+        processor 10, local counter 45064955
+        processor 11, local counter 45063568
+        processor 12, local counter 44966963
+        processor 13, local counter 45002743
+        processor 14, local counter 45127830
+        processor 15, local counter 45126512
+        processor 16, local counter 44947194
+        processor 17, local counter 44992882
+        processor 18, local counter 45006760
+        processor 19, local counter 45005553
+        processor 20, local counter 44880447
+        processor 21, local counter 44889042
+        processor 22, local counter 45036454
+        processor 23, local counter 45036288
+        global counter 0, sum of local counter 1080350262
+local ticket lock with global counter
+        processor 0, local counter 3962116
+        processor 1, local counter 3963441
+        processor 2, local counter 3963482
+        processor 3, local counter 3963367
+        processor 4, local counter 3962978
+        processor 5, local counter 3963102
+        processor 6, local counter 3962979
+        processor 7, local counter 3962911
+        processor 8, local counter 3962974
+        processor 9, local counter 3963125
+        processor 10, local counter 3963056
+        processor 11, local counter 3963093
+        processor 12, local counter 3962996
+        processor 13, local counter 3963100
+        processor 14, local counter 3963096
+        processor 15, local counter 3963028
+        processor 16, local counter 3967076
+        processor 17, local counter 3967251
+        processor 18, local counter 3967222
+        processor 19, local counter 3967093
+        processor 20, local counter 3972862
+        processor 21, local counter 3972917
+        processor 22, local counter 3967217
+        processor 23, local counter 3967220
+        global counter 7095791, sum of local counter 95157702
+local MCS lock with global counter
+        processor 0, local counter 3849478
+        processor 1, local counter 3860113
+        processor 2, local counter 3966891
+        processor 3, local counter 3966750
+        processor 4, local counter 3973618
+        processor 5, local counter 4014013
+        processor 6, local counter 3914674
+        processor 7, local counter 3914601
+        processor 8, local counter 3910536
+        processor 9, local counter 3924908
+        processor 10, local counter 3995362
+        processor 11, local counter 3995130
+        processor 12, local counter 3909912
+        processor 13, local counter 3923977
+        processor 14, local counter 3995941
+        processor 15, local counter 3995667
+        processor 16, local counter 3842753
+        processor 17, local counter 3852728
+        processor 18, local counter 3956029
+        processor 19, local counter 3955977
+        processor 20, local counter 3961870
+        processor 21, local counter 4001067
+        processor 22, local counter 3911767
+        processor 23, local counter 3911724
+        global counter 8503087, sum of local counter 94505486
+global ticket lock with busy section
+        processor 0, local counter 614377
+        processor 1, local counter 614376
+        processor 2, local counter 614377
+        processor 3, local counter 614377
+        processor 4, local counter 614377
+        processor 5, local counter 614378
+        processor 6, local counter 614377
+        processor 7, local counter 614377
+        processor 8, local counter 614377
+        processor 9, local counter 614376
+        processor 10, local counter 614378
+        processor 11, local counter 614377
+        processor 12, local counter 614377
+        processor 13, local counter 614377
+        processor 14, local counter 614377
+        processor 15, local counter 614376
+        processor 16, local counter 614377
+        processor 17, local counter 614377
+        processor 18, local counter 614377
+        processor 19, local counter 614378
+        processor 20, local counter 614378
+        processor 21, local counter 614377
+        processor 22, local counter 614377
+        processor 23, local counter 614377
+        global counter 0, sum of local counter 14745049
+global MCS lock with busy section
+        processor 0, local counter 552660
+        processor 1, local counter 552661
+        processor 2, local counter 552659
+        processor 3, local counter 552659
+        processor 4, local counter 552660
+        processor 5, local counter 552659
+        processor 6, local counter 552659
+        processor 7, local counter 552660
+        processor 8, local counter 552660
+        processor 9, local counter 552660
+        processor 10, local counter 552660
+        processor 11, local counter 552659
+        processor 12, local counter 552660
+        processor 13, local counter 552659
+        processor 14, local counter 552660
+        processor 15, local counter 552661
+        processor 16, local counter 552660
+        processor 17, local counter 552659
+        processor 18, local counter 552660
+        processor 19, local counter 552661
+        processor 20, local counter 552660
+        processor 21, local counter 552661
+        processor 22, local counter 552660
+        processor 23, local counter 552661
+        global counter 0, sum of local counter 13263838
+sequence lock
+        processor 0, local counter 12138641
+        processor 1, local counter 8
+        processor 2, local counter 64
+        processor 3, local counter 89
+        processor 4, local counter 208
+        processor 5, local counter 227
+        processor 6, local counter 69
+        processor 7, local counter 82
+        processor 8, local counter 2019
+        processor 9, local counter 2017
+        processor 10, local counter 1914
+        processor 11, local counter 2008
+        processor 12, local counter 1890
+        processor 13, local counter 1902
+        processor 14, local counter 1734
+        processor 15, local counter 1701
+        processor 16, local counter 2198
+        processor 17, local counter 2176
+        processor 18, local counter 2011
+        processor 19, local counter 2047
+        processor 20, local counter 2072
+        processor 21, local counter 2084
+        processor 22, local counter 1866
+        processor 23, local counter 1849
+        global counter 0, sum of local counter 12170876
 *** END OF TEST SMPLOCK 1 ***
-- 
1.8.4.5



More information about the devel mailing list