make urcu_free_no_wmb | tee urcu_free_no_wmb.log
make urcu_free_no_mb | tee urcu_free_no_mb.log
make urcu_free_single_flip | tee urcu_free_single_flip.log
+ make urcu_progress_writer | tee urcu_progress_writer.log
+ make urcu_progress_reader | tee urcu_progress_reader.log
+ make urcu_progress_writer_error | tee urcu_progress_writer_error.log
make asserts | tee asserts.log
make summary
summary:
@echo
@echo "Verification summary"
- @grep error *.log
+ @grep errors: *.log
asserts: clean
cat DEFINES > .input.spin
cat .input.define >> pan.ltl
spin -f "!(`cat urcu_free.ltl | grep -v ^//`)" >> pan.ltl
+# Progress checks
+
+urcu_progress_writer: clean urcu_progress_writer_ltl \
+ urcu_progress_writer_define run_weak_fair
+ cp .input.spin $@.spin.input
+ -cp .input.spin.trail $@.spin.input.trail
+
+urcu_progress_writer_define:
+ cp urcu_progress_writer.define .input.define
+
+urcu_progress_writer_ltl:
+ touch .input.define
+ cat DEFINES > pan.ltl
+ cat .input.define >> pan.ltl
+ spin -f "!(`cat urcu_progress.ltl | grep -v ^//`)" >> pan.ltl
+
+urcu_progress_reader: clean urcu_progress_reader_ltl \
+ urcu_progress_reader_define run_weak_fair
+ cp .input.spin $@.spin.input
+ -cp .input.spin.trail $@.spin.input.trail
+
+urcu_progress_reader_define:
+ cp urcu_progress_reader.define .input.define
+
+urcu_progress_reader_ltl:
+ touch .input.define
+ cat DEFINES > pan.ltl
+ cat .input.define >> pan.ltl
+ spin -f "!(`cat urcu_progress.ltl | grep -v ^//`)" >> pan.ltl
+
+urcu_progress_writer_error: clean urcu_progress_writer_error_ltl \
+ urcu_progress_writer_error_define run_weak_fair
+ cp .input.spin $@.spin.input
+ -cp .input.spin.trail $@.spin.input.trail
+
+urcu_progress_writer_error_define:
+ cp urcu_progress_writer_error.define .input.define
+
+urcu_progress_writer_error_ltl:
+ touch .input.define
+ cat DEFINES > pan.ltl
+ cat .input.define >> pan.ltl
+ spin -f "!(`cat urcu_progress.ltl | grep -v ^//`)" >> pan.ltl
+
+
+run_weak_fair: pan
+ ./pan -a -f -v -c1 -X -m10000 -w20
+
run: pan
./pan -a -v -c1 -X -m10000 -w20
/* Promela validation variables. */
#define NR_READERS 1
-#define NR_WRITERS 2
+#define NR_WRITERS 1
-#define NR_PROCS 3
+#define NR_PROCS 2
#define get_pid() (_pid)
inline wait_for_reader(tmp, id, i)
{
- tmp = READ_CACHED_VAR(urcu_active_readers_one);
- ooo_mem(i);
do
- :: (tmp & RCU_GP_CTR_NEST_MASK) && ((tmp ^ READ_CACHED_VAR(urcu_gp_ctr))
- & RCU_GP_CTR_BIT)
- ->
- ooo_mem(i);
+ :: 1 ->
+ ooo_mem(i);
+ tmp = READ_CACHED_VAR(urcu_active_readers_one);
+ if
+ :: (tmp & RCU_GP_CTR_NEST_MASK)
+ && ((tmp ^ READ_CACHED_VAR(urcu_gp_ctr))
+ & RCU_GP_CTR_BIT) ->
+#ifndef GEN_ERROR_WRITER_PROGRESS
+ smp_mb(i);
+#else
skip;
- :: else ->
+#endif
+ :: else ->
break;
+ fi;
od;
}
assert(get_pid() < NR_PROCS);
- 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);
+end_reader:
+ do
+ :: 1 ->
+ /*
+ * We do not test reader's progress here, because we are mainly
+ * interested in writer's progress. The reader never blocks
+ * anyway. We have to test for reader/writer's progress
+ * separately, otherwise we could think the writer is doing
+ * progress when it's blocked by an always progressing reader.
+ */
+#ifdef READER_PROGRESS
+progress_reader:
+#endif
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);
- read_generation = READ_CACHED_VAR(generation_ptr);
- ooo_mem(i);
- data_access = 1;
- ooo_mem(i);
- data_access = 0;
- 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);
- //smp_mc(i); /* added */
+ 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);
+ read_generation = READ_CACHED_VAR(generation_ptr);
+ ooo_mem(i);
+ data_access = 1;
+ ooo_mem(i);
+ data_access = 0;
+ 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;
}
assert(get_pid() < NR_PROCS);
- ooo_mem(i);
- atomic {
- old_gen = READ_CACHED_VAR(generation_ptr);
- WRITE_CACHED_VAR(generation_ptr, old_gen + 1);
- }
- ooo_mem(i);
-
do
- :: 1 ->
+ :: (READ_CACHED_VAR(generation_ptr) < 5) ->
+#ifdef WRITER_PROGRESS
+progress_writer1:
+#endif
+ ooo_mem(i);
atomic {
- if
- :: write_lock == 0 ->
- write_lock = 1;
- break;
- :: else ->
- skip;
- fi;
+ old_gen = READ_CACHED_VAR(generation_ptr);
+ WRITE_CACHED_VAR(generation_ptr, old_gen + 1);
}
+ ooo_mem(i);
+
+ do
+ :: 1 ->
+ atomic {
+ if
+ :: write_lock == 0 ->
+ write_lock = 1;
+ break;
+ :: else ->
+ skip;
+ fi;
+ }
+ od;
+ smp_mb(i);
+ ooo_mem(i);
+ tmp = READ_CACHED_VAR(urcu_gp_ctr);
+ ooo_mem(i);
+ WRITE_CACHED_VAR(urcu_gp_ctr, tmp ^ RCU_GP_CTR_BIT);
+ ooo_mem(i);
+ //smp_mc(i);
+ wait_for_quiescent_state(tmp, i, j);
+ //smp_mc(i);
+ #ifndef SINGLE_FLIP
+ ooo_mem(i);
+ tmp = READ_CACHED_VAR(urcu_gp_ctr);
+ ooo_mem(i);
+ WRITE_CACHED_VAR(urcu_gp_ctr, tmp ^ RCU_GP_CTR_BIT);
+ //smp_mc(i);
+ ooo_mem(i);
+ wait_for_quiescent_state(tmp, i, j);
+ #endif
+ ooo_mem(i);
+ smp_mb(i);
+ ooo_mem(i);
+ write_lock = 0;
+ /* free-up step, e.g., kfree(). */
+ atomic {
+ last_free_gen = old_gen;
+ free_done = 1;
+ }
+ :: else -> break;
od;
- smp_mb(i);
- ooo_mem(i);
- tmp = READ_CACHED_VAR(urcu_gp_ctr);
- ooo_mem(i);
- WRITE_CACHED_VAR(urcu_gp_ctr, tmp ^ RCU_GP_CTR_BIT);
- ooo_mem(i);
- //smp_mc(i);
- wait_for_quiescent_state(tmp, i, j);
- //smp_mc(i);
-#ifndef SINGLE_FLIP
- ooo_mem(i);
- tmp = READ_CACHED_VAR(urcu_gp_ctr);
- ooo_mem(i);
- WRITE_CACHED_VAR(urcu_gp_ctr, tmp ^ RCU_GP_CTR_BIT);
- //smp_mc(i);
- ooo_mem(i);
- wait_for_quiescent_state(tmp, i, j);
+ /*
+ * Given the reader loops infinitely, let the writer also busy-loop
+ * with progress here so, with weak fairness, we can test the
+ * writer's progress.
+ */
+end_writer:
+ do
+ :: 1 ->
+#ifdef WRITER_PROGRESS
+progress_writer2:
#endif
- ooo_mem(i);
- smp_mb(i);
- ooo_mem(i);
- write_lock = 0;
- /* free-up step, e.g., kfree(). */
- atomic {
- last_free_gen = old_gen;
- free_done = 1;
- }
+ skip;
+ od;
}