Add remote barrier model
[urcu.git] / formal-model / urcu / urcu.spin
index e9271f82bb58e3acdef1db13aa7226e011d48200..2282407ce5aa6c16a4891748df3923d4b492cc57 100644 (file)
        :: 1 -> skip                    \
        fi;
 
+/*
+ * Remote barriers tests the scheme where a signal (or IPI) is sent to all
+ * reader threads to promote their compiler barrier to a smp_mb().
+ */
+#ifdef REMOTE_BARRIERS
+
+inline smp_rmb_pid(i)
+{
+       atomic {
+               CACHE_READ_FROM_MEM(urcu_gp_ctr, i);
+               CACHE_READ_FROM_MEM(urcu_active_readers_one, i);
+               CACHE_READ_FROM_MEM(generation_ptr, i);
+       }
+}
+
+inline smp_wmb_pid(i)
+{
+       atomic {
+               CACHE_WRITE_TO_MEM(urcu_gp_ctr, i);
+               CACHE_WRITE_TO_MEM(urcu_active_readers_one, i);
+               CACHE_WRITE_TO_MEM(generation_ptr, i);
+       }
+}
+
+inline smp_mb_pid(i)
+{
+       atomic {
+#ifndef NO_WMB
+               smp_wmb_pid(i);
+#endif
+#ifndef NO_RMB
+               smp_rmb_pid(i);
+#endif
+               skip;
+       }
+}
+
+/*
+ * Readers do a simple barrier(), writers are doing a smp_mb() _and_ sending a
+ * signal or IPI to have all readers execute a smp_mb.
+ * We are not modeling the whole rendez-vous between readers and writers here,
+ * we just let the writer update each reader's caches remotely.
+ */
+inline smp_mb(i)
+{
+       if
+       :: get_pid() >= NR_READERS ->
+               smp_mb_pid(get_pid());
+               i = 0;
+               do
+               :: i < NR_READERS ->
+                       smp_mb_pid(i);
+                       i++;
+               :: i >= NR_READERS -> break
+               od;
+               smp_mb_pid(get_pid());
+       :: else -> skip;
+       fi;
+}
+
+#else
+
 inline smp_rmb(i)
 {
        atomic {
@@ -111,6 +173,8 @@ inline smp_mb(i)
        }
 }
 
+#endif
+
 /* Keep in sync manually with smp_rmb, wmp_wmb and ooo_mem */
 DECLARE_CACHED_VAR(byte, urcu_gp_ctr, 1);
 /* Note ! currently only one reader */
@@ -178,7 +242,7 @@ inline wait_for_quiescent_state(tmp, i, j)
 
 active [NR_READERS] proctype urcu_reader()
 {
-       byte i;
+       byte i, nest_i;
        byte tmp, tmp2;
 
        assert(get_pid() < NR_PROCS);
@@ -196,33 +260,48 @@ end_reader:
 #ifdef READER_PROGRESS
 progress_reader:
 #endif
-               ooo_mem(i);
-               tmp = READ_CACHED_VAR(urcu_active_readers_one);
-               ooo_mem(i);
-               if
-               :: (!(tmp & RCU_GP_CTR_NEST_MASK))
-                       ->
-                       tmp2 = READ_CACHED_VAR(urcu_gp_ctr);
+               nest_i = 0;
+               do
+               :: nest_i < READER_NEST_LEVEL ->
                        ooo_mem(i);
-                       WRITE_CACHED_VAR(urcu_active_readers_one, tmp2);
-               :: else ->
-                       WRITE_CACHED_VAR(urcu_active_readers_one, tmp + 1);
-               fi;
+                       tmp = READ_CACHED_VAR(urcu_active_readers_one);
+                       ooo_mem(i);
+                       if
+                       :: (!(tmp & RCU_GP_CTR_NEST_MASK))
+                               ->
+                               tmp2 = READ_CACHED_VAR(urcu_gp_ctr);
+                               ooo_mem(i);
+                               WRITE_CACHED_VAR(urcu_active_readers_one, tmp2);
+                       :: else ->
+                               WRITE_CACHED_VAR(urcu_active_readers_one,
+                                                tmp + 1);
+                       fi;
+                       ooo_mem(i);
+                       smp_mb(i);
+                       nest_i++;
+               :: nest_i >= READER_NEST_LEVEL -> break;
+               od;
+
                ooo_mem(i);
-               smp_mb(i);
                read_generation = READ_CACHED_VAR(generation_ptr);
                ooo_mem(i);
                data_access = 1;
                ooo_mem(i);
                data_access = 0;
+
+               nest_i = 0;
+               do
+               :: nest_i < READER_NEST_LEVEL ->
+                       ooo_mem(i);
+                       smp_mb(i);
+                       ooo_mem(i);
+                       tmp2 = READ_CACHED_VAR(urcu_active_readers_one);
+                       ooo_mem(i);
+                       WRITE_CACHED_VAR(urcu_active_readers_one, tmp2 - 1);
+                       nest_i++;
+               :: nest_i >= READER_NEST_LEVEL -> break;
+               od;
                ooo_mem(i);
-               smp_mb(i);
-               ooo_mem(i);
-               tmp2 = READ_CACHED_VAR(urcu_active_readers_one);
-               ooo_mem(i);
-               WRITE_CACHED_VAR(urcu_active_readers_one, tmp2 - 1);
-               ooo_mem(i);
-               //wakeup_all(i);
                //smp_mc(i);    /* added */
        od;
 }
@@ -271,7 +350,7 @@ progress_writer1:
                //smp_mc(i);
                wait_for_quiescent_state(tmp, i, j);
                //smp_mc(i);
-       #ifndef SINGLE_FLIP
+#ifndef SINGLE_FLIP
                ooo_mem(i);
                tmp = READ_CACHED_VAR(urcu_gp_ctr);
                ooo_mem(i);
@@ -279,7 +358,7 @@ progress_writer1:
                //smp_mc(i);
                ooo_mem(i);
                wait_for_quiescent_state(tmp, i, j);
-       #endif
+#endif
                ooo_mem(i);
                smp_mb(i);
                ooo_mem(i);
This page took 0.024683 seconds and 4 git commands to generate.