Fix standard (no remote barrier) parity flip bug
[urcu.git] / formal-model / urcu-controldataflow / urcu.spin
index 6ec1655654367c75e78ca547dcbaf07fe4af73ca..44bbe523e153abfe52c39ee3eac957a4b7f22f46 100644 (file)
@@ -243,7 +243,6 @@ inline smp_mb(i, j)
        }
 }
 
-
 #ifdef REMOTE_BARRIERS
 
 bit reader_barrier[NR_READERS];
@@ -269,32 +268,53 @@ inline smp_mb_recv(i, j)
        :: (reader_barrier[get_readerid()] == 1) ->
                smp_mb(i, j);
                reader_barrier[get_readerid()] = 0;
-       :: 1 -> skip;
+       :: 1 ->
+       /*
+        * Busy-looping waiting for other barrier requests are not considered as
+        * non-progress.
+        */
+#ifdef READER_PROGRESS
+progress_reader2:
+#endif
+               skip;
        :: 1 -> break;
        od;
 }
 
-inline smp_mb_send(i, j)
-{
-       smp_mb(i, j);
-       i = 0;
-       do
-       :: i < NR_READERS ->
-               reader_barrier[i] = 1;
-               do
-               :: (reader_barrier[i] == 1) -> skip;
-               :: (reader_barrier[i] == 0) -> break;
-               od;
-               i++;
-       :: i >= NR_READERS ->
-               break
-       od;
-       smp_mb(i, j);
+#ifdef WRITER_PROGRESS
+#define PROGRESS_LABEL(progressid)     progress_writer_progid_##progressid:
+#else
+#define PROGRESS_LABEL(progressid)
+#endif
+
+#define smp_mb_send(i, j, progressid)                                          \
+{                                                                              \
+       smp_mb(i, j);                                                           \
+       i = 0;                                                                  \
+       do                                                                      \
+       :: i < NR_READERS ->                                                    \
+               reader_barrier[i] = 1;                                          \
+               do                                                              \
+               :: (reader_barrier[i] == 1) ->                                  \
+               /*                                                              \
+                * Busy-looping waiting for reader barrier handling is of little\
+                * interest, given the reader has the ability to totally ignore \
+                * barrier requests.                                            \
+                */                                                             \
+PROGRESS_LABEL(progressid)                                                     \
+                       skip;                                                   \
+               :: (reader_barrier[i] == 0) -> break;                           \
+               od;                                                             \
+               i++;                                                            \
+       :: i >= NR_READERS ->                                                   \
+               break                                                           \
+       od;                                                                     \
+       smp_mb(i, j);                                                           \
 }
 
 #else
 
-#define smp_mb_send    smp_mb
+#define smp_mb_send(i, j, progressid)  smp_mb(i, j)
 #define smp_mb_reader  smp_mb
 #define smp_mb_recv(i, j)
 
@@ -887,6 +907,8 @@ progress_writer1:
                PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP);
                PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP);
                PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT);
+               /* For single flip, we need to know the current parity */
+               cur_gp_val = cur_gp_val ^ RCU_GP_CTR_BIT;
 #endif
 
                do :: 1 ->
@@ -919,7 +941,12 @@ smp_mb_send1_end:
                        ooo_mem(i);
                        /* ONLY WAITING FOR READER 0 */
                        tmp2 = READ_CACHED_VAR(urcu_active_readers[0]);
-                       cur_gp_val = cur_gp_val ^ RCU_GP_CTR_BIT;
+#ifndef SINGLE_FLIP
+                       /* In normal execution, we are always starting by
+                        * waiting for the even parity.
+                        */
+                       cur_gp_val = RCU_GP_CTR_BIT;
+#endif
                        if
                        :: (tmp2 & RCU_GP_CTR_NEST_MASK)
                                        && ((tmp2 ^ cur_gp_val) & RCU_GP_CTR_BIT) ->
@@ -973,10 +1000,9 @@ smp_mb_send2_end:
                        ooo_mem(i);
                        /* ONLY WAITING FOR READER 0 */
                        tmp2 = READ_CACHED_VAR(urcu_active_readers[0]);
-                       cur_gp_val = cur_gp_val ^ RCU_GP_CTR_BIT;
                        if
                        :: (tmp2 & RCU_GP_CTR_NEST_MASK)
-                                       && ((tmp2 ^ cur_gp_val) & RCU_GP_CTR_BIT) ->
+                                       && ((tmp2 ^ 0) & RCU_GP_CTR_BIT) ->
                                PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP);
                        :: else ->
                                PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT);
@@ -1046,18 +1072,18 @@ progress_writer2:
        /* Non-atomic parts of the loop */
        goto end;
 smp_mb_send1:
-       smp_mb_send(i, j);
+       smp_mb_send(i, j, 1);
        goto smp_mb_send1_end;
 #ifndef GEN_ERROR_WRITER_PROGRESS
 smp_mb_send2:
-       smp_mb_send(i, j);
+       smp_mb_send(i, j, 2);
        goto smp_mb_send2_end;
 smp_mb_send3:
-       smp_mb_send(i, j);
+       smp_mb_send(i, j, 3);
        goto smp_mb_send3_end;
 #endif
 smp_mb_send4:
-       smp_mb_send(i, j);
+       smp_mb_send(i, j, 4);
        goto smp_mb_send4_end;
 end:
        skip;
This page took 0.024936 seconds and 4 git commands to generate.