X-Git-Url: http://git.liburcu.org/?p=urcu.git;a=blobdiff_plain;f=formal-model%2Furcu.spin;h=3e184576d7d39e7b458192936ad0194299d56611;hp=611464b3eb660b61d6269b5c64210afe6754d950;hb=ba59a0c7b244a0939a2298fc76a9002436ef9674;hpb=f321bf383dd9b5940b31e4db6c9e18a5abaa0213 diff --git a/formal-model/urcu.spin b/formal-model/urcu.spin index 611464b..3e18457 100644 --- a/formal-model/urcu.spin +++ b/formal-model/urcu.spin @@ -27,6 +27,10 @@ bit free = 0; /* Has RCU reclamation happened, e.g., kfree()? */ bit need_mb = 0; /* =1 says need reader mb, =0 for reader response. */ byte reader_progress[4]; /* Count of read-side statement executions. */ +bit reader_done = 0; + /* =0 says reader still running, =1 says done. */ +bit updater_done = 0; + /* =0 says updater still running, =1 says done. */ /* urcu definitions and variables, taken straight from the algorithm. */ @@ -50,7 +54,7 @@ proctype urcu_reader() do :: need_mb == 1 -> need_mb = 0; - :: 1 -> skip; + :: !updater_done -> skip; :: 1 -> break; od; @@ -92,7 +96,7 @@ proctype urcu_reader() reader_progress[2] + reader_progress[3] == 0) && need_mb == 1 -> need_mb = 0; - :: 1 -> skip; + :: !updater_done -> skip; :: 1 -> break; od; urcu_active_readers = tmp; @@ -150,7 +154,7 @@ proctype urcu_reader() do :: need_mb == 1 -> need_mb = 0; - :: 1 -> skip; + :: !updater_done -> skip; :: 1 -> break; od; :: else -> skip; @@ -167,11 +171,14 @@ proctype urcu_reader() od; assert((tmp_free == 0) || (tmp_removed == 1)); + /* Reader has completed. */ + reader_done = 1; + /* Process any late-arriving memory-barrier requests. */ do :: need_mb == 1 -> need_mb = 0; - :: 1 -> skip; + :: !updater_done -> skip; :: 1 -> break; od; } @@ -180,10 +187,38 @@ proctype urcu_reader() proctype urcu_updater() { + /* prior synchronize_rcu(), second counter flip. */ + need_mb = 1; + do + :: need_mb == 1 -> skip; + :: need_mb == 0 -> break; + od; + urcu_gp_ctr = urcu_gp_ctr + RCU_GP_CTR_BIT; + need_mb = 1; + do + :: need_mb == 1 -> skip; + :: need_mb == 0 -> break; + od; + do + :: 1 -> + if + :: (urcu_active_readers & RCU_GP_CTR_NEST_MASK) != 0 && + (urcu_active_readers & ~RCU_GP_CTR_NEST_MASK) != + (urcu_gp_ctr & ~RCU_GP_CTR_NEST_MASK) -> + skip; + :: else -> break; + fi; + od; + need_mb = 1; + do + :: need_mb == 1 -> skip; + :: need_mb == 0 -> break; + od; + /* Removal statement, e.g., list_del_rcu(). */ removed = 1; - /* synchronize_rcu(), first counter flip. */ + /* current synchronize_rcu(), first counter flip. */ need_mb = 1; do :: need_mb == 1 -> skip; @@ -197,15 +232,13 @@ proctype urcu_updater() od; do :: 1 -> - printf("urcu_gp_ctr=%x urcu_active_readers=%x\n", urcu_gp_ctr, urcu_active_readers); - printf("urcu_gp_ctr&0x7f=%x urcu_active_readers&0x7f=%x\n", urcu_gp_ctr & ~RCU_GP_CTR_NEST_MASK, urcu_active_readers & ~RCU_GP_CTR_NEST_MASK); if :: (urcu_active_readers & RCU_GP_CTR_NEST_MASK) != 0 && (urcu_active_readers & ~RCU_GP_CTR_NEST_MASK) != (urcu_gp_ctr & ~RCU_GP_CTR_NEST_MASK) -> skip; :: else -> break; - fi + fi; od; need_mb = 1; do @@ -213,10 +246,7 @@ proctype urcu_updater() :: need_mb == 0 -> break; od; - /* Erroneous removal statement, e.g., list_del_rcu(). */ - /* removed = 1; */ - - /* synchronize_rcu(), second counter flip. */ + /* current synchronize_rcu(), second counter flip. */ need_mb = 1; do :: need_mb == 1 -> skip; @@ -230,8 +260,6 @@ proctype urcu_updater() od; do :: 1 -> - printf("urcu_gp_ctr=%x urcu_active_readers=%x\n", urcu_gp_ctr, urcu_active_readers); - printf("urcu_gp_ctr&0x7f=%x urcu_active_readers&0x7f=%x\n", urcu_gp_ctr & ~RCU_GP_CTR_NEST_MASK, urcu_active_readers & ~RCU_GP_CTR_NEST_MASK); if :: (urcu_active_readers & RCU_GP_CTR_NEST_MASK) != 0 && (urcu_active_readers & ~RCU_GP_CTR_NEST_MASK) != @@ -248,6 +276,12 @@ proctype urcu_updater() /* free-up step, e.g., kfree(). */ free = 1; + + /* + * Signal updater done, ending any otherwise-infinite loops + * in the reading process. + */ + updater_done = 1; } /*