From: Mathieu Desnoyers Date: Sat, 30 May 2009 22:31:09 +0000 (-0400) Subject: Verification run #1, ipi and no-ipi results X-Git-Tag: v0.1~202 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=dbf6928575dc30b5d8602b9a50ca385670f26ff1;p=userspace-rcu.git Verification run #1, ipi and no-ipi results Signed-off-by: Mathieu Desnoyers --- diff --git a/formal-model/results/urcu-controldataflow-ipi/.input.spin b/formal-model/results/urcu-controldataflow-ipi/.input.spin new file mode 100644 index 0000000..4640ac9 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/.input.spin @@ -0,0 +1,1239 @@ + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-ipi/DEFINES b/formal-model/results/urcu-controldataflow-ipi/DEFINES new file mode 100644 index 0000000..980fad6 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/DEFINES @@ -0,0 +1,14 @@ + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS diff --git a/formal-model/results/urcu-controldataflow-ipi/Makefile b/formal-model/results/urcu-controldataflow-ipi/Makefile new file mode 100644 index 0000000..de47dff --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/Makefile @@ -0,0 +1,170 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# Copyright (C) Mathieu Desnoyers, 2009 +# +# Authors: Mathieu Desnoyers + +#CFLAGS=-DSAFETY +#for multi-core verif, 15.5GB shared mem, use files if full +#CFLAGS=-DHASH64 -DMEMLIM=15500 -DNCORE=2 +#CFLAGS=-DHASH64 -DCOLLAPSE -DMA=88 -DMEMLIM=15500 -DNCORE=8 + +#liveness +#CFLAGS=-DHASH64 -DCOLLAPSE -DMA=88 +CFLAGS=-DHASH64 + +SPINFILE=urcu.spin + +default: + make urcu_free | tee urcu_free.log + make urcu_free_no_mb | tee urcu_free_no_mb.log + make urcu_free_no_rmb | tee urcu_free_no_rmb.log + make urcu_free_no_wmb | tee urcu_free_no_wmb.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 + +#show trail : spin -v -t -N pan.ltl input.spin +# after each individual make. + +summary: + @echo + @echo "Verification summary" + @grep errors: *.log + +asserts: clean + cat DEFINES > .input.spin + cat ${SPINFILE} >> .input.spin + rm -f .input.spin.trail + spin -a -X .input.spin + gcc -O2 -w ${CFLAGS} -DSAFETY -o pan pan.c + ./pan -v -c1 -X -m10000000 -w20 + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free: clean urcu_free_ltl run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_nested: clean urcu_free_ltl urcu_free_nested_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_nested_define: + cp urcu_free_nested.define .input.define + +urcu_free_no_rmb: clean urcu_free_ltl urcu_free_no_rmb_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_no_rmb_define: + cp urcu_free_no_rmb.define .input.define + +urcu_free_no_wmb: clean urcu_free_ltl urcu_free_no_wmb_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_no_wmb_define: + cp urcu_free_no_wmb.define .input.define + +urcu_free_no_mb: clean urcu_free_ltl urcu_free_no_mb_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_no_mb_define: + cp urcu_free_no_mb.define .input.define + +urcu_free_single_flip: clean urcu_free_ltl urcu_free_single_flip_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_single_flip_define: + cp urcu_free_single_flip.define .input.define + +urcu_free_ltl: + touch .input.define + cat .input.define >> pan.ltl + cat DEFINES >> 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 .input.define > pan.ltl + cat DEFINES >> 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 .input.define > pan.ltl + cat DEFINES >> 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 .input.define > pan.ltl + cat DEFINES >> pan.ltl + spin -f "!(`cat urcu_progress.ltl | grep -v ^//`)" >> pan.ltl + + +run_weak_fair: pan + ./pan -a -f -v -c1 -X -m10000000 -w20 + +run: pan + ./pan -a -v -c1 -X -m10000000 -w20 + +pan: pan.c + gcc -O2 -w ${CFLAGS} -o pan pan.c + +pan.c: pan.ltl ${SPINFILE} + cat .input.define > .input.spin + cat DEFINES >> .input.spin + cat ${SPINFILE} >> .input.spin + rm -f .input.spin.trail + spin -a -X -N pan.ltl .input.spin + +.PHONY: clean default distclean summary +clean: + rm -f pan* trail.out .input.spin* *.spin.trail .input.define +distclean: + rm -f *.trail *.input *.log diff --git a/formal-model/results/urcu-controldataflow-ipi/asserts.log b/formal-model/results/urcu-controldataflow-ipi/asserts.log new file mode 100644 index 0000000..98a269c --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/asserts.log @@ -0,0 +1,522 @@ +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +cat DEFINES > .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -DSAFETY -o pan pan.c +./pan -v -c1 -X -m10000000 -w20 +Depth= 5832 States= 1e+06 Transitions= 1.25e+08 Memory= 542.717 t= 123 R= 8e+03 +Depth= 5832 States= 2e+06 Transitions= 4.09e+08 Memory= 618.986 t= 417 R= 5e+03 +Depth= 5832 States= 3e+06 Transitions= 6.64e+08 Memory= 695.256 t= 685 R= 4e+03 +pan: resizing hashtable to -w22.. done +Depth= 5832 States= 4e+06 Transitions= 1.15e+09 Memory= 802.647 t= 1.2e+03 R= 3e+03 +Depth= 5832 States= 5e+06 Transitions= 1.46e+09 Memory= 878.916 t= 1.52e+03 R= 3e+03 +Depth= 5832 States= 6e+06 Transitions= 1.66e+09 Memory= 955.186 t= 1.72e+03 R= 3e+03 +Depth= 5832 States= 7e+06 Transitions= 1.86e+09 Memory= 1031.455 t= 1.93e+03 R= 4e+03 +Depth= 5832 States= 8e+06 Transitions= 2.13e+09 Memory= 1107.822 t= 2.22e+03 R= 4e+03 +Depth= 5832 States= 9e+06 Transitions= 2.38e+09 Memory= 1184.092 t= 2.49e+03 R= 4e+03 +pan: resizing hashtable to -w24.. done +Depth= 5832 States= 1e+07 Transitions= 2.87e+09 Memory= 1384.455 t= 3e+03 R= 3e+03 +Depth= 5832 States= 1.1e+07 Transitions= 3.15e+09 Memory= 1460.725 t= 3.29e+03 R= 3e+03 +Depth= 5832 States= 1.2e+07 Transitions= 3.42e+09 Memory= 1536.994 t= 3.57e+03 R= 3e+03 +Depth= 5832 States= 1.3e+07 Transitions= 3.62e+09 Memory= 1613.361 t= 3.77e+03 R= 3e+03 +Depth= 5832 States= 1.4e+07 Transitions= 3.84e+09 Memory= 1689.631 t= 3.99e+03 R= 4e+03 +Depth= 5832 States= 1.5e+07 Transitions= 4.13e+09 Memory= 1765.901 t= 4.29e+03 R= 3e+03 + +(Spin Version 5.1.7 -- 23 December 2008) + + Partial Order Reduction + +Full statespace search for: + never claim - (none specified) + assertion violations + + cycle checks - (disabled by -DSAFETY) + invalid end states + + +State-vector 72 byte, depth reached 5832, errors: 0 + 15444143 states, stored +4.2527754e+09 states, matched +4.2682195e+09 transitions (= stored+matched) +2.483245e+10 atomic steps +hash conflicts: 2.790927e+09 (resolved) + +Stats on memory usage (in Megabytes): + 1472.868 equivalent memory usage for states (stored*(State-vector + overhead)) + 1214.135 actual memory usage for states (compression: 82.43%) + state-vector as stored = 54 byte + 28 byte overhead + 128.000 memory used for hash table (-w24) + 457.764 memory used for DFS stack (-m10000000) + 1799.787 total actual memory usage + +unreached in proctype urcu_reader + line 249, ".input.spin", state 30, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 257, ".input.spin", state 52, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, ".input.spin", state 61, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, ".input.spin", state 77, "(1)" + line 230, ".input.spin", state 85, "(1)" + line 234, ".input.spin", state 97, "(1)" + line 238, ".input.spin", state 105, "(1)" + line 394, ".input.spin", state 131, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 163, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 177, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 196, "(1)" + line 420, ".input.spin", state 226, "(1)" + line 424, ".input.spin", state 239, "(1)" + line 669, ".input.spin", state 260, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 394, ".input.spin", state 267, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 299, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 313, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 332, "(1)" + line 420, ".input.spin", state 362, "(1)" + line 424, ".input.spin", state 375, "(1)" + line 394, ".input.spin", state 396, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 428, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 442, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 461, "(1)" + line 420, ".input.spin", state 491, "(1)" + line 424, ".input.spin", state 504, "(1)" + line 394, ".input.spin", state 527, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 394, ".input.spin", state 529, "(1)" + line 394, ".input.spin", state 530, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 394, ".input.spin", state 530, "else" + line 394, ".input.spin", state 533, "(1)" + line 398, ".input.spin", state 541, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 543, "(1)" + line 398, ".input.spin", state 544, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 398, ".input.spin", state 544, "else" + line 398, ".input.spin", state 547, "(1)" + line 398, ".input.spin", state 548, "(1)" + line 398, ".input.spin", state 548, "(1)" + line 396, ".input.spin", state 553, "((i<1))" + line 396, ".input.spin", state 553, "((i>=1))" + line 403, ".input.spin", state 559, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 561, "(1)" + line 403, ".input.spin", state 562, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 403, ".input.spin", state 562, "else" + line 403, ".input.spin", state 565, "(1)" + line 403, ".input.spin", state 566, "(1)" + line 403, ".input.spin", state 566, "(1)" + line 407, ".input.spin", state 573, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 575, "(1)" + line 407, ".input.spin", state 576, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 407, ".input.spin", state 576, "else" + line 407, ".input.spin", state 579, "(1)" + line 407, ".input.spin", state 580, "(1)" + line 407, ".input.spin", state 580, "(1)" + line 405, ".input.spin", state 585, "((i<2))" + line 405, ".input.spin", state 585, "((i>=2))" + line 411, ".input.spin", state 592, "(1)" + line 411, ".input.spin", state 593, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 411, ".input.spin", state 593, "else" + line 411, ".input.spin", state 596, "(1)" + line 411, ".input.spin", state 597, "(1)" + line 411, ".input.spin", state 597, "(1)" + line 415, ".input.spin", state 605, "(1)" + line 415, ".input.spin", state 606, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 415, ".input.spin", state 606, "else" + line 415, ".input.spin", state 609, "(1)" + line 415, ".input.spin", state 610, "(1)" + line 415, ".input.spin", state 610, "(1)" + line 413, ".input.spin", state 615, "((i<1))" + line 413, ".input.spin", state 615, "((i>=1))" + line 420, ".input.spin", state 622, "(1)" + line 420, ".input.spin", state 623, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 420, ".input.spin", state 623, "else" + line 420, ".input.spin", state 626, "(1)" + line 420, ".input.spin", state 627, "(1)" + line 420, ".input.spin", state 627, "(1)" + line 424, ".input.spin", state 635, "(1)" + line 424, ".input.spin", state 636, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 424, ".input.spin", state 636, "else" + line 424, ".input.spin", state 639, "(1)" + line 424, ".input.spin", state 640, "(1)" + line 424, ".input.spin", state 640, "(1)" + line 422, ".input.spin", state 645, "((i<2))" + line 422, ".input.spin", state 645, "((i>=2))" + line 429, ".input.spin", state 649, "(1)" + line 429, ".input.spin", state 649, "(1)" + line 669, ".input.spin", state 652, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 669, ".input.spin", state 653, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 669, ".input.spin", state 654, "(1)" + line 394, ".input.spin", state 661, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 693, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 707, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 726, "(1)" + line 420, ".input.spin", state 756, "(1)" + line 424, ".input.spin", state 769, "(1)" + line 394, ".input.spin", state 797, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 394, ".input.spin", state 799, "(1)" + line 394, ".input.spin", state 800, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 394, ".input.spin", state 800, "else" + line 394, ".input.spin", state 803, "(1)" + line 398, ".input.spin", state 811, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 813, "(1)" + line 398, ".input.spin", state 814, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 398, ".input.spin", state 814, "else" + line 398, ".input.spin", state 817, "(1)" + line 398, ".input.spin", state 818, "(1)" + line 398, ".input.spin", state 818, "(1)" + line 396, ".input.spin", state 823, "((i<1))" + line 396, ".input.spin", state 823, "((i>=1))" + line 403, ".input.spin", state 829, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 831, "(1)" + line 403, ".input.spin", state 832, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 403, ".input.spin", state 832, "else" + line 403, ".input.spin", state 835, "(1)" + line 403, ".input.spin", state 836, "(1)" + line 403, ".input.spin", state 836, "(1)" + line 407, ".input.spin", state 843, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 845, "(1)" + line 407, ".input.spin", state 846, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 407, ".input.spin", state 846, "else" + line 407, ".input.spin", state 849, "(1)" + line 407, ".input.spin", state 850, "(1)" + line 407, ".input.spin", state 850, "(1)" + line 405, ".input.spin", state 855, "((i<2))" + line 405, ".input.spin", state 855, "((i>=2))" + line 411, ".input.spin", state 862, "(1)" + line 411, ".input.spin", state 863, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 411, ".input.spin", state 863, "else" + line 411, ".input.spin", state 866, "(1)" + line 411, ".input.spin", state 867, "(1)" + line 411, ".input.spin", state 867, "(1)" + line 415, ".input.spin", state 875, "(1)" + line 415, ".input.spin", state 876, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 415, ".input.spin", state 876, "else" + line 415, ".input.spin", state 879, "(1)" + line 415, ".input.spin", state 880, "(1)" + line 415, ".input.spin", state 880, "(1)" + line 413, ".input.spin", state 885, "((i<1))" + line 413, ".input.spin", state 885, "((i>=1))" + line 420, ".input.spin", state 892, "(1)" + line 420, ".input.spin", state 893, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 420, ".input.spin", state 893, "else" + line 420, ".input.spin", state 896, "(1)" + line 420, ".input.spin", state 897, "(1)" + line 420, ".input.spin", state 897, "(1)" + line 424, ".input.spin", state 905, "(1)" + line 424, ".input.spin", state 906, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 424, ".input.spin", state 906, "else" + line 424, ".input.spin", state 909, "(1)" + line 424, ".input.spin", state 910, "(1)" + line 424, ".input.spin", state 910, "(1)" + line 429, ".input.spin", state 919, "(1)" + line 429, ".input.spin", state 919, "(1)" + line 394, ".input.spin", state 926, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 394, ".input.spin", state 928, "(1)" + line 394, ".input.spin", state 929, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 394, ".input.spin", state 929, "else" + line 394, ".input.spin", state 932, "(1)" + line 398, ".input.spin", state 940, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 942, "(1)" + line 398, ".input.spin", state 943, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 398, ".input.spin", state 943, "else" + line 398, ".input.spin", state 946, "(1)" + line 398, ".input.spin", state 947, "(1)" + line 398, ".input.spin", state 947, "(1)" + line 396, ".input.spin", state 952, "((i<1))" + line 396, ".input.spin", state 952, "((i>=1))" + line 403, ".input.spin", state 958, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 960, "(1)" + line 403, ".input.spin", state 961, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 403, ".input.spin", state 961, "else" + line 403, ".input.spin", state 964, "(1)" + line 403, ".input.spin", state 965, "(1)" + line 403, ".input.spin", state 965, "(1)" + line 407, ".input.spin", state 972, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 974, "(1)" + line 407, ".input.spin", state 975, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 407, ".input.spin", state 975, "else" + line 407, ".input.spin", state 978, "(1)" + line 407, ".input.spin", state 979, "(1)" + line 407, ".input.spin", state 979, "(1)" + line 405, ".input.spin", state 984, "((i<2))" + line 405, ".input.spin", state 984, "((i>=2))" + line 411, ".input.spin", state 991, "(1)" + line 411, ".input.spin", state 992, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 411, ".input.spin", state 992, "else" + line 411, ".input.spin", state 995, "(1)" + line 411, ".input.spin", state 996, "(1)" + line 411, ".input.spin", state 996, "(1)" + line 415, ".input.spin", state 1004, "(1)" + line 415, ".input.spin", state 1005, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 415, ".input.spin", state 1005, "else" + line 415, ".input.spin", state 1008, "(1)" + line 415, ".input.spin", state 1009, "(1)" + line 415, ".input.spin", state 1009, "(1)" + line 413, ".input.spin", state 1014, "((i<1))" + line 413, ".input.spin", state 1014, "((i>=1))" + line 420, ".input.spin", state 1021, "(1)" + line 420, ".input.spin", state 1022, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 420, ".input.spin", state 1022, "else" + line 420, ".input.spin", state 1025, "(1)" + line 420, ".input.spin", state 1026, "(1)" + line 420, ".input.spin", state 1026, "(1)" + line 424, ".input.spin", state 1034, "(1)" + line 424, ".input.spin", state 1035, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 424, ".input.spin", state 1035, "else" + line 424, ".input.spin", state 1038, "(1)" + line 424, ".input.spin", state 1039, "(1)" + line 424, ".input.spin", state 1039, "(1)" + line 422, ".input.spin", state 1044, "((i<2))" + line 422, ".input.spin", state 1044, "((i>=2))" + line 429, ".input.spin", state 1048, "(1)" + line 429, ".input.spin", state 1048, "(1)" + line 677, ".input.spin", state 1052, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 394, ".input.spin", state 1057, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 1089, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 1103, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 1122, "(1)" + line 420, ".input.spin", state 1152, "(1)" + line 424, ".input.spin", state 1165, "(1)" + line 394, ".input.spin", state 1189, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 1221, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 1235, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 1254, "(1)" + line 420, ".input.spin", state 1284, "(1)" + line 424, ".input.spin", state 1297, "(1)" + line 394, ".input.spin", state 1322, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 1354, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 1368, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 1387, "(1)" + line 420, ".input.spin", state 1417, "(1)" + line 424, ".input.spin", state 1430, "(1)" + line 394, ".input.spin", state 1451, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 1483, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 1497, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 1516, "(1)" + line 420, ".input.spin", state 1546, "(1)" + line 424, ".input.spin", state 1559, "(1)" + line 394, ".input.spin", state 1585, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 1617, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 1631, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 1650, "(1)" + line 420, ".input.spin", state 1680, "(1)" + line 424, ".input.spin", state 1693, "(1)" + line 394, ".input.spin", state 1714, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 1746, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 1760, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 1779, "(1)" + line 420, ".input.spin", state 1809, "(1)" + line 424, ".input.spin", state 1822, "(1)" + line 394, ".input.spin", state 1846, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 1878, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 1892, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 1911, "(1)" + line 420, ".input.spin", state 1941, "(1)" + line 424, ".input.spin", state 1954, "(1)" + line 716, ".input.spin", state 1975, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 394, ".input.spin", state 1982, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 2014, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 2028, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 2047, "(1)" + line 420, ".input.spin", state 2077, "(1)" + line 424, ".input.spin", state 2090, "(1)" + line 394, ".input.spin", state 2111, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 2143, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 2157, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 2176, "(1)" + line 420, ".input.spin", state 2206, "(1)" + line 424, ".input.spin", state 2219, "(1)" + line 394, ".input.spin", state 2242, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 394, ".input.spin", state 2244, "(1)" + line 394, ".input.spin", state 2245, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 394, ".input.spin", state 2245, "else" + line 394, ".input.spin", state 2248, "(1)" + line 398, ".input.spin", state 2256, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 2258, "(1)" + line 398, ".input.spin", state 2259, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 398, ".input.spin", state 2259, "else" + line 398, ".input.spin", state 2262, "(1)" + line 398, ".input.spin", state 2263, "(1)" + line 398, ".input.spin", state 2263, "(1)" + line 396, ".input.spin", state 2268, "((i<1))" + line 396, ".input.spin", state 2268, "((i>=1))" + line 403, ".input.spin", state 2274, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 2276, "(1)" + line 403, ".input.spin", state 2277, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 403, ".input.spin", state 2277, "else" + line 403, ".input.spin", state 2280, "(1)" + line 403, ".input.spin", state 2281, "(1)" + line 403, ".input.spin", state 2281, "(1)" + line 407, ".input.spin", state 2288, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 2290, "(1)" + line 407, ".input.spin", state 2291, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 407, ".input.spin", state 2291, "else" + line 407, ".input.spin", state 2294, "(1)" + line 407, ".input.spin", state 2295, "(1)" + line 407, ".input.spin", state 2295, "(1)" + line 405, ".input.spin", state 2300, "((i<2))" + line 405, ".input.spin", state 2300, "((i>=2))" + line 411, ".input.spin", state 2307, "(1)" + line 411, ".input.spin", state 2308, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 411, ".input.spin", state 2308, "else" + line 411, ".input.spin", state 2311, "(1)" + line 411, ".input.spin", state 2312, "(1)" + line 411, ".input.spin", state 2312, "(1)" + line 415, ".input.spin", state 2320, "(1)" + line 415, ".input.spin", state 2321, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 415, ".input.spin", state 2321, "else" + line 415, ".input.spin", state 2324, "(1)" + line 415, ".input.spin", state 2325, "(1)" + line 415, ".input.spin", state 2325, "(1)" + line 413, ".input.spin", state 2330, "((i<1))" + line 413, ".input.spin", state 2330, "((i>=1))" + line 420, ".input.spin", state 2337, "(1)" + line 420, ".input.spin", state 2338, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 420, ".input.spin", state 2338, "else" + line 420, ".input.spin", state 2341, "(1)" + line 420, ".input.spin", state 2342, "(1)" + line 420, ".input.spin", state 2342, "(1)" + line 424, ".input.spin", state 2350, "(1)" + line 424, ".input.spin", state 2351, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 424, ".input.spin", state 2351, "else" + line 424, ".input.spin", state 2354, "(1)" + line 424, ".input.spin", state 2355, "(1)" + line 424, ".input.spin", state 2355, "(1)" + line 422, ".input.spin", state 2360, "((i<2))" + line 422, ".input.spin", state 2360, "((i>=2))" + line 429, ".input.spin", state 2364, "(1)" + line 429, ".input.spin", state 2364, "(1)" + line 716, ".input.spin", state 2367, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 716, ".input.spin", state 2368, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 716, ".input.spin", state 2369, "(1)" + line 394, ".input.spin", state 2376, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 2408, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 2422, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 2441, "(1)" + line 420, ".input.spin", state 2471, "(1)" + line 424, ".input.spin", state 2484, "(1)" + line 394, ".input.spin", state 2511, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 2543, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 2557, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 2576, "(1)" + line 420, ".input.spin", state 2606, "(1)" + line 424, ".input.spin", state 2619, "(1)" + line 394, ".input.spin", state 2640, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 2672, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 2686, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 2705, "(1)" + line 420, ".input.spin", state 2735, "(1)" + line 424, ".input.spin", state 2748, "(1)" + line 226, ".input.spin", state 2781, "(1)" + line 234, ".input.spin", state 2801, "(1)" + line 238, ".input.spin", state 2809, "(1)" + line 226, ".input.spin", state 2824, "(1)" + line 234, ".input.spin", state 2844, "(1)" + line 238, ".input.spin", state 2852, "(1)" + line 876, ".input.spin", state 2869, "-end-" + (278 of 2869 states) +unreached in proctype urcu_writer + line 394, ".input.spin", state 18, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 32, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 50, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 83, "(1)" + line 415, ".input.spin", state 96, "(1)" + line 420, ".input.spin", state 113, "(1)" + line 249, ".input.spin", state 149, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, ".input.spin", state 158, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, ".input.spin", state 171, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 394, ".input.spin", state 211, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 225, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 243, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 257, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 276, "(1)" + line 415, ".input.spin", state 289, "(1)" + line 420, ".input.spin", state 306, "(1)" + line 424, ".input.spin", state 319, "(1)" + line 398, ".input.spin", state 356, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 374, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 388, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 415, ".input.spin", state 420, "(1)" + line 420, ".input.spin", state 437, "(1)" + line 424, ".input.spin", state 450, "(1)" + line 398, ".input.spin", state 494, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 512, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 526, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 415, ".input.spin", state 558, "(1)" + line 420, ".input.spin", state 575, "(1)" + line 424, ".input.spin", state 588, "(1)" + line 398, ".input.spin", state 623, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 641, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 655, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 415, ".input.spin", state 687, "(1)" + line 420, ".input.spin", state 704, "(1)" + line 424, ".input.spin", state 717, "(1)" + line 398, ".input.spin", state 754, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 772, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 786, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 415, ".input.spin", state 818, "(1)" + line 420, ".input.spin", state 835, "(1)" + line 424, ".input.spin", state 848, "(1)" + line 249, ".input.spin", state 903, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, ".input.spin", state 912, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, ".input.spin", state 927, "(1)" + line 261, ".input.spin", state 934, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, ".input.spin", state 950, "(1)" + line 230, ".input.spin", state 958, "(1)" + line 234, ".input.spin", state 970, "(1)" + line 238, ".input.spin", state 978, "(1)" + line 249, ".input.spin", state 1009, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, ".input.spin", state 1018, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, ".input.spin", state 1031, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, ".input.spin", state 1040, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, ".input.spin", state 1056, "(1)" + line 230, ".input.spin", state 1064, "(1)" + line 234, ".input.spin", state 1076, "(1)" + line 238, ".input.spin", state 1084, "(1)" + line 253, ".input.spin", state 1110, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, ".input.spin", state 1123, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, ".input.spin", state 1132, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, ".input.spin", state 1148, "(1)" + line 230, ".input.spin", state 1156, "(1)" + line 234, ".input.spin", state 1168, "(1)" + line 238, ".input.spin", state 1176, "(1)" + line 249, ".input.spin", state 1207, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, ".input.spin", state 1216, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, ".input.spin", state 1229, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, ".input.spin", state 1238, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, ".input.spin", state 1254, "(1)" + line 230, ".input.spin", state 1262, "(1)" + line 234, ".input.spin", state 1274, "(1)" + line 238, ".input.spin", state 1282, "(1)" + line 253, ".input.spin", state 1308, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, ".input.spin", state 1321, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, ".input.spin", state 1330, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, ".input.spin", state 1346, "(1)" + line 230, ".input.spin", state 1354, "(1)" + line 234, ".input.spin", state 1366, "(1)" + line 238, ".input.spin", state 1374, "(1)" + line 249, ".input.spin", state 1405, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, ".input.spin", state 1414, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, ".input.spin", state 1427, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, ".input.spin", state 1436, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, ".input.spin", state 1452, "(1)" + line 230, ".input.spin", state 1460, "(1)" + line 234, ".input.spin", state 1472, "(1)" + line 238, ".input.spin", state 1480, "(1)" + line 253, ".input.spin", state 1506, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, ".input.spin", state 1519, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, ".input.spin", state 1528, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, ".input.spin", state 1544, "(1)" + line 230, ".input.spin", state 1552, "(1)" + line 234, ".input.spin", state 1564, "(1)" + line 238, ".input.spin", state 1572, "(1)" + line 249, ".input.spin", state 1603, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, ".input.spin", state 1612, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, ".input.spin", state 1625, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, ".input.spin", state 1634, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, ".input.spin", state 1650, "(1)" + line 230, ".input.spin", state 1658, "(1)" + line 234, ".input.spin", state 1670, "(1)" + line 238, ".input.spin", state 1678, "(1)" + line 1203, ".input.spin", state 1694, "-end-" + (103 of 1694 states) +unreached in proctype :init: + (0 of 78 states) + +pan: elapsed time 4.43e+03 seconds +pan: rate 3486.0658 states/second +pan: avg transition delay 1.038e-06 usec +cp .input.spin asserts.spin.input +cp .input.spin.trail asserts.spin.input.trail diff --git a/formal-model/results/urcu-controldataflow-ipi/asserts.spin.input b/formal-model/results/urcu-controldataflow-ipi/asserts.spin.input new file mode 100644 index 0000000..4640ac9 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/asserts.spin.input @@ -0,0 +1,1239 @@ + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-ipi/references.txt b/formal-model/results/urcu-controldataflow-ipi/references.txt new file mode 100644 index 0000000..72c67a2 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/references.txt @@ -0,0 +1,13 @@ +http://spinroot.com/spin/Man/ltl.html +http://en.wikipedia.org/wiki/Linear_temporal_logic +http://www.dcs.gla.ac.uk/~muffy/MRS4-2002/lect11.ppt + +http://www.lsv.ens-cachan.fr/~gastin/ltl2ba/index.php +http://spinroot.com/spin/Man/index.html +http://spinroot.com/spin/Man/promela.html + +LTL vs CTL : + +http://spinroot.com/spin/Doc/course/lecture12.pdf p. 9, p. 15, p. 18 +http://www-i2.informatik.rwth-aachen.de/i2/fileadmin/user_upload/documents/Introduction_to_Model_Checking/mc_lec18.pdf + (downloaded) diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu.sh b/formal-model/results/urcu-controldataflow-ipi/urcu.sh new file mode 100644 index 0000000..65ff517 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# +# Compiles and runs the urcu.spin Promela model. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# Copyright (C) IBM Corporation, 2009 +# Mathieu Desnoyers, 2009 +# +# Authors: Paul E. McKenney +# Mathieu Desnoyers + +# Basic execution, without LTL clauses. See Makefile. + +spin -a urcu.spin +cc -DSAFETY -o pan pan.c +./pan -v -c1 -X -m10000000 -w21 diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu.spin b/formal-model/results/urcu-controldataflow-ipi/urcu.spin new file mode 100644 index 0000000..4fe6b9e --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu.spin @@ -0,0 +1,1225 @@ +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu.spin.bkp.b4ptr b/formal-model/results/urcu-controldataflow-ipi/urcu.spin.bkp.b4ptr new file mode 100644 index 0000000..6670f3e --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu.spin.bkp.b4ptr @@ -0,0 +1,1123 @@ +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bit { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bit cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(generation_ptr, get_pid()); + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(generation_ptr, get_pid()); + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * Busy-looping waiting for other barrier requests is not considered as + * non-progress. + */ +#ifdef READER_PROGRESS +progress_reader2: +#endif +#ifdef WRITER_PROGRESS +//progress_writer_from_reader1: +#endif + skip; + :: 1 -> + /* We choose to ignore writer's non-progress caused from the + * reader ignoring the writer's mb() requests */ +#ifdef WRITER_PROGRESS +//progress_writer_from_reader2: +#endif + break; + od; +} + +#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; \ + /* \ + * 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) \ + do \ + :: (reader_barrier[i] == 1) -> skip; \ + :: (reader_barrier[i] == 0) -> break; \ + od; \ + i++; \ + :: i >= NR_READERS -> \ + break \ + od; \ + smp_mb(i, j); \ +} + +#else + +#define smp_mb_send(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, wmp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only two readers */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* pointer generation */ +DECLARE_CACHED_VAR(byte, generation_ptr); + +byte last_free_gen = 0; +bit free_done = 0; +byte read_generation[NR_READERS]; +bit data_access[NR_READERS]; + +bit write_lock = 0; + +bit init_done = 0; + +bit sighand_exec = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(generation_ptr, get_pid()); + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(generation_ptr, get_pid()); + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + :: 1 -> skip; + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + read_generation[get_readerid()] = + READ_CACHED_VAR(generation_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + ooo_mem(i); + goto non_atomic; +non_atomic_end: + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + read_generation[get_readerid()] = + READ_CACHED_VAR(generation_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + ooo_mem(i); + goto non_atomic2; +non_atomic2_end: + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +non_atomic: + data_access[get_readerid()] = 1; + data_access[get_readerid()] = 0; + goto non_atomic_end; +non_atomic2: + data_access[get_readerid()] = 1; + data_access[get_readerid()] = 0; + goto non_atomic2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_PROC_FIRST_MB (1 << 1) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 2) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 3) +#define WRITE_PROC_FIRST_WAIT (1 << 4) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 5) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 6) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 7) +#define WRITE_PROC_SECOND_WAIT (1 << 8) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 9) + +#define WRITE_PROC_SECOND_MB (1 << 10) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 11) - 1) + +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte old_gen; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (READ_CACHED_VAR(generation_ptr) < 5) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + ooo_mem(i); + atomic { + 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; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + + write_lock = 0; + /* free-up step, e.g., kfree(). */ + atomic { + last_free_gen = old_gen; + free_done = 1; + } + :: else -> break; + od; + /* + * 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 + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(generation_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + read_generation[i] = 1; + data_access[i] = 0; + i++; + :: i >= NR_READERS -> break + od; + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free.log b/formal-model/results/urcu-controldataflow-ipi/urcu_free.log new file mode 100644 index 0000000..bcad427 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free.log @@ -0,0 +1,533 @@ +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define >> pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_free.ltl | grep -v ^//`)" >> pan.ltl +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1257) +Depth= 7192 States= 1e+06 Transitions= 1.25e+08 Memory= 550.432 t= 156 R= 6e+03 +Depth= 7192 States= 2e+06 Transitions= 4.1e+08 Memory= 634.318 t= 524 R= 4e+03 +Depth= 7192 States= 3e+06 Transitions= 6.64e+08 Memory= 718.303 t= 857 R= 3e+03 +pan: resizing hashtable to -w22.. done +Depth= 7192 States= 4e+06 Transitions= 1.15e+09 Memory= 833.311 t= 1.5e+03 R= 3e+03 +Depth= 7192 States= 5e+06 Transitions= 1.46e+09 Memory= 917.295 t= 1.9e+03 R= 3e+03 +Depth= 7192 States= 6e+06 Transitions= 1.66e+09 Memory= 1001.279 t= 2.15e+03 R= 3e+03 +Depth= 7192 States= 7e+06 Transitions= 1.86e+09 Memory= 1085.264 t= 2.42e+03 R= 3e+03 +Depth= 7192 States= 8e+06 Transitions= 2.13e+09 Memory= 1169.151 t= 2.78e+03 R= 3e+03 +Depth= 7192 States= 9e+06 Transitions= 2.38e+09 Memory= 1253.135 t= 3.1e+03 R= 3e+03 +pan: resizing hashtable to -w24.. done +Depth= 7192 States= 1e+07 Transitions= 2.87e+09 Memory= 1461.115 t= 3.74e+03 R= 3e+03 +Depth= 7192 States= 1.1e+07 Transitions= 3.15e+09 Memory= 1545.100 t= 4.1e+03 R= 3e+03 +Depth= 7192 States= 1.2e+07 Transitions= 3.42e+09 Memory= 1629.084 t= 4.46e+03 R= 3e+03 +Depth= 7192 States= 1.3e+07 Transitions= 3.62e+09 Memory= 1713.068 t= 4.71e+03 R= 3e+03 +Depth= 7192 States= 1.4e+07 Transitions= 3.84e+09 Memory= 1797.053 t= 4.98e+03 R= 3e+03 +Depth= 7192 States= 1.5e+07 Transitions= 4.13e+09 Memory= 1881.037 t= 5.36e+03 R= 3e+03 + +(Spin Version 5.1.7 -- 23 December 2008) + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness disabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 7192, errors: 0 + 15444143 states, stored +4.2528076e+09 states, matched +4.2682517e+09 transitions (= stored+matched) +2.483245e+10 atomic steps +hash conflicts: 2.7880402e+09 (resolved) + +Stats on memory usage (in Megabytes): + 1708.527 equivalent memory usage for states (stored*(State-vector + overhead)) + 1333.263 actual memory usage for states (compression: 78.04%) + state-vector as stored = 63 byte + 28 byte overhead + 128.000 memory used for hash table (-w24) + 457.764 memory used for DFS stack (-m10000000) + 1918.244 total actual memory usage + +unreached in proctype urcu_reader + line 249, "pan.___", state 30, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 52, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 61, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 77, "(1)" + line 230, "pan.___", state 85, "(1)" + line 234, "pan.___", state 97, "(1)" + line 238, "pan.___", state 105, "(1)" + line 394, "pan.___", state 131, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 163, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 177, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 196, "(1)" + line 420, "pan.___", state 226, "(1)" + line 424, "pan.___", state 239, "(1)" + line 669, "pan.___", state 260, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 394, "pan.___", state 267, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 299, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 313, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 332, "(1)" + line 420, "pan.___", state 362, "(1)" + line 424, "pan.___", state 375, "(1)" + line 394, "pan.___", state 396, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 428, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 442, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 461, "(1)" + line 420, "pan.___", state 491, "(1)" + line 424, "pan.___", state 504, "(1)" + line 394, "pan.___", state 527, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 394, "pan.___", state 529, "(1)" + line 394, "pan.___", state 530, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 394, "pan.___", state 530, "else" + line 394, "pan.___", state 533, "(1)" + line 398, "pan.___", state 541, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 543, "(1)" + line 398, "pan.___", state 544, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 398, "pan.___", state 544, "else" + line 398, "pan.___", state 547, "(1)" + line 398, "pan.___", state 548, "(1)" + line 398, "pan.___", state 548, "(1)" + line 396, "pan.___", state 553, "((i<1))" + line 396, "pan.___", state 553, "((i>=1))" + line 403, "pan.___", state 559, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 561, "(1)" + line 403, "pan.___", state 562, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 403, "pan.___", state 562, "else" + line 403, "pan.___", state 565, "(1)" + line 403, "pan.___", state 566, "(1)" + line 403, "pan.___", state 566, "(1)" + line 407, "pan.___", state 573, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, "pan.___", state 575, "(1)" + line 407, "pan.___", state 576, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 407, "pan.___", state 576, "else" + line 407, "pan.___", state 579, "(1)" + line 407, "pan.___", state 580, "(1)" + line 407, "pan.___", state 580, "(1)" + line 405, "pan.___", state 585, "((i<2))" + line 405, "pan.___", state 585, "((i>=2))" + line 411, "pan.___", state 592, "(1)" + line 411, "pan.___", state 593, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 411, "pan.___", state 593, "else" + line 411, "pan.___", state 596, "(1)" + line 411, "pan.___", state 597, "(1)" + line 411, "pan.___", state 597, "(1)" + line 415, "pan.___", state 605, "(1)" + line 415, "pan.___", state 606, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 415, "pan.___", state 606, "else" + line 415, "pan.___", state 609, "(1)" + line 415, "pan.___", state 610, "(1)" + line 415, "pan.___", state 610, "(1)" + line 413, "pan.___", state 615, "((i<1))" + line 413, "pan.___", state 615, "((i>=1))" + line 420, "pan.___", state 622, "(1)" + line 420, "pan.___", state 623, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 420, "pan.___", state 623, "else" + line 420, "pan.___", state 626, "(1)" + line 420, "pan.___", state 627, "(1)" + line 420, "pan.___", state 627, "(1)" + line 424, "pan.___", state 635, "(1)" + line 424, "pan.___", state 636, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 424, "pan.___", state 636, "else" + line 424, "pan.___", state 639, "(1)" + line 424, "pan.___", state 640, "(1)" + line 424, "pan.___", state 640, "(1)" + line 422, "pan.___", state 645, "((i<2))" + line 422, "pan.___", state 645, "((i>=2))" + line 429, "pan.___", state 649, "(1)" + line 429, "pan.___", state 649, "(1)" + line 669, "pan.___", state 652, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 669, "pan.___", state 653, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 669, "pan.___", state 654, "(1)" + line 394, "pan.___", state 661, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 693, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 707, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 726, "(1)" + line 420, "pan.___", state 756, "(1)" + line 424, "pan.___", state 769, "(1)" + line 394, "pan.___", state 797, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 394, "pan.___", state 799, "(1)" + line 394, "pan.___", state 800, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 394, "pan.___", state 800, "else" + line 394, "pan.___", state 803, "(1)" + line 398, "pan.___", state 811, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 813, "(1)" + line 398, "pan.___", state 814, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 398, "pan.___", state 814, "else" + line 398, "pan.___", state 817, "(1)" + line 398, "pan.___", state 818, "(1)" + line 398, "pan.___", state 818, "(1)" + line 396, "pan.___", state 823, "((i<1))" + line 396, "pan.___", state 823, "((i>=1))" + line 403, "pan.___", state 829, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 831, "(1)" + line 403, "pan.___", state 832, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 403, "pan.___", state 832, "else" + line 403, "pan.___", state 835, "(1)" + line 403, "pan.___", state 836, "(1)" + line 403, "pan.___", state 836, "(1)" + line 407, "pan.___", state 843, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, "pan.___", state 845, "(1)" + line 407, "pan.___", state 846, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 407, "pan.___", state 846, "else" + line 407, "pan.___", state 849, "(1)" + line 407, "pan.___", state 850, "(1)" + line 407, "pan.___", state 850, "(1)" + line 405, "pan.___", state 855, "((i<2))" + line 405, "pan.___", state 855, "((i>=2))" + line 411, "pan.___", state 862, "(1)" + line 411, "pan.___", state 863, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 411, "pan.___", state 863, "else" + line 411, "pan.___", state 866, "(1)" + line 411, "pan.___", state 867, "(1)" + line 411, "pan.___", state 867, "(1)" + line 415, "pan.___", state 875, "(1)" + line 415, "pan.___", state 876, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 415, "pan.___", state 876, "else" + line 415, "pan.___", state 879, "(1)" + line 415, "pan.___", state 880, "(1)" + line 415, "pan.___", state 880, "(1)" + line 413, "pan.___", state 885, "((i<1))" + line 413, "pan.___", state 885, "((i>=1))" + line 420, "pan.___", state 892, "(1)" + line 420, "pan.___", state 893, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 420, "pan.___", state 893, "else" + line 420, "pan.___", state 896, "(1)" + line 420, "pan.___", state 897, "(1)" + line 420, "pan.___", state 897, "(1)" + line 424, "pan.___", state 905, "(1)" + line 424, "pan.___", state 906, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 424, "pan.___", state 906, "else" + line 424, "pan.___", state 909, "(1)" + line 424, "pan.___", state 910, "(1)" + line 424, "pan.___", state 910, "(1)" + line 429, "pan.___", state 919, "(1)" + line 429, "pan.___", state 919, "(1)" + line 394, "pan.___", state 926, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 394, "pan.___", state 928, "(1)" + line 394, "pan.___", state 929, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 394, "pan.___", state 929, "else" + line 394, "pan.___", state 932, "(1)" + line 398, "pan.___", state 940, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 942, "(1)" + line 398, "pan.___", state 943, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 398, "pan.___", state 943, "else" + line 398, "pan.___", state 946, "(1)" + line 398, "pan.___", state 947, "(1)" + line 398, "pan.___", state 947, "(1)" + line 396, "pan.___", state 952, "((i<1))" + line 396, "pan.___", state 952, "((i>=1))" + line 403, "pan.___", state 958, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 960, "(1)" + line 403, "pan.___", state 961, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 403, "pan.___", state 961, "else" + line 403, "pan.___", state 964, "(1)" + line 403, "pan.___", state 965, "(1)" + line 403, "pan.___", state 965, "(1)" + line 407, "pan.___", state 972, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, "pan.___", state 974, "(1)" + line 407, "pan.___", state 975, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 407, "pan.___", state 975, "else" + line 407, "pan.___", state 978, "(1)" + line 407, "pan.___", state 979, "(1)" + line 407, "pan.___", state 979, "(1)" + line 405, "pan.___", state 984, "((i<2))" + line 405, "pan.___", state 984, "((i>=2))" + line 411, "pan.___", state 991, "(1)" + line 411, "pan.___", state 992, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 411, "pan.___", state 992, "else" + line 411, "pan.___", state 995, "(1)" + line 411, "pan.___", state 996, "(1)" + line 411, "pan.___", state 996, "(1)" + line 415, "pan.___", state 1004, "(1)" + line 415, "pan.___", state 1005, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 415, "pan.___", state 1005, "else" + line 415, "pan.___", state 1008, "(1)" + line 415, "pan.___", state 1009, "(1)" + line 415, "pan.___", state 1009, "(1)" + line 413, "pan.___", state 1014, "((i<1))" + line 413, "pan.___", state 1014, "((i>=1))" + line 420, "pan.___", state 1021, "(1)" + line 420, "pan.___", state 1022, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 420, "pan.___", state 1022, "else" + line 420, "pan.___", state 1025, "(1)" + line 420, "pan.___", state 1026, "(1)" + line 420, "pan.___", state 1026, "(1)" + line 424, "pan.___", state 1034, "(1)" + line 424, "pan.___", state 1035, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 424, "pan.___", state 1035, "else" + line 424, "pan.___", state 1038, "(1)" + line 424, "pan.___", state 1039, "(1)" + line 424, "pan.___", state 1039, "(1)" + line 422, "pan.___", state 1044, "((i<2))" + line 422, "pan.___", state 1044, "((i>=2))" + line 429, "pan.___", state 1048, "(1)" + line 429, "pan.___", state 1048, "(1)" + line 677, "pan.___", state 1052, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 394, "pan.___", state 1057, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1089, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 1103, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 1122, "(1)" + line 420, "pan.___", state 1152, "(1)" + line 424, "pan.___", state 1165, "(1)" + line 394, "pan.___", state 1189, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1221, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 1235, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 1254, "(1)" + line 420, "pan.___", state 1284, "(1)" + line 424, "pan.___", state 1297, "(1)" + line 394, "pan.___", state 1322, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1354, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 1368, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 1387, "(1)" + line 420, "pan.___", state 1417, "(1)" + line 424, "pan.___", state 1430, "(1)" + line 394, "pan.___", state 1451, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1483, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 1497, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 1516, "(1)" + line 420, "pan.___", state 1546, "(1)" + line 424, "pan.___", state 1559, "(1)" + line 394, "pan.___", state 1585, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1617, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 1631, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 1650, "(1)" + line 420, "pan.___", state 1680, "(1)" + line 424, "pan.___", state 1693, "(1)" + line 394, "pan.___", state 1714, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1746, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 1760, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 1779, "(1)" + line 420, "pan.___", state 1809, "(1)" + line 424, "pan.___", state 1822, "(1)" + line 394, "pan.___", state 1846, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1878, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 1892, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 1911, "(1)" + line 420, "pan.___", state 1941, "(1)" + line 424, "pan.___", state 1954, "(1)" + line 716, "pan.___", state 1975, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 394, "pan.___", state 1982, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 2014, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 2028, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 2047, "(1)" + line 420, "pan.___", state 2077, "(1)" + line 424, "pan.___", state 2090, "(1)" + line 394, "pan.___", state 2111, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 2143, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 2157, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 2176, "(1)" + line 420, "pan.___", state 2206, "(1)" + line 424, "pan.___", state 2219, "(1)" + line 394, "pan.___", state 2242, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 394, "pan.___", state 2244, "(1)" + line 394, "pan.___", state 2245, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 394, "pan.___", state 2245, "else" + line 394, "pan.___", state 2248, "(1)" + line 398, "pan.___", state 2256, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 2258, "(1)" + line 398, "pan.___", state 2259, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 398, "pan.___", state 2259, "else" + line 398, "pan.___", state 2262, "(1)" + line 398, "pan.___", state 2263, "(1)" + line 398, "pan.___", state 2263, "(1)" + line 396, "pan.___", state 2268, "((i<1))" + line 396, "pan.___", state 2268, "((i>=1))" + line 403, "pan.___", state 2274, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 2276, "(1)" + line 403, "pan.___", state 2277, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 403, "pan.___", state 2277, "else" + line 403, "pan.___", state 2280, "(1)" + line 403, "pan.___", state 2281, "(1)" + line 403, "pan.___", state 2281, "(1)" + line 407, "pan.___", state 2288, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, "pan.___", state 2290, "(1)" + line 407, "pan.___", state 2291, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 407, "pan.___", state 2291, "else" + line 407, "pan.___", state 2294, "(1)" + line 407, "pan.___", state 2295, "(1)" + line 407, "pan.___", state 2295, "(1)" + line 405, "pan.___", state 2300, "((i<2))" + line 405, "pan.___", state 2300, "((i>=2))" + line 411, "pan.___", state 2307, "(1)" + line 411, "pan.___", state 2308, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 411, "pan.___", state 2308, "else" + line 411, "pan.___", state 2311, "(1)" + line 411, "pan.___", state 2312, "(1)" + line 411, "pan.___", state 2312, "(1)" + line 415, "pan.___", state 2320, "(1)" + line 415, "pan.___", state 2321, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 415, "pan.___", state 2321, "else" + line 415, "pan.___", state 2324, "(1)" + line 415, "pan.___", state 2325, "(1)" + line 415, "pan.___", state 2325, "(1)" + line 413, "pan.___", state 2330, "((i<1))" + line 413, "pan.___", state 2330, "((i>=1))" + line 420, "pan.___", state 2337, "(1)" + line 420, "pan.___", state 2338, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 420, "pan.___", state 2338, "else" + line 420, "pan.___", state 2341, "(1)" + line 420, "pan.___", state 2342, "(1)" + line 420, "pan.___", state 2342, "(1)" + line 424, "pan.___", state 2350, "(1)" + line 424, "pan.___", state 2351, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 424, "pan.___", state 2351, "else" + line 424, "pan.___", state 2354, "(1)" + line 424, "pan.___", state 2355, "(1)" + line 424, "pan.___", state 2355, "(1)" + line 422, "pan.___", state 2360, "((i<2))" + line 422, "pan.___", state 2360, "((i>=2))" + line 429, "pan.___", state 2364, "(1)" + line 429, "pan.___", state 2364, "(1)" + line 716, "pan.___", state 2367, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 716, "pan.___", state 2368, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 716, "pan.___", state 2369, "(1)" + line 394, "pan.___", state 2376, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 2408, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 2422, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 2441, "(1)" + line 420, "pan.___", state 2471, "(1)" + line 424, "pan.___", state 2484, "(1)" + line 394, "pan.___", state 2511, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 2543, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 2557, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 2576, "(1)" + line 420, "pan.___", state 2606, "(1)" + line 424, "pan.___", state 2619, "(1)" + line 394, "pan.___", state 2640, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 2672, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 2686, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 2705, "(1)" + line 420, "pan.___", state 2735, "(1)" + line 424, "pan.___", state 2748, "(1)" + line 226, "pan.___", state 2781, "(1)" + line 234, "pan.___", state 2801, "(1)" + line 238, "pan.___", state 2809, "(1)" + line 226, "pan.___", state 2824, "(1)" + line 234, "pan.___", state 2844, "(1)" + line 238, "pan.___", state 2852, "(1)" + line 876, "pan.___", state 2869, "-end-" + (278 of 2869 states) +unreached in proctype urcu_writer + line 394, "pan.___", state 18, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 32, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 50, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 411, "pan.___", state 83, "(1)" + line 415, "pan.___", state 96, "(1)" + line 420, "pan.___", state 113, "(1)" + line 249, "pan.___", state 149, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 158, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 171, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 394, "pan.___", state 211, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 225, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 243, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 257, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 276, "(1)" + line 415, "pan.___", state 289, "(1)" + line 420, "pan.___", state 306, "(1)" + line 424, "pan.___", state 319, "(1)" + line 398, "pan.___", state 356, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 374, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 388, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 415, "pan.___", state 420, "(1)" + line 420, "pan.___", state 437, "(1)" + line 424, "pan.___", state 450, "(1)" + line 398, "pan.___", state 494, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 512, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 526, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 415, "pan.___", state 558, "(1)" + line 420, "pan.___", state 575, "(1)" + line 424, "pan.___", state 588, "(1)" + line 398, "pan.___", state 623, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 641, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 655, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 415, "pan.___", state 687, "(1)" + line 420, "pan.___", state 704, "(1)" + line 424, "pan.___", state 717, "(1)" + line 398, "pan.___", state 754, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 772, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 786, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 415, "pan.___", state 818, "(1)" + line 420, "pan.___", state 835, "(1)" + line 424, "pan.___", state 848, "(1)" + line 249, "pan.___", state 903, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 912, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 927, "(1)" + line 261, "pan.___", state 934, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 950, "(1)" + line 230, "pan.___", state 958, "(1)" + line 234, "pan.___", state 970, "(1)" + line 238, "pan.___", state 978, "(1)" + line 249, "pan.___", state 1009, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 1018, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 1031, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1040, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 1056, "(1)" + line 230, "pan.___", state 1064, "(1)" + line 234, "pan.___", state 1076, "(1)" + line 238, "pan.___", state 1084, "(1)" + line 253, "pan.___", state 1110, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 1123, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1132, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 1148, "(1)" + line 230, "pan.___", state 1156, "(1)" + line 234, "pan.___", state 1168, "(1)" + line 238, "pan.___", state 1176, "(1)" + line 249, "pan.___", state 1207, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 1216, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 1229, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1238, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 1254, "(1)" + line 230, "pan.___", state 1262, "(1)" + line 234, "pan.___", state 1274, "(1)" + line 238, "pan.___", state 1282, "(1)" + line 253, "pan.___", state 1308, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 1321, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1330, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 1346, "(1)" + line 230, "pan.___", state 1354, "(1)" + line 234, "pan.___", state 1366, "(1)" + line 238, "pan.___", state 1374, "(1)" + line 249, "pan.___", state 1405, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 1414, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 1427, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1436, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 1452, "(1)" + line 230, "pan.___", state 1460, "(1)" + line 234, "pan.___", state 1472, "(1)" + line 238, "pan.___", state 1480, "(1)" + line 253, "pan.___", state 1506, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 1519, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1528, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 1544, "(1)" + line 230, "pan.___", state 1552, "(1)" + line 234, "pan.___", state 1564, "(1)" + line 238, "pan.___", state 1572, "(1)" + line 249, "pan.___", state 1603, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 1612, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 1625, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1634, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 1650, "(1)" + line 230, "pan.___", state 1658, "(1)" + line 234, "pan.___", state 1670, "(1)" + line 238, "pan.___", state 1678, "(1)" + line 1203, "pan.___", state 1694, "-end-" + (103 of 1694 states) +unreached in proctype :init: + (0 of 78 states) +unreached in proctype :never: + line 1262, "pan.___", state 8, "-end-" + (1 of 8 states) + +pan: elapsed time 5.54e+03 seconds +pan: rate 2789.4684 states/second +pan: avg transition delay 1.2972e-06 usec +cp .input.spin urcu_free.spin.input +cp .input.spin.trail urcu_free.spin.input.trail diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free.ltl b/formal-model/results/urcu-controldataflow-ipi/urcu_free.ltl new file mode 100644 index 0000000..6be1be9 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free.ltl @@ -0,0 +1 @@ +[] (!read_poison) diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free.spin.input b/formal-model/results/urcu-controldataflow-ipi/urcu_free.spin.input new file mode 100644 index 0000000..4640ac9 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free.spin.input @@ -0,0 +1,1239 @@ + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free.spin.input.trail b/formal-model/results/urcu-controldataflow-ipi/urcu_free.spin.input.trail new file mode 100644 index 0000000..011045f --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free.spin.input.trail @@ -0,0 +1,2598 @@ +-2:3:-2 +-4:-4:-4 +1:0:4863 +2:3:4786 +3:3:4789 +4:3:4789 +5:3:4792 +6:3:4800 +7:3:4800 +8:3:4803 +9:3:4809 +10:3:4813 +11:3:4813 +12:3:4816 +13:3:4823 +14:3:4831 +15:3:4831 +16:3:4834 +17:3:4840 +18:3:4844 +19:3:4844 +20:3:4847 +21:3:4853 +22:3:4857 +23:3:4858 +24:0:4863 +25:3:4860 +26:0:4863 +27:2:3279 +28:0:4863 +29:2:3285 +30:0:4863 +31:2:3286 +32:0:4863 +33:2:3289 +34:2:3293 +35:2:3294 +36:2:3302 +37:2:3303 +38:2:3307 +39:2:3308 +40:2:3316 +41:2:3321 +42:2:3325 +43:2:3326 +44:2:3334 +45:2:3335 +46:2:3339 +47:2:3340 +48:2:3334 +49:2:3335 +50:2:3339 +51:2:3340 +52:2:3348 +53:2:3353 +54:2:3354 +55:2:3365 +56:2:3366 +57:2:3367 +58:2:3378 +59:2:3383 +60:2:3384 +61:2:3395 +62:2:3396 +63:2:3397 +64:2:3395 +65:2:3396 +66:2:3397 +67:2:3408 +68:2:3412 +69:0:4863 +70:2:3415 +71:0:4863 +72:2:3421 +73:2:3422 +74:2:3426 +75:2:3430 +76:2:3431 +77:2:3435 +78:2:3443 +79:2:3444 +80:2:3448 +81:2:3452 +82:2:3453 +83:2:3448 +84:2:3449 +85:2:3457 +86:2:3461 +87:0:4863 +88:2:3464 +89:0:4863 +90:2:3465 +91:2:3469 +92:2:3470 +93:2:3478 +94:2:3479 +95:2:3483 +96:2:3484 +97:2:3492 +98:2:3497 +99:2:3501 +100:2:3502 +101:2:3510 +102:2:3511 +103:2:3515 +104:2:3516 +105:2:3510 +106:2:3511 +107:2:3515 +108:2:3516 +109:2:3524 +110:2:3529 +111:2:3530 +112:2:3541 +113:2:3542 +114:2:3543 +115:2:3554 +116:2:3559 +117:2:3560 +118:2:3571 +119:2:3572 +120:2:3573 +121:2:3571 +122:2:3572 +123:2:3573 +124:2:3584 +125:2:3588 +126:0:4863 +127:2:3591 +128:0:4863 +129:2:3594 +130:2:3598 +131:2:3599 +132:2:3607 +133:2:3608 +134:2:3612 +135:2:3613 +136:2:3621 +137:2:3626 +138:2:3627 +139:2:3639 +140:2:3640 +141:2:3644 +142:2:3645 +143:2:3639 +144:2:3640 +145:2:3644 +146:2:3645 +147:2:3653 +148:2:3658 +149:2:3659 +150:2:3670 +151:2:3671 +152:2:3672 +153:2:3683 +154:2:3688 +155:2:3689 +156:2:3700 +157:2:3701 +158:2:3702 +159:2:3700 +160:2:3701 +161:2:3702 +162:2:3713 +163:2:3717 +164:0:4863 +165:2:3720 +166:0:4863 +167:2:3721 +168:0:4863 +169:2:3722 +170:0:4863 +171:2:4423 +172:2:4424 +173:2:4428 +174:2:4432 +175:2:4433 +176:2:4437 +177:2:4445 +178:2:4446 +179:2:4450 +180:2:4454 +181:2:4455 +182:2:4450 +183:2:4454 +184:2:4455 +185:2:4459 +186:2:4466 +187:2:4473 +188:2:4474 +189:2:4481 +190:2:4486 +191:2:4493 +192:2:4494 +193:2:4493 +194:2:4494 +195:2:4501 +196:2:4505 +197:0:4863 +198:2:3724 +199:2:4401 +200:0:4863 +201:2:3721 +202:0:4863 +203:2:3725 +204:0:4863 +205:2:3721 +206:0:4863 +207:2:3728 +208:2:3729 +209:2:3733 +210:2:3734 +211:2:3742 +212:2:3743 +213:2:3747 +214:2:3748 +215:2:3756 +216:2:3761 +217:2:3765 +218:2:3766 +219:2:3774 +220:2:3775 +221:2:3779 +222:2:3780 +223:2:3774 +224:2:3775 +225:2:3779 +226:2:3780 +227:2:3788 +228:2:3793 +229:2:3794 +230:2:3805 +231:2:3806 +232:2:3807 +233:2:3818 +234:2:3823 +235:2:3824 +236:2:3835 +237:2:3836 +238:2:3837 +239:2:3835 +240:2:3836 +241:2:3837 +242:2:3848 +243:2:3855 +244:0:4863 +245:2:3721 +246:0:4863 +247:2:3859 +248:2:3860 +249:2:3861 +250:2:3873 +251:2:3874 +252:2:3878 +253:2:3879 +254:2:3887 +255:2:3892 +256:2:3896 +257:2:3897 +258:2:3905 +259:2:3906 +260:2:3910 +261:2:3911 +262:2:3905 +263:2:3906 +264:2:3910 +265:2:3911 +266:2:3919 +267:2:3924 +268:2:3925 +269:2:3936 +270:2:3937 +271:2:3938 +272:2:3949 +273:2:3954 +274:2:3955 +275:2:3966 +276:2:3967 +277:2:3968 +278:2:3966 +279:2:3967 +280:2:3968 +281:2:3979 +282:2:3990 +283:2:3991 +284:0:4863 +285:2:3721 +286:0:4863 +287:2:3997 +288:2:3998 +289:2:4002 +290:2:4003 +291:2:4011 +292:2:4012 +293:2:4016 +294:2:4017 +295:2:4025 +296:2:4030 +297:2:4034 +298:2:4035 +299:2:4043 +300:2:4044 +301:2:4048 +302:2:4049 +303:2:4043 +304:2:4044 +305:2:4048 +306:2:4049 +307:2:4057 +308:2:4062 +309:2:4063 +310:2:4074 +311:2:4075 +312:2:4076 +313:2:4087 +314:2:4092 +315:2:4093 +316:2:4104 +317:2:4105 +318:2:4106 +319:2:4104 +320:2:4105 +321:2:4106 +322:2:4117 +323:0:4863 +324:2:3721 +325:0:4863 +326:2:4126 +327:2:4127 +328:2:4131 +329:2:4132 +330:2:4140 +331:2:4141 +332:2:4145 +333:2:4146 +334:2:4154 +335:2:4159 +336:2:4163 +337:2:4164 +338:2:4172 +339:2:4173 +340:2:4177 +341:2:4178 +342:2:4172 +343:2:4173 +344:2:4177 +345:2:4178 +346:2:4186 +347:2:4191 +348:2:4192 +349:2:4203 +350:2:4204 +351:2:4205 +352:2:4216 +353:2:4221 +354:2:4222 +355:2:4233 +356:2:4234 +357:2:4235 +358:2:4233 +359:2:4234 +360:2:4235 +361:2:4246 +362:2:4253 +363:0:4863 +364:2:3721 +365:0:4863 +366:2:4257 +367:2:4258 +368:2:4259 +369:2:4271 +370:2:4272 +371:2:4276 +372:2:4277 +373:2:4285 +374:2:4290 +375:2:4294 +376:2:4295 +377:2:4303 +378:2:4304 +379:2:4308 +380:2:4309 +381:2:4303 +382:2:4304 +383:2:4308 +384:2:4309 +385:2:4317 +386:2:4322 +387:2:4323 +388:2:4334 +389:2:4335 +390:2:4336 +391:2:4347 +392:2:4352 +393:2:4353 +394:2:4364 +395:2:4365 +396:2:4366 +397:2:4364 +398:2:4365 +399:2:4366 +400:2:4377 +401:2:4387 +402:2:4388 +403:0:4863 +404:2:3721 +405:0:4863 +406:2:4394 +407:0:4863 +408:2:4696 +409:2:4697 +410:2:4701 +411:2:4705 +412:2:4706 +413:2:4710 +414:2:4718 +415:2:4719 +416:2:4723 +417:2:4727 +418:2:4728 +419:2:4723 +420:2:4727 +421:2:4728 +422:2:4732 +423:2:4739 +424:2:4746 +425:2:4747 +426:2:4754 +427:2:4759 +428:2:4766 +429:2:4767 +430:2:4766 +431:2:4767 +432:2:4774 +433:2:4778 +434:0:4863 +435:2:4396 +436:2:4401 +437:0:4863 +438:2:3721 +439:0:4863 +440:2:4397 +441:0:4863 +442:2:4405 +443:0:4863 +444:2:4406 +445:0:4863 +446:2:3286 +447:0:4863 +448:2:3289 +449:2:3293 +450:2:3294 +451:2:3302 +452:2:3303 +453:2:3307 +454:2:3308 +455:2:3316 +456:2:3321 +457:2:3325 +458:2:3326 +459:2:3334 +460:2:3335 +461:2:3336 +462:2:3334 +463:2:3335 +464:2:3339 +465:2:3340 +466:2:3348 +467:2:3353 +468:2:3354 +469:2:3365 +470:2:3366 +471:2:3367 +472:2:3378 +473:2:3383 +474:2:3384 +475:2:3395 +476:2:3396 +477:2:3397 +478:2:3395 +479:2:3396 +480:2:3397 +481:2:3408 +482:2:3412 +483:0:4863 +484:2:3415 +485:0:4863 +486:2:3421 +487:2:3422 +488:2:3426 +489:2:3430 +490:2:3431 +491:2:3435 +492:2:3443 +493:2:3444 +494:2:3448 +495:2:3449 +496:2:3448 +497:2:3452 +498:2:3453 +499:2:3457 +500:2:3461 +501:0:4863 +502:2:3464 +503:0:4863 +504:2:3465 +505:2:3469 +506:2:3470 +507:2:3478 +508:2:3479 +509:2:3483 +510:2:3484 +511:2:3492 +512:2:3497 +513:2:3501 +514:2:3502 +515:2:3510 +516:2:3511 +517:2:3515 +518:2:3516 +519:2:3510 +520:2:3511 +521:2:3515 +522:2:3516 +523:2:3524 +524:2:3529 +525:2:3530 +526:2:3541 +527:2:3542 +528:2:3543 +529:2:3554 +530:2:3559 +531:2:3560 +532:2:3571 +533:2:3572 +534:2:3573 +535:2:3571 +536:2:3572 +537:2:3573 +538:2:3584 +539:2:3588 +540:0:4863 +541:2:3591 +542:0:4863 +543:2:3594 +544:2:3598 +545:2:3599 +546:2:3607 +547:2:3608 +548:2:3612 +549:2:3613 +550:2:3621 +551:2:3626 +552:2:3627 +553:2:3639 +554:2:3640 +555:2:3644 +556:2:3645 +557:2:3639 +558:2:3640 +559:2:3644 +560:2:3645 +561:2:3653 +562:2:3658 +563:2:3659 +564:2:3670 +565:2:3671 +566:2:3672 +567:2:3683 +568:2:3688 +569:2:3689 +570:2:3700 +571:2:3701 +572:2:3702 +573:2:3700 +574:2:3701 +575:2:3702 +576:2:3713 +577:2:3717 +578:0:4863 +579:2:3720 +580:0:4863 +581:2:3721 +582:0:4863 +583:2:3722 +584:0:4863 +585:2:4423 +586:2:4424 +587:2:4428 +588:2:4432 +589:2:4433 +590:2:4437 +591:2:4445 +592:2:4446 +593:2:4450 +594:2:4454 +595:2:4455 +596:2:4450 +597:2:4454 +598:2:4455 +599:2:4459 +600:2:4466 +601:2:4473 +602:2:4474 +603:2:4481 +604:2:4486 +605:2:4493 +606:2:4494 +607:2:4493 +608:2:4494 +609:2:4501 +610:2:4505 +611:0:4863 +612:2:3724 +613:2:4401 +614:0:4863 +615:2:3721 +616:0:4863 +617:2:3725 +618:0:4863 +619:2:3721 +620:0:4863 +621:2:3728 +622:2:3729 +623:2:3733 +624:2:3734 +625:2:3742 +626:2:3743 +627:2:3747 +628:2:3748 +629:2:3756 +630:2:3761 +631:2:3765 +632:2:3766 +633:2:3774 +634:2:3775 +635:2:3779 +636:2:3780 +637:2:3774 +638:2:3775 +639:2:3779 +640:2:3780 +641:2:3788 +642:2:3793 +643:2:3794 +644:2:3805 +645:2:3806 +646:2:3807 +647:2:3818 +648:2:3823 +649:2:3824 +650:2:3835 +651:2:3836 +652:2:3837 +653:2:3835 +654:2:3836 +655:2:3837 +656:2:3848 +657:2:3855 +658:0:4863 +659:2:3721 +660:0:4863 +661:2:3859 +662:2:3860 +663:2:3861 +664:2:3873 +665:2:3874 +666:2:3878 +667:2:3879 +668:2:3887 +669:2:3892 +670:2:3896 +671:2:3897 +672:2:3905 +673:2:3906 +674:2:3910 +675:2:3911 +676:2:3905 +677:2:3906 +678:2:3910 +679:2:3911 +680:2:3919 +681:2:3924 +682:2:3925 +683:2:3936 +684:2:3937 +685:2:3938 +686:2:3949 +687:2:3954 +688:2:3955 +689:2:3966 +690:2:3967 +691:2:3968 +692:2:3966 +693:2:3967 +694:2:3968 +695:2:3979 +696:2:3990 +697:2:3991 +698:0:4863 +699:2:3721 +700:0:4863 +701:2:3997 +702:2:3998 +703:2:4002 +704:2:4003 +705:2:4011 +706:2:4012 +707:2:4016 +708:2:4017 +709:2:4025 +710:2:4030 +711:2:4034 +712:2:4035 +713:2:4043 +714:2:4044 +715:2:4048 +716:2:4049 +717:2:4043 +718:2:4044 +719:2:4048 +720:2:4049 +721:2:4057 +722:2:4062 +723:2:4063 +724:2:4074 +725:2:4075 +726:2:4076 +727:2:4087 +728:2:4092 +729:2:4093 +730:2:4104 +731:2:4105 +732:2:4106 +733:2:4104 +734:2:4105 +735:2:4106 +736:2:4117 +737:0:4863 +738:2:3721 +739:0:4863 +740:2:4126 +741:2:4127 +742:2:4131 +743:2:4132 +744:2:4140 +745:2:4141 +746:2:4145 +747:2:4146 +748:2:4154 +749:2:4159 +750:2:4163 +751:2:4164 +752:2:4172 +753:2:4173 +754:2:4177 +755:2:4178 +756:2:4172 +757:2:4173 +758:2:4177 +759:2:4178 +760:2:4186 +761:2:4191 +762:2:4192 +763:2:4203 +764:2:4204 +765:2:4205 +766:2:4216 +767:2:4221 +768:2:4222 +769:2:4233 +770:2:4234 +771:2:4235 +772:2:4233 +773:2:4234 +774:2:4235 +775:2:4246 +776:2:4253 +777:0:4863 +778:2:3721 +779:0:4863 +780:2:4257 +781:2:4258 +782:2:4259 +783:2:4271 +784:2:4272 +785:2:4276 +786:2:4277 +787:2:4285 +788:2:4290 +789:2:4294 +790:2:4295 +791:2:4303 +792:2:4304 +793:2:4308 +794:2:4309 +795:2:4303 +796:2:4304 +797:2:4308 +798:2:4309 +799:2:4317 +800:2:4322 +801:2:4323 +802:2:4334 +803:2:4335 +804:2:4336 +805:2:4347 +806:2:4352 +807:2:4353 +808:2:4364 +809:2:4365 +810:2:4366 +811:2:4364 +812:2:4365 +813:2:4366 +814:2:4377 +815:2:4387 +816:2:4388 +817:0:4863 +818:2:3721 +819:0:4863 +820:2:4394 +821:0:4863 +822:2:4696 +823:2:4697 +824:2:4701 +825:2:4705 +826:2:4706 +827:2:4710 +828:2:4718 +829:2:4719 +830:2:4723 +831:2:4727 +832:2:4728 +833:2:4723 +834:2:4727 +835:2:4728 +836:2:4732 +837:2:4739 +838:2:4746 +839:2:4747 +840:2:4754 +841:2:4759 +842:2:4766 +843:2:4767 +844:2:4766 +845:2:4767 +846:2:4774 +847:2:4778 +848:0:4863 +849:2:4396 +850:2:4401 +851:0:4863 +852:2:3721 +853:0:4863 +854:2:4397 +855:0:4863 +856:2:4405 +857:0:4863 +858:2:4406 +859:0:4863 +860:2:3286 +861:0:4863 +862:2:3289 +863:2:3293 +864:2:3294 +865:2:3302 +866:2:3303 +867:2:3307 +868:2:3308 +869:2:3316 +870:2:3321 +871:2:3325 +872:2:3326 +873:2:3334 +874:2:3335 +875:2:3339 +876:2:3340 +877:2:3334 +878:2:3335 +879:2:3336 +880:2:3348 +881:2:3353 +882:2:3354 +883:2:3365 +884:2:3366 +885:2:3367 +886:2:3378 +887:2:3383 +888:2:3384 +889:2:3395 +890:2:3396 +891:2:3397 +892:2:3395 +893:2:3396 +894:2:3397 +895:2:3408 +896:2:3412 +897:0:4863 +898:2:3415 +899:0:4863 +900:2:3421 +901:2:3422 +902:2:3426 +903:2:3430 +904:2:3431 +905:2:3435 +906:2:3443 +907:2:3444 +908:2:3448 +909:2:3452 +910:2:3453 +911:2:3448 +912:2:3449 +913:2:3457 +914:2:3461 +915:0:4863 +916:2:3464 +917:0:4863 +918:2:3465 +919:2:3469 +920:2:3470 +921:2:3478 +922:2:3479 +923:2:3483 +924:2:3484 +925:2:3492 +926:2:3497 +927:2:3501 +928:2:3502 +929:2:3510 +930:2:3511 +931:2:3515 +932:2:3516 +933:2:3510 +934:2:3511 +935:2:3515 +936:2:3516 +937:2:3524 +938:2:3529 +939:2:3530 +940:2:3541 +941:2:3542 +942:2:3543 +943:2:3554 +944:2:3559 +945:2:3560 +946:2:3571 +947:2:3572 +948:2:3573 +949:2:3571 +950:2:3572 +951:2:3573 +952:2:3584 +953:2:3588 +954:0:4863 +955:2:3591 +956:0:4863 +957:2:3594 +958:2:3598 +959:2:3599 +960:2:3607 +961:2:3608 +962:2:3612 +963:2:3613 +964:2:3621 +965:2:3626 +966:2:3627 +967:2:3639 +968:2:3640 +969:2:3644 +970:2:3645 +971:2:3639 +972:2:3640 +973:2:3644 +974:2:3645 +975:2:3653 +976:2:3658 +977:2:3659 +978:2:3670 +979:2:3671 +980:2:3672 +981:2:3683 +982:2:3688 +983:2:3689 +984:2:3700 +985:2:3701 +986:2:3702 +987:2:3700 +988:2:3701 +989:2:3702 +990:2:3713 +991:2:3717 +992:0:4863 +993:2:3720 +994:0:4863 +995:2:3721 +996:0:4863 +997:2:3722 +998:0:4863 +999:2:4423 +1000:2:4424 +1001:2:4428 +1002:2:4432 +1003:2:4433 +1004:2:4437 +1005:2:4445 +1006:2:4446 +1007:2:4450 +1008:2:4454 +1009:2:4455 +1010:2:4450 +1011:2:4454 +1012:2:4455 +1013:2:4459 +1014:2:4466 +1015:2:4473 +1016:2:4474 +1017:2:4481 +1018:2:4486 +1019:2:4493 +1020:2:4494 +1021:2:4493 +1022:2:4494 +1023:2:4501 +1024:2:4505 +1025:0:4863 +1026:2:3724 +1027:2:4401 +1028:0:4863 +1029:2:3721 +1030:0:4863 +1031:2:3725 +1032:0:4863 +1033:2:3721 +1034:0:4863 +1035:2:3728 +1036:2:3729 +1037:2:3733 +1038:2:3734 +1039:2:3742 +1040:2:3743 +1041:2:3747 +1042:2:3748 +1043:2:3756 +1044:2:3761 +1045:2:3765 +1046:2:3766 +1047:2:3774 +1048:2:3775 +1049:2:3779 +1050:2:3780 +1051:2:3774 +1052:2:3775 +1053:2:3779 +1054:2:3780 +1055:2:3788 +1056:2:3793 +1057:2:3794 +1058:2:3805 +1059:2:3806 +1060:2:3807 +1061:2:3818 +1062:2:3823 +1063:2:3824 +1064:2:3835 +1065:2:3836 +1066:2:3837 +1067:2:3835 +1068:2:3836 +1069:2:3837 +1070:2:3848 +1071:2:3855 +1072:0:4863 +1073:2:3721 +1074:0:4863 +1075:2:3859 +1076:2:3860 +1077:2:3861 +1078:2:3873 +1079:2:3874 +1080:2:3878 +1081:2:3879 +1082:2:3887 +1083:2:3892 +1084:2:3896 +1085:2:3897 +1086:2:3905 +1087:2:3906 +1088:2:3910 +1089:2:3911 +1090:2:3905 +1091:2:3906 +1092:2:3910 +1093:2:3911 +1094:2:3919 +1095:2:3924 +1096:2:3925 +1097:2:3936 +1098:2:3937 +1099:2:3938 +1100:2:3949 +1101:2:3954 +1102:2:3955 +1103:2:3966 +1104:2:3967 +1105:2:3968 +1106:2:3966 +1107:2:3967 +1108:2:3968 +1109:2:3979 +1110:2:3990 +1111:2:3991 +1112:0:4863 +1113:2:3721 +1114:0:4863 +1115:2:3997 +1116:2:3998 +1117:2:4002 +1118:2:4003 +1119:2:4011 +1120:2:4012 +1121:2:4016 +1122:2:4017 +1123:2:4025 +1124:2:4030 +1125:2:4034 +1126:2:4035 +1127:2:4043 +1128:2:4044 +1129:2:4048 +1130:2:4049 +1131:2:4043 +1132:2:4044 +1133:2:4048 +1134:2:4049 +1135:2:4057 +1136:2:4062 +1137:2:4063 +1138:2:4074 +1139:2:4075 +1140:2:4076 +1141:2:4087 +1142:2:4092 +1143:2:4093 +1144:2:4104 +1145:2:4105 +1146:2:4106 +1147:2:4104 +1148:2:4105 +1149:2:4106 +1150:2:4117 +1151:0:4863 +1152:2:3721 +1153:0:4863 +1154:2:4126 +1155:2:4127 +1156:2:4131 +1157:2:4132 +1158:2:4140 +1159:2:4141 +1160:2:4145 +1161:2:4146 +1162:2:4154 +1163:2:4159 +1164:2:4163 +1165:2:4164 +1166:2:4172 +1167:2:4173 +1168:2:4177 +1169:2:4178 +1170:2:4172 +1171:2:4173 +1172:2:4177 +1173:2:4178 +1174:2:4186 +1175:2:4191 +1176:2:4192 +1177:2:4203 +1178:2:4204 +1179:2:4205 +1180:2:4216 +1181:2:4221 +1182:2:4222 +1183:2:4233 +1184:2:4234 +1185:2:4235 +1186:2:4233 +1187:2:4234 +1188:2:4235 +1189:2:4246 +1190:2:4253 +1191:0:4863 +1192:2:3721 +1193:0:4863 +1194:2:4257 +1195:2:4258 +1196:2:4259 +1197:2:4271 +1198:2:4272 +1199:2:4276 +1200:2:4277 +1201:2:4285 +1202:2:4290 +1203:2:4294 +1204:2:4295 +1205:2:4303 +1206:2:4304 +1207:2:4308 +1208:2:4309 +1209:2:4303 +1210:2:4304 +1211:2:4308 +1212:2:4309 +1213:2:4317 +1214:2:4322 +1215:2:4323 +1216:2:4334 +1217:2:4335 +1218:2:4336 +1219:2:4347 +1220:2:4352 +1221:2:4353 +1222:2:4364 +1223:2:4365 +1224:2:4366 +1225:2:4364 +1226:2:4365 +1227:2:4366 +1228:2:4377 +1229:2:4387 +1230:2:4388 +1231:0:4863 +1232:2:3721 +1233:0:4863 +1234:2:4394 +1235:0:4863 +1236:2:4696 +1237:2:4697 +1238:2:4701 +1239:2:4705 +1240:2:4706 +1241:2:4710 +1242:2:4718 +1243:2:4719 +1244:2:4723 +1245:2:4727 +1246:2:4728 +1247:2:4723 +1248:2:4727 +1249:2:4728 +1250:2:4732 +1251:2:4739 +1252:2:4746 +1253:2:4747 +1254:2:4754 +1255:2:4759 +1256:2:4766 +1257:2:4767 +1258:2:4766 +1259:2:4767 +1260:2:4774 +1261:2:4778 +1262:0:4863 +1263:2:4396 +1264:2:4401 +1265:0:4863 +1266:2:3721 +1267:0:4863 +1268:2:4397 +1269:0:4863 +1270:2:4405 +1271:0:4863 +1272:2:4406 +1273:0:4863 +1274:2:3286 +1275:0:4863 +1276:2:3289 +1277:2:3293 +1278:2:3294 +1279:2:3302 +1280:2:3303 +1281:2:3307 +1282:2:3308 +1283:2:3316 +1284:2:3321 +1285:2:3325 +1286:2:3326 +1287:2:3334 +1288:2:3335 +1289:2:3336 +1290:2:3334 +1291:2:3335 +1292:2:3339 +1293:2:3340 +1294:2:3348 +1295:2:3353 +1296:2:3354 +1297:2:3365 +1298:2:3366 +1299:2:3367 +1300:2:3378 +1301:2:3383 +1302:2:3384 +1303:2:3395 +1304:2:3396 +1305:2:3397 +1306:2:3395 +1307:2:3396 +1308:2:3397 +1309:2:3408 +1310:2:3412 +1311:0:4863 +1312:2:3415 +1313:0:4863 +1314:2:3421 +1315:2:3422 +1316:2:3426 +1317:2:3430 +1318:2:3431 +1319:2:3435 +1320:2:3443 +1321:2:3444 +1322:2:3448 +1323:2:3449 +1324:2:3448 +1325:2:3452 +1326:2:3453 +1327:2:3457 +1328:2:3461 +1329:0:4863 +1330:2:3464 +1331:0:4863 +1332:2:3465 +1333:2:3469 +1334:2:3470 +1335:2:3478 +1336:2:3479 +1337:2:3483 +1338:2:3484 +1339:2:3492 +1340:2:3497 +1341:2:3501 +1342:2:3502 +1343:2:3510 +1344:2:3511 +1345:2:3515 +1346:2:3516 +1347:2:3510 +1348:2:3511 +1349:2:3515 +1350:2:3516 +1351:2:3524 +1352:2:3529 +1353:2:3530 +1354:2:3541 +1355:2:3542 +1356:2:3543 +1357:2:3554 +1358:2:3559 +1359:2:3560 +1360:2:3571 +1361:2:3572 +1362:2:3573 +1363:2:3571 +1364:2:3572 +1365:2:3573 +1366:2:3584 +1367:2:3588 +1368:0:4863 +1369:2:3591 +1370:0:4863 +1371:2:3594 +1372:2:3598 +1373:2:3599 +1374:2:3607 +1375:2:3608 +1376:2:3612 +1377:2:3613 +1378:2:3621 +1379:2:3626 +1380:2:3627 +1381:2:3639 +1382:2:3640 +1383:2:3644 +1384:2:3645 +1385:2:3639 +1386:2:3640 +1387:2:3644 +1388:2:3645 +1389:2:3653 +1390:2:3658 +1391:2:3659 +1392:2:3670 +1393:2:3671 +1394:2:3672 +1395:2:3683 +1396:2:3688 +1397:2:3689 +1398:2:3700 +1399:2:3701 +1400:2:3702 +1401:2:3700 +1402:2:3701 +1403:2:3702 +1404:2:3713 +1405:2:3717 +1406:0:4863 +1407:2:3720 +1408:0:4863 +1409:2:3721 +1410:0:4863 +1411:2:3722 +1412:0:4863 +1413:2:4423 +1414:2:4424 +1415:2:4428 +1416:2:4432 +1417:2:4433 +1418:2:4437 +1419:2:4445 +1420:2:4446 +1421:2:4450 +1422:2:4454 +1423:2:4455 +1424:2:4450 +1425:2:4454 +1426:2:4455 +1427:2:4459 +1428:2:4466 +1429:2:4473 +1430:2:4474 +1431:2:4481 +1432:2:4486 +1433:2:4493 +1434:2:4494 +1435:2:4493 +1436:2:4494 +1437:2:4501 +1438:2:4505 +1439:0:4863 +1440:2:3724 +1441:2:4401 +1442:0:4863 +1443:2:3721 +1444:0:4863 +1445:2:3725 +1446:0:4863 +1447:2:3721 +1448:0:4863 +1449:2:3728 +1450:2:3729 +1451:2:3733 +1452:2:3734 +1453:2:3742 +1454:2:3743 +1455:2:3747 +1456:2:3748 +1457:2:3756 +1458:2:3761 +1459:2:3765 +1460:2:3766 +1461:2:3774 +1462:2:3775 +1463:2:3779 +1464:2:3780 +1465:2:3774 +1466:2:3775 +1467:2:3779 +1468:2:3780 +1469:2:3788 +1470:2:3793 +1471:2:3794 +1472:2:3805 +1473:2:3806 +1474:2:3807 +1475:2:3818 +1476:2:3823 +1477:2:3824 +1478:2:3835 +1479:2:3836 +1480:2:3837 +1481:2:3835 +1482:2:3836 +1483:2:3837 +1484:2:3848 +1485:2:3855 +1486:0:4863 +1487:2:3721 +1488:0:4863 +1489:2:3859 +1490:2:3860 +1491:2:3861 +1492:2:3873 +1493:2:3874 +1494:2:3878 +1495:2:3879 +1496:2:3887 +1497:2:3892 +1498:2:3896 +1499:2:3897 +1500:2:3905 +1501:2:3906 +1502:2:3910 +1503:2:3911 +1504:2:3905 +1505:2:3906 +1506:2:3910 +1507:2:3911 +1508:2:3919 +1509:2:3924 +1510:2:3925 +1511:2:3936 +1512:2:3937 +1513:2:3938 +1514:2:3949 +1515:2:3954 +1516:2:3955 +1517:2:3966 +1518:2:3967 +1519:2:3968 +1520:2:3966 +1521:2:3967 +1522:2:3968 +1523:2:3979 +1524:2:3990 +1525:2:3991 +1526:0:4863 +1527:2:3721 +1528:0:4863 +1529:2:3997 +1530:2:3998 +1531:2:4002 +1532:2:4003 +1533:2:4011 +1534:2:4012 +1535:2:4016 +1536:2:4017 +1537:2:4025 +1538:2:4030 +1539:2:4034 +1540:2:4035 +1541:2:4043 +1542:2:4044 +1543:2:4048 +1544:2:4049 +1545:2:4043 +1546:2:4044 +1547:2:4048 +1548:2:4049 +1549:2:4057 +1550:2:4062 +1551:2:4063 +1552:2:4074 +1553:2:4075 +1554:2:4076 +1555:2:4087 +1556:2:4092 +1557:2:4093 +1558:2:4104 +1559:2:4105 +1560:2:4106 +1561:2:4104 +1562:2:4105 +1563:2:4106 +1564:2:4117 +1565:0:4863 +1566:2:3721 +1567:0:4863 +1568:2:4126 +1569:2:4127 +1570:2:4131 +1571:2:4132 +1572:2:4140 +1573:2:4141 +1574:2:4145 +1575:2:4146 +1576:2:4154 +1577:2:4159 +1578:2:4163 +1579:2:4164 +1580:2:4172 +1581:2:4173 +1582:2:4177 +1583:2:4178 +1584:2:4172 +1585:2:4173 +1586:2:4177 +1587:2:4178 +1588:2:4186 +1589:2:4191 +1590:2:4192 +1591:2:4203 +1592:2:4204 +1593:2:4205 +1594:2:4216 +1595:2:4221 +1596:2:4222 +1597:2:4233 +1598:2:4234 +1599:2:4235 +1600:2:4233 +1601:2:4234 +1602:2:4235 +1603:2:4246 +1604:2:4253 +1605:0:4863 +1606:2:3721 +1607:0:4863 +1608:2:4257 +1609:2:4258 +1610:2:4259 +1611:2:4271 +1612:2:4272 +1613:2:4276 +1614:2:4277 +1615:2:4285 +1616:2:4290 +1617:2:4294 +1618:2:4295 +1619:2:4303 +1620:2:4304 +1621:2:4308 +1622:2:4309 +1623:2:4303 +1624:2:4304 +1625:2:4308 +1626:2:4309 +1627:2:4317 +1628:2:4322 +1629:2:4323 +1630:2:4334 +1631:2:4335 +1632:2:4336 +1633:2:4347 +1634:2:4352 +1635:2:4353 +1636:2:4364 +1637:2:4365 +1638:2:4366 +1639:2:4364 +1640:2:4365 +1641:2:4366 +1642:2:4377 +1643:2:4387 +1644:2:4388 +1645:0:4863 +1646:2:3721 +1647:0:4863 +1648:2:4394 +1649:0:4863 +1650:2:4696 +1651:2:4697 +1652:2:4701 +1653:2:4705 +1654:2:4706 +1655:2:4710 +1656:2:4718 +1657:2:4719 +1658:2:4723 +1659:2:4727 +1660:2:4728 +1661:2:4723 +1662:2:4727 +1663:2:4728 +1664:2:4732 +1665:2:4739 +1666:2:4746 +1667:2:4747 +1668:2:4754 +1669:2:4759 +1670:2:4766 +1671:2:4767 +1672:2:4766 +1673:2:4767 +1674:2:4774 +1675:2:4778 +1676:0:4863 +1677:2:4396 +1678:2:4401 +1679:0:4863 +1680:2:3721 +1681:0:4863 +1682:2:4397 +1683:0:4863 +1684:2:4405 +1685:0:4863 +1686:2:4406 +1687:0:4863 +1688:2:3286 +1689:0:4863 +1690:2:3289 +1691:2:3293 +1692:2:3294 +1693:2:3302 +1694:2:3303 +1695:2:3307 +1696:2:3308 +1697:2:3316 +1698:2:3321 +1699:2:3325 +1700:2:3326 +1701:2:3334 +1702:2:3335 +1703:2:3339 +1704:2:3340 +1705:2:3334 +1706:2:3335 +1707:2:3336 +1708:2:3348 +1709:2:3353 +1710:2:3354 +1711:2:3365 +1712:2:3366 +1713:2:3367 +1714:2:3378 +1715:2:3383 +1716:2:3384 +1717:2:3395 +1718:2:3396 +1719:2:3397 +1720:2:3395 +1721:2:3396 +1722:2:3397 +1723:2:3408 +1724:2:3412 +1725:0:4863 +1726:2:3415 +1727:0:4863 +1728:1:2 +1729:0:4863 +1730:1:8 +1731:0:4863 +1732:1:9 +1733:0:4863 +1734:1:10 +1735:0:4863 +1736:1:11 +1737:0:4863 +1738:1:12 +1739:1:13 +1740:1:17 +1741:1:18 +1742:1:26 +1743:1:27 +1744:1:31 +1745:1:32 +1746:1:40 +1747:1:45 +1748:1:49 +1749:1:50 +1750:1:58 +1751:1:59 +1752:1:63 +1753:1:64 +1754:1:58 +1755:1:59 +1756:1:63 +1757:1:64 +1758:1:72 +1759:1:77 +1760:1:78 +1761:1:89 +1762:1:90 +1763:1:91 +1764:1:102 +1765:1:107 +1766:1:108 +1767:1:119 +1768:1:120 +1769:1:121 +1770:1:119 +1771:1:120 +1772:1:121 +1773:1:132 +1774:0:4863 +1775:1:11 +1776:0:4863 +1777:1:141 +1778:1:142 +1779:0:4863 +1780:1:11 +1781:0:4863 +1782:1:148 +1783:1:149 +1784:1:153 +1785:1:154 +1786:1:162 +1787:1:163 +1788:1:167 +1789:1:168 +1790:1:176 +1791:1:181 +1792:1:185 +1793:1:186 +1794:1:194 +1795:1:195 +1796:1:199 +1797:1:200 +1798:1:194 +1799:1:195 +1800:1:199 +1801:1:200 +1802:1:208 +1803:1:213 +1804:1:214 +1805:1:225 +1806:1:226 +1807:1:227 +1808:1:238 +1809:1:243 +1810:1:244 +1811:1:255 +1812:1:256 +1813:1:257 +1814:1:255 +1815:1:256 +1816:1:257 +1817:1:268 +1818:0:4863 +1819:1:11 +1820:0:4863 +1821:1:277 +1822:1:278 +1823:1:282 +1824:1:283 +1825:1:291 +1826:1:292 +1827:1:296 +1828:1:297 +1829:1:305 +1830:1:310 +1831:1:314 +1832:1:315 +1833:1:323 +1834:1:324 +1835:1:328 +1836:1:329 +1837:1:323 +1838:1:324 +1839:1:328 +1840:1:329 +1841:1:337 +1842:1:342 +1843:1:343 +1844:1:354 +1845:1:355 +1846:1:356 +1847:1:367 +1848:1:372 +1849:1:373 +1850:1:384 +1851:1:385 +1852:1:386 +1853:1:384 +1854:1:385 +1855:1:386 +1856:1:397 +1857:1:404 +1858:0:4863 +1859:1:11 +1860:0:4863 +1861:1:540 +1862:1:544 +1863:1:545 +1864:1:549 +1865:1:550 +1866:1:558 +1867:1:566 +1868:1:567 +1869:1:571 +1870:1:575 +1871:1:576 +1872:1:571 +1873:1:575 +1874:1:576 +1875:1:580 +1876:1:587 +1877:1:594 +1878:1:595 +1879:1:602 +1880:1:607 +1881:1:614 +1882:1:615 +1883:1:614 +1884:1:615 +1885:1:622 +1886:0:4863 +1887:1:11 +1888:0:4863 +1889:2:3421 +1890:2:3422 +1891:2:3426 +1892:2:3430 +1893:2:3431 +1894:2:3435 +1895:2:3443 +1896:2:3444 +1897:2:3448 +1898:2:3452 +1899:2:3453 +1900:2:3448 +1901:2:3449 +1902:2:3457 +1903:2:3461 +1904:0:4863 +1905:2:3464 +1906:0:4863 +1907:2:3465 +1908:2:3469 +1909:2:3470 +1910:2:3478 +1911:2:3479 +1912:2:3483 +1913:2:3484 +1914:2:3492 +1915:2:3497 +1916:2:3501 +1917:2:3502 +1918:2:3510 +1919:2:3511 +1920:2:3515 +1921:2:3516 +1922:2:3510 +1923:2:3511 +1924:2:3515 +1925:2:3516 +1926:2:3524 +1927:2:3529 +1928:2:3530 +1929:2:3541 +1930:2:3542 +1931:2:3543 +1932:2:3554 +1933:2:3559 +1934:2:3560 +1935:2:3571 +1936:2:3572 +1937:2:3573 +1938:2:3571 +1939:2:3572 +1940:2:3573 +1941:2:3584 +1942:2:3588 +1943:0:4863 +1944:2:3591 +1945:0:4863 +1946:2:3594 +1947:2:3598 +1948:2:3599 +1949:2:3607 +1950:2:3608 +1951:2:3612 +1952:2:3613 +1953:2:3621 +1954:2:3626 +1955:2:3627 +1956:2:3639 +1957:2:3640 +1958:2:3644 +1959:2:3645 +1960:2:3639 +1961:2:3640 +1962:2:3644 +1963:2:3645 +1964:2:3653 +1965:2:3658 +1966:2:3659 +1967:2:3670 +1968:2:3671 +1969:2:3672 +1970:2:3683 +1971:2:3688 +1972:2:3689 +1973:2:3700 +1974:2:3701 +1975:2:3702 +1976:2:3700 +1977:2:3701 +1978:2:3702 +1979:2:3713 +1980:2:3717 +1981:0:4863 +1982:2:3720 +1983:0:4863 +1984:2:3721 +1985:0:4863 +1986:2:3722 +1987:0:4863 +1988:2:4423 +1989:2:4424 +1990:2:4428 +1991:2:4432 +1992:2:4433 +1993:2:4437 +1994:2:4445 +1995:2:4446 +1996:2:4450 +1997:2:4454 +1998:2:4455 +1999:2:4450 +2000:2:4454 +2001:2:4455 +2002:2:4459 +2003:2:4466 +2004:2:4473 +2005:2:4474 +2006:2:4481 +2007:2:4486 +2008:2:4493 +2009:2:4494 +2010:2:4493 +2011:2:4494 +2012:2:4501 +2013:2:4505 +2014:0:4863 +2015:2:3724 +2016:2:4401 +2017:0:4863 +2018:2:3721 +2019:0:4863 +2020:2:3725 +2021:0:4863 +2022:2:3721 +2023:0:4863 +2024:2:3728 +2025:2:3729 +2026:2:3733 +2027:2:3734 +2028:2:3742 +2029:2:3743 +2030:2:3747 +2031:2:3748 +2032:2:3756 +2033:2:3761 +2034:2:3765 +2035:2:3766 +2036:2:3774 +2037:2:3775 +2038:2:3779 +2039:2:3780 +2040:2:3774 +2041:2:3775 +2042:2:3779 +2043:2:3780 +2044:2:3788 +2045:2:3793 +2046:2:3794 +2047:2:3805 +2048:2:3806 +2049:2:3807 +2050:2:3818 +2051:2:3823 +2052:2:3824 +2053:2:3835 +2054:2:3836 +2055:2:3837 +2056:2:3835 +2057:2:3836 +2058:2:3837 +2059:2:3848 +2060:2:3855 +2061:0:4863 +2062:2:3721 +2063:0:4863 +2064:2:3859 +2065:2:3860 +2066:2:3861 +2067:2:3873 +2068:2:3874 +2069:2:3878 +2070:2:3879 +2071:2:3887 +2072:2:3892 +2073:2:3896 +2074:2:3897 +2075:2:3905 +2076:2:3906 +2077:2:3910 +2078:2:3911 +2079:2:3905 +2080:2:3906 +2081:2:3910 +2082:2:3911 +2083:2:3919 +2084:2:3924 +2085:2:3925 +2086:2:3936 +2087:2:3937 +2088:2:3938 +2089:2:3949 +2090:2:3954 +2091:2:3955 +2092:2:3966 +2093:2:3967 +2094:2:3968 +2095:2:3966 +2096:2:3967 +2097:2:3968 +2098:2:3979 +2099:2:3988 +2100:0:4863 +2101:2:3721 +2102:0:4863 +2103:2:3994 +2104:0:4863 +2105:2:4514 +2106:2:4515 +2107:2:4519 +2108:2:4523 +2109:2:4524 +2110:2:4528 +2111:2:4536 +2112:2:4537 +2113:2:4541 +2114:2:4545 +2115:2:4546 +2116:2:4541 +2117:2:4545 +2118:2:4546 +2119:2:4550 +2120:2:4557 +2121:2:4564 +2122:2:4565 +2123:2:4572 +2124:2:4577 +2125:2:4584 +2126:2:4585 +2127:2:4584 +2128:2:4585 +2129:2:4592 +2130:2:4596 +2131:0:4863 +2132:2:3996 +2133:2:4401 +2134:0:4863 +2135:2:3721 +2136:0:4863 +2137:1:632 +2138:1:633 +2139:1:637 +2140:1:638 +2141:1:646 +2142:1:647 +2143:1:651 +2144:1:652 +2145:1:660 +2146:1:665 +2147:1:669 +2148:1:670 +2149:1:678 +2150:1:679 +2151:1:683 +2152:1:684 +2153:1:678 +2154:1:679 +2155:1:683 +2156:1:684 +2157:1:692 +2158:1:697 +2159:1:698 +2160:1:709 +2161:1:710 +2162:1:711 +2163:1:722 +2164:1:727 +2165:1:728 +2166:1:739 +2167:1:740 +2168:1:741 +2169:1:739 +2170:1:747 +2171:1:748 +2172:1:752 +2173:0:4863 +2174:1:11 +2175:0:4863 +2176:2:3859 +2177:2:3860 +2178:2:3864 +2179:2:3865 +2180:2:3873 +2181:2:3874 +2182:2:3878 +2183:2:3879 +2184:2:3887 +2185:2:3892 +2186:2:3896 +2187:2:3897 +2188:2:3905 +2189:2:3906 +2190:2:3910 +2191:2:3911 +2192:2:3905 +2193:2:3906 +2194:2:3910 +2195:2:3911 +2196:2:3919 +2197:2:3924 +2198:2:3925 +2199:2:3936 +2200:2:3937 +2201:2:3938 +2202:2:3949 +2203:2:3954 +2204:2:3955 +2205:2:3966 +2206:2:3967 +2207:2:3968 +2208:2:3966 +2209:2:3967 +2210:2:3968 +2211:2:3979 +2212:2:3988 +2213:0:4863 +2214:2:3721 +2215:0:4863 +2216:2:3994 +2217:0:4863 +2218:2:4514 +2219:2:4515 +2220:2:4519 +2221:2:4523 +2222:2:4524 +2223:2:4528 +2224:2:4536 +2225:2:4537 +2226:2:4541 +2227:2:4545 +2228:2:4546 +2229:2:4541 +2230:2:4545 +2231:2:4546 +2232:2:4550 +2233:2:4557 +2234:2:4564 +2235:2:4565 +2236:2:4572 +2237:2:4577 +2238:2:4584 +2239:2:4585 +2240:2:4584 +2241:2:4585 +2242:2:4592 +2243:2:4596 +2244:0:4863 +2245:2:3996 +2246:2:4401 +2247:0:4863 +2248:1:761 +2249:1:764 +2250:1:765 +2251:0:4863 +2252:2:3721 +2253:0:4863 +2254:1:11 +2255:0:4863 +2256:2:3859 +2257:2:3860 +2258:2:3864 +2259:2:3865 +2260:2:3873 +2261:2:3874 +2262:2:3878 +2263:2:3879 +2264:2:3887 +2265:2:3892 +2266:2:3896 +2267:2:3897 +2268:2:3905 +2269:2:3906 +2270:2:3910 +2271:2:3911 +2272:2:3905 +2273:2:3906 +2274:2:3910 +2275:2:3911 +2276:2:3919 +2277:2:3924 +2278:2:3925 +2279:2:3936 +2280:2:3937 +2281:2:3938 +2282:2:3949 +2283:2:3954 +2284:2:3955 +2285:2:3966 +2286:2:3967 +2287:2:3968 +2288:2:3966 +2289:2:3967 +2290:2:3968 +2291:2:3979 +2292:2:3988 +2293:0:4863 +2294:2:3721 +2295:0:4863 +2296:2:3994 +2297:0:4863 +2298:2:4514 +2299:2:4515 +2300:2:4519 +2301:2:4523 +2302:2:4524 +2303:2:4528 +2304:2:4536 +2305:2:4537 +2306:2:4541 +2307:2:4545 +2308:2:4546 +2309:2:4541 +2310:2:4545 +2311:2:4546 +2312:2:4550 +2313:2:4557 +2314:2:4564 +2315:2:4565 +2316:2:4572 +2317:2:4577 +2318:2:4584 +2319:2:4585 +2320:2:4584 +2321:2:4585 +2322:2:4592 +2323:2:4596 +2324:0:4863 +2325:2:3996 +2326:2:4401 +2327:0:4863 +2328:1:1028 +2329:1:1029 +2330:1:1033 +2331:1:1034 +2332:1:1042 +2333:1:1043 +2334:1:1047 +2335:1:1048 +2336:1:1056 +2337:1:1061 +2338:1:1065 +2339:1:1066 +2340:1:1074 +2341:1:1075 +2342:1:1079 +2343:1:1080 +2344:1:1074 +2345:1:1075 +2346:1:1079 +2347:1:1080 +2348:1:1088 +2349:1:1093 +2350:1:1094 +2351:1:1105 +2352:1:1106 +2353:1:1107 +2354:1:1118 +2355:1:1123 +2356:1:1124 +2357:1:1135 +2358:1:1136 +2359:1:1137 +2360:1:1135 +2361:1:1143 +2362:1:1144 +2363:1:1148 +2364:1:1155 +2365:1:1159 +2366:0:4863 +2367:2:3721 +2368:0:4863 +2369:1:11 +2370:0:4863 +2371:2:3859 +2372:2:3860 +2373:2:3864 +2374:2:3865 +2375:2:3873 +2376:2:3874 +2377:2:3878 +2378:2:3879 +2379:2:3887 +2380:2:3892 +2381:2:3896 +2382:2:3897 +2383:2:3905 +2384:2:3906 +2385:2:3910 +2386:2:3911 +2387:2:3905 +2388:2:3906 +2389:2:3910 +2390:2:3911 +2391:2:3919 +2392:2:3924 +2393:2:3925 +2394:2:3936 +2395:2:3937 +2396:2:3938 +2397:2:3949 +2398:2:3954 +2399:2:3955 +2400:2:3966 +2401:2:3967 +2402:2:3968 +2403:2:3966 +2404:2:3967 +2405:2:3968 +2406:2:3979 +2407:2:3988 +2408:0:4863 +2409:2:3721 +2410:0:4863 +2411:2:3994 +2412:0:4863 +2413:2:4514 +2414:2:4515 +2415:2:4519 +2416:2:4523 +2417:2:4524 +2418:2:4528 +2419:2:4536 +2420:2:4537 +2421:2:4541 +2422:2:4545 +2423:2:4546 +2424:2:4541 +2425:2:4545 +2426:2:4546 +2427:2:4550 +2428:2:4557 +2429:2:4564 +2430:2:4565 +2431:2:4572 +2432:2:4577 +2433:2:4584 +2434:2:4585 +2435:2:4584 +2436:2:4585 +2437:2:4592 +2438:2:4596 +2439:0:4863 +2440:2:3996 +2441:2:4401 +2442:0:4863 +2443:1:1160 +2444:1:1161 +2445:1:1165 +2446:1:1166 +2447:1:1174 +2448:1:1175 +2449:1:1176 +2450:1:1188 +2451:1:1193 +2452:1:1197 +2453:1:1198 +2454:1:1206 +2455:1:1207 +2456:1:1211 +2457:1:1212 +2458:1:1206 +2459:1:1207 +2460:1:1211 +2461:1:1212 +2462:1:1220 +2463:1:1225 +2464:1:1226 +2465:1:1237 +2466:1:1238 +2467:1:1239 +2468:1:1250 +2469:1:1255 +2470:1:1256 +2471:1:1267 +2472:1:1268 +2473:1:1269 +2474:1:1267 +2475:1:1275 +2476:1:1276 +2477:1:1280 +2478:0:4863 +2479:2:3721 +2480:0:4863 +2481:1:11 +2482:0:4863 +2483:2:3859 +2484:2:3860 +2485:2:3864 +2486:2:3865 +2487:2:3873 +2488:2:3874 +2489:2:3878 +2490:2:3879 +2491:2:3887 +2492:2:3892 +2493:2:3896 +2494:2:3897 +2495:2:3905 +2496:2:3906 +2497:2:3910 +2498:2:3911 +2499:2:3905 +2500:2:3906 +2501:2:3910 +2502:2:3911 +2503:2:3919 +2504:2:3924 +2505:2:3925 +2506:2:3936 +2507:2:3937 +2508:2:3938 +2509:2:3949 +2510:2:3954 +2511:2:3955 +2512:2:3966 +2513:2:3967 +2514:2:3968 +2515:2:3966 +2516:2:3967 +2517:2:3968 +2518:2:3979 +2519:2:3988 +2520:0:4863 +2521:2:3721 +2522:0:4863 +2523:2:3994 +2524:0:4863 +2525:2:4514 +2526:2:4515 +2527:2:4519 +2528:2:4523 +2529:2:4524 +2530:2:4528 +2531:2:4536 +2532:2:4537 +2533:2:4541 +2534:2:4545 +2535:2:4546 +2536:2:4541 +2537:2:4545 +2538:2:4546 +2539:2:4550 +2540:2:4557 +2541:2:4564 +2542:2:4565 +2543:2:4572 +2544:2:4577 +2545:2:4584 +2546:2:4585 +2547:2:4584 +2548:2:4585 +2549:2:4592 +2550:2:4596 +2551:0:4863 +2552:2:3996 +2553:2:4401 +2554:0:4863 +2555:2:3721 +2556:0:4863 +2557:1:1289 +2558:1:1290 +2559:1:1294 +2560:1:1295 +2561:1:1303 +2562:1:1304 +2563:1:1308 +2564:1:1309 +2565:1:1317 +2566:1:1322 +2567:1:1326 +2568:1:1327 +2569:1:1335 +2570:1:1336 +2571:1:1340 +2572:1:1341 +2573:1:1335 +2574:1:1336 +2575:1:1340 +2576:1:1341 +2577:1:1349 +2578:1:1354 +2579:1:1355 +2580:1:1366 +2581:1:1367 +2582:1:1368 +2583:1:1379 +2584:1:1384 +2585:1:1385 +2586:1:1396 +2587:1:1397 +2588:1:1398 +2589:1:1396 +2590:1:1404 +2591:1:1405 +2592:1:1409 +2593:0:4861 +2594:1:11 +2595:0:4867 +2596:0:4863 diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free_nested.define b/formal-model/results/urcu-controldataflow-ipi/urcu_free_nested.define new file mode 100644 index 0000000..0fb59bd --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free_nested.define @@ -0,0 +1 @@ +#define READER_NEST_LEVEL 2 diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_mb.define b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_mb.define new file mode 100644 index 0000000..d99d793 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_mb.define @@ -0,0 +1 @@ +#define NO_MB diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_mb.log b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_mb.log new file mode 100644 index 0000000..1446ff9 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_mb.log @@ -0,0 +1,874 @@ +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define >> pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_free.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_free_no_mb.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1258) +pan: claim violated! (at depth 1420) +pan: wrote .input.spin.trail + +(Spin Version 5.1.7 -- 23 December 2008) +Warning: Search not completed + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness disabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 5697, errors: 1 + 552184 states, stored + 73251405 states, matched + 73803589 transitions (= stored+matched) +4.1259494e+08 atomic steps +hash conflicts: 9982809 (resolved) + +Stats on memory usage (in Megabytes): + 61.086 equivalent memory usage for states (stored*(State-vector + overhead)) + 47.033 actual memory usage for states (compression: 76.99%) + state-vector as stored = 61 byte + 28 byte overhead + 8.000 memory used for hash table (-w20) + 457.764 memory used for DFS stack (-m10000000) + 512.736 total actual memory usage + +unreached in proctype urcu_reader + line 250, "pan.___", state 34, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 56, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 65, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 81, "(1)" + line 231, "pan.___", state 89, "(1)" + line 235, "pan.___", state 101, "(1)" + line 239, "pan.___", state 109, "(1)" + line 395, "pan.___", state 135, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 167, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 181, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 200, "(1)" + line 421, "pan.___", state 230, "(1)" + line 425, "pan.___", state 243, "(1)" + line 679, "pan.___", state 264, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 395, "pan.___", state 271, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 303, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 317, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 336, "(1)" + line 421, "pan.___", state 366, "(1)" + line 425, "pan.___", state 379, "(1)" + line 395, "pan.___", state 400, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 432, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 446, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 465, "(1)" + line 421, "pan.___", state 495, "(1)" + line 425, "pan.___", state 508, "(1)" + line 395, "pan.___", state 531, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 533, "(1)" + line 395, "pan.___", state 534, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 534, "else" + line 395, "pan.___", state 537, "(1)" + line 399, "pan.___", state 545, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 547, "(1)" + line 399, "pan.___", state 548, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 548, "else" + line 399, "pan.___", state 551, "(1)" + line 399, "pan.___", state 552, "(1)" + line 399, "pan.___", state 552, "(1)" + line 397, "pan.___", state 557, "((i<1))" + line 397, "pan.___", state 557, "((i>=1))" + line 404, "pan.___", state 563, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 565, "(1)" + line 404, "pan.___", state 566, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 566, "else" + line 404, "pan.___", state 569, "(1)" + line 404, "pan.___", state 570, "(1)" + line 404, "pan.___", state 570, "(1)" + line 408, "pan.___", state 577, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 579, "(1)" + line 408, "pan.___", state 580, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 580, "else" + line 408, "pan.___", state 583, "(1)" + line 408, "pan.___", state 584, "(1)" + line 408, "pan.___", state 584, "(1)" + line 406, "pan.___", state 589, "((i<2))" + line 406, "pan.___", state 589, "((i>=2))" + line 412, "pan.___", state 596, "(1)" + line 412, "pan.___", state 597, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 597, "else" + line 412, "pan.___", state 600, "(1)" + line 412, "pan.___", state 601, "(1)" + line 412, "pan.___", state 601, "(1)" + line 416, "pan.___", state 609, "(1)" + line 416, "pan.___", state 610, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 610, "else" + line 416, "pan.___", state 613, "(1)" + line 416, "pan.___", state 614, "(1)" + line 416, "pan.___", state 614, "(1)" + line 414, "pan.___", state 619, "((i<1))" + line 414, "pan.___", state 619, "((i>=1))" + line 421, "pan.___", state 626, "(1)" + line 421, "pan.___", state 627, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 627, "else" + line 421, "pan.___", state 630, "(1)" + line 421, "pan.___", state 631, "(1)" + line 421, "pan.___", state 631, "(1)" + line 425, "pan.___", state 639, "(1)" + line 425, "pan.___", state 640, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 640, "else" + line 425, "pan.___", state 643, "(1)" + line 425, "pan.___", state 644, "(1)" + line 425, "pan.___", state 644, "(1)" + line 423, "pan.___", state 649, "((i<2))" + line 423, "pan.___", state 649, "((i>=2))" + line 430, "pan.___", state 653, "(1)" + line 430, "pan.___", state 653, "(1)" + line 679, "pan.___", state 656, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 679, "pan.___", state 657, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 679, "pan.___", state 658, "(1)" + line 395, "pan.___", state 665, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 697, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 711, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 730, "(1)" + line 421, "pan.___", state 760, "(1)" + line 425, "pan.___", state 773, "(1)" + line 395, "pan.___", state 801, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 803, "(1)" + line 395, "pan.___", state 804, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 804, "else" + line 395, "pan.___", state 807, "(1)" + line 399, "pan.___", state 815, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 817, "(1)" + line 399, "pan.___", state 818, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 818, "else" + line 399, "pan.___", state 821, "(1)" + line 399, "pan.___", state 822, "(1)" + line 399, "pan.___", state 822, "(1)" + line 397, "pan.___", state 827, "((i<1))" + line 397, "pan.___", state 827, "((i>=1))" + line 404, "pan.___", state 833, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 835, "(1)" + line 404, "pan.___", state 836, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 836, "else" + line 404, "pan.___", state 839, "(1)" + line 404, "pan.___", state 840, "(1)" + line 404, "pan.___", state 840, "(1)" + line 408, "pan.___", state 847, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 849, "(1)" + line 408, "pan.___", state 850, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 850, "else" + line 408, "pan.___", state 853, "(1)" + line 408, "pan.___", state 854, "(1)" + line 408, "pan.___", state 854, "(1)" + line 406, "pan.___", state 859, "((i<2))" + line 406, "pan.___", state 859, "((i>=2))" + line 412, "pan.___", state 866, "(1)" + line 412, "pan.___", state 867, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 867, "else" + line 412, "pan.___", state 870, "(1)" + line 412, "pan.___", state 871, "(1)" + line 412, "pan.___", state 871, "(1)" + line 416, "pan.___", state 879, "(1)" + line 416, "pan.___", state 880, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 880, "else" + line 416, "pan.___", state 883, "(1)" + line 416, "pan.___", state 884, "(1)" + line 416, "pan.___", state 884, "(1)" + line 414, "pan.___", state 889, "((i<1))" + line 414, "pan.___", state 889, "((i>=1))" + line 421, "pan.___", state 896, "(1)" + line 421, "pan.___", state 897, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 897, "else" + line 421, "pan.___", state 900, "(1)" + line 421, "pan.___", state 901, "(1)" + line 421, "pan.___", state 901, "(1)" + line 425, "pan.___", state 909, "(1)" + line 425, "pan.___", state 910, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 910, "else" + line 425, "pan.___", state 913, "(1)" + line 425, "pan.___", state 914, "(1)" + line 425, "pan.___", state 914, "(1)" + line 430, "pan.___", state 923, "(1)" + line 430, "pan.___", state 923, "(1)" + line 395, "pan.___", state 930, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 932, "(1)" + line 395, "pan.___", state 933, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 933, "else" + line 395, "pan.___", state 936, "(1)" + line 399, "pan.___", state 944, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 946, "(1)" + line 399, "pan.___", state 947, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 947, "else" + line 399, "pan.___", state 950, "(1)" + line 399, "pan.___", state 951, "(1)" + line 399, "pan.___", state 951, "(1)" + line 397, "pan.___", state 956, "((i<1))" + line 397, "pan.___", state 956, "((i>=1))" + line 404, "pan.___", state 962, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 964, "(1)" + line 404, "pan.___", state 965, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 965, "else" + line 404, "pan.___", state 968, "(1)" + line 404, "pan.___", state 969, "(1)" + line 404, "pan.___", state 969, "(1)" + line 408, "pan.___", state 976, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 978, "(1)" + line 408, "pan.___", state 979, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 979, "else" + line 408, "pan.___", state 982, "(1)" + line 408, "pan.___", state 983, "(1)" + line 408, "pan.___", state 983, "(1)" + line 406, "pan.___", state 988, "((i<2))" + line 406, "pan.___", state 988, "((i>=2))" + line 412, "pan.___", state 995, "(1)" + line 412, "pan.___", state 996, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 996, "else" + line 412, "pan.___", state 999, "(1)" + line 412, "pan.___", state 1000, "(1)" + line 412, "pan.___", state 1000, "(1)" + line 416, "pan.___", state 1008, "(1)" + line 416, "pan.___", state 1009, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 1009, "else" + line 416, "pan.___", state 1012, "(1)" + line 416, "pan.___", state 1013, "(1)" + line 416, "pan.___", state 1013, "(1)" + line 414, "pan.___", state 1018, "((i<1))" + line 414, "pan.___", state 1018, "((i>=1))" + line 421, "pan.___", state 1025, "(1)" + line 421, "pan.___", state 1026, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 1026, "else" + line 421, "pan.___", state 1029, "(1)" + line 421, "pan.___", state 1030, "(1)" + line 421, "pan.___", state 1030, "(1)" + line 425, "pan.___", state 1038, "(1)" + line 425, "pan.___", state 1039, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 1039, "else" + line 425, "pan.___", state 1042, "(1)" + line 425, "pan.___", state 1043, "(1)" + line 425, "pan.___", state 1043, "(1)" + line 423, "pan.___", state 1048, "((i<2))" + line 423, "pan.___", state 1048, "((i>=2))" + line 430, "pan.___", state 1052, "(1)" + line 430, "pan.___", state 1052, "(1)" + line 687, "pan.___", state 1056, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 395, "pan.___", state 1061, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1093, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1107, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1126, "(1)" + line 421, "pan.___", state 1156, "(1)" + line 425, "pan.___", state 1169, "(1)" + line 395, "pan.___", state 1193, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1225, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1239, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1258, "(1)" + line 421, "pan.___", state 1288, "(1)" + line 425, "pan.___", state 1301, "(1)" + line 395, "pan.___", state 1326, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1358, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1372, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1391, "(1)" + line 421, "pan.___", state 1421, "(1)" + line 425, "pan.___", state 1434, "(1)" + line 395, "pan.___", state 1455, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1487, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1501, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1520, "(1)" + line 421, "pan.___", state 1550, "(1)" + line 425, "pan.___", state 1563, "(1)" + line 395, "pan.___", state 1589, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1621, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1635, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1654, "(1)" + line 421, "pan.___", state 1684, "(1)" + line 425, "pan.___", state 1697, "(1)" + line 395, "pan.___", state 1718, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1750, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1764, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1783, "(1)" + line 421, "pan.___", state 1813, "(1)" + line 425, "pan.___", state 1826, "(1)" + line 395, "pan.___", state 1850, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1882, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1896, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1915, "(1)" + line 421, "pan.___", state 1945, "(1)" + line 425, "pan.___", state 1958, "(1)" + line 726, "pan.___", state 1979, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 395, "pan.___", state 1986, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2018, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2032, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2051, "(1)" + line 421, "pan.___", state 2081, "(1)" + line 425, "pan.___", state 2094, "(1)" + line 395, "pan.___", state 2115, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2147, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2161, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2180, "(1)" + line 421, "pan.___", state 2210, "(1)" + line 425, "pan.___", state 2223, "(1)" + line 395, "pan.___", state 2246, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 2248, "(1)" + line 395, "pan.___", state 2249, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 2249, "else" + line 395, "pan.___", state 2252, "(1)" + line 399, "pan.___", state 2260, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2262, "(1)" + line 399, "pan.___", state 2263, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 2263, "else" + line 399, "pan.___", state 2266, "(1)" + line 399, "pan.___", state 2267, "(1)" + line 399, "pan.___", state 2267, "(1)" + line 397, "pan.___", state 2272, "((i<1))" + line 397, "pan.___", state 2272, "((i>=1))" + line 404, "pan.___", state 2278, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2280, "(1)" + line 404, "pan.___", state 2281, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 2281, "else" + line 404, "pan.___", state 2284, "(1)" + line 404, "pan.___", state 2285, "(1)" + line 404, "pan.___", state 2285, "(1)" + line 408, "pan.___", state 2292, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2294, "(1)" + line 408, "pan.___", state 2295, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 2295, "else" + line 408, "pan.___", state 2298, "(1)" + line 408, "pan.___", state 2299, "(1)" + line 408, "pan.___", state 2299, "(1)" + line 406, "pan.___", state 2304, "((i<2))" + line 406, "pan.___", state 2304, "((i>=2))" + line 412, "pan.___", state 2311, "(1)" + line 412, "pan.___", state 2312, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 2312, "else" + line 412, "pan.___", state 2315, "(1)" + line 412, "pan.___", state 2316, "(1)" + line 412, "pan.___", state 2316, "(1)" + line 416, "pan.___", state 2324, "(1)" + line 416, "pan.___", state 2325, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 2325, "else" + line 416, "pan.___", state 2328, "(1)" + line 416, "pan.___", state 2329, "(1)" + line 416, "pan.___", state 2329, "(1)" + line 414, "pan.___", state 2334, "((i<1))" + line 414, "pan.___", state 2334, "((i>=1))" + line 421, "pan.___", state 2341, "(1)" + line 421, "pan.___", state 2342, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 2342, "else" + line 421, "pan.___", state 2345, "(1)" + line 421, "pan.___", state 2346, "(1)" + line 421, "pan.___", state 2346, "(1)" + line 425, "pan.___", state 2354, "(1)" + line 425, "pan.___", state 2355, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 2355, "else" + line 425, "pan.___", state 2358, "(1)" + line 425, "pan.___", state 2359, "(1)" + line 425, "pan.___", state 2359, "(1)" + line 423, "pan.___", state 2364, "((i<2))" + line 423, "pan.___", state 2364, "((i>=2))" + line 430, "pan.___", state 2368, "(1)" + line 430, "pan.___", state 2368, "(1)" + line 726, "pan.___", state 2371, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 726, "pan.___", state 2372, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 726, "pan.___", state 2373, "(1)" + line 395, "pan.___", state 2380, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2412, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2426, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2445, "(1)" + line 421, "pan.___", state 2475, "(1)" + line 425, "pan.___", state 2488, "(1)" + line 395, "pan.___", state 2515, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2547, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2561, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2580, "(1)" + line 421, "pan.___", state 2610, "(1)" + line 425, "pan.___", state 2623, "(1)" + line 395, "pan.___", state 2644, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2676, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2690, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2709, "(1)" + line 421, "pan.___", state 2739, "(1)" + line 425, "pan.___", state 2752, "(1)" + line 227, "pan.___", state 2785, "(1)" + line 235, "pan.___", state 2805, "(1)" + line 239, "pan.___", state 2813, "(1)" + line 227, "pan.___", state 2828, "(1)" + line 235, "pan.___", state 2848, "(1)" + line 239, "pan.___", state 2856, "(1)" + line 877, "pan.___", state 2873, "-end-" + (278 of 2873 states) +unreached in proctype urcu_writer + line 395, "pan.___", state 20, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 26, "(1)" + line 399, "pan.___", state 34, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 40, "(1)" + line 399, "pan.___", state 41, "(1)" + line 399, "pan.___", state 41, "(1)" + line 397, "pan.___", state 46, "((i<1))" + line 397, "pan.___", state 46, "((i>=1))" + line 404, "pan.___", state 52, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 58, "(1)" + line 404, "pan.___", state 59, "(1)" + line 404, "pan.___", state 59, "(1)" + line 408, "pan.___", state 72, "(1)" + line 408, "pan.___", state 73, "(1)" + line 408, "pan.___", state 73, "(1)" + line 406, "pan.___", state 78, "((i<2))" + line 406, "pan.___", state 78, "((i>=2))" + line 412, "pan.___", state 85, "(1)" + line 412, "pan.___", state 86, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 86, "else" + line 412, "pan.___", state 89, "(1)" + line 412, "pan.___", state 90, "(1)" + line 412, "pan.___", state 90, "(1)" + line 416, "pan.___", state 98, "(1)" + line 416, "pan.___", state 99, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 99, "else" + line 416, "pan.___", state 102, "(1)" + line 416, "pan.___", state 103, "(1)" + line 416, "pan.___", state 103, "(1)" + line 414, "pan.___", state 108, "((i<1))" + line 414, "pan.___", state 108, "((i>=1))" + line 421, "pan.___", state 115, "(1)" + line 421, "pan.___", state 116, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 116, "else" + line 421, "pan.___", state 119, "(1)" + line 421, "pan.___", state 120, "(1)" + line 421, "pan.___", state 120, "(1)" + line 425, "pan.___", state 128, "(1)" + line 425, "pan.___", state 129, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 129, "else" + line 425, "pan.___", state 132, "(1)" + line 425, "pan.___", state 133, "(1)" + line 425, "pan.___", state 133, "(1)" + line 423, "pan.___", state 138, "((i<2))" + line 423, "pan.___", state 138, "((i>=2))" + line 430, "pan.___", state 142, "(1)" + line 430, "pan.___", state 142, "(1)" + line 250, "pan.___", state 151, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 160, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 252, "pan.___", state 168, "((i<1))" + line 252, "pan.___", state 168, "((i>=1))" + line 258, "pan.___", state 173, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 1000, "pan.___", state 201, "old_data = cached_rcu_ptr.val[_pid]" + line 1011, "pan.___", state 205, "_proc_urcu_writer = (_proc_urcu_writer|(1<<4))" + line 395, "pan.___", state 213, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 219, "(1)" + line 399, "pan.___", state 227, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 233, "(1)" + line 399, "pan.___", state 234, "(1)" + line 399, "pan.___", state 234, "(1)" + line 397, "pan.___", state 239, "((i<1))" + line 397, "pan.___", state 239, "((i>=1))" + line 404, "pan.___", state 247, "(1)" + line 404, "pan.___", state 248, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 248, "else" + line 404, "pan.___", state 251, "(1)" + line 404, "pan.___", state 252, "(1)" + line 404, "pan.___", state 252, "(1)" + line 408, "pan.___", state 259, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 265, "(1)" + line 408, "pan.___", state 266, "(1)" + line 408, "pan.___", state 266, "(1)" + line 406, "pan.___", state 271, "((i<2))" + line 406, "pan.___", state 271, "((i>=2))" + line 412, "pan.___", state 278, "(1)" + line 412, "pan.___", state 279, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 279, "else" + line 412, "pan.___", state 282, "(1)" + line 412, "pan.___", state 283, "(1)" + line 412, "pan.___", state 283, "(1)" + line 416, "pan.___", state 291, "(1)" + line 416, "pan.___", state 292, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 292, "else" + line 416, "pan.___", state 295, "(1)" + line 416, "pan.___", state 296, "(1)" + line 416, "pan.___", state 296, "(1)" + line 414, "pan.___", state 301, "((i<1))" + line 414, "pan.___", state 301, "((i>=1))" + line 421, "pan.___", state 308, "(1)" + line 421, "pan.___", state 309, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 309, "else" + line 421, "pan.___", state 312, "(1)" + line 421, "pan.___", state 313, "(1)" + line 421, "pan.___", state 313, "(1)" + line 425, "pan.___", state 321, "(1)" + line 425, "pan.___", state 322, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 322, "else" + line 425, "pan.___", state 325, "(1)" + line 425, "pan.___", state 326, "(1)" + line 425, "pan.___", state 326, "(1)" + line 423, "pan.___", state 331, "((i<2))" + line 423, "pan.___", state 331, "((i>=2))" + line 430, "pan.___", state 335, "(1)" + line 430, "pan.___", state 335, "(1)" + line 395, "pan.___", state 346, "(1)" + line 395, "pan.___", state 347, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 347, "else" + line 395, "pan.___", state 350, "(1)" + line 399, "pan.___", state 358, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 364, "(1)" + line 399, "pan.___", state 365, "(1)" + line 399, "pan.___", state 365, "(1)" + line 397, "pan.___", state 370, "((i<1))" + line 397, "pan.___", state 370, "((i>=1))" + line 404, "pan.___", state 376, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 382, "(1)" + line 404, "pan.___", state 383, "(1)" + line 404, "pan.___", state 383, "(1)" + line 408, "pan.___", state 390, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 396, "(1)" + line 408, "pan.___", state 397, "(1)" + line 408, "pan.___", state 397, "(1)" + line 406, "pan.___", state 402, "((i<2))" + line 406, "pan.___", state 402, "((i>=2))" + line 412, "pan.___", state 409, "(1)" + line 412, "pan.___", state 410, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 410, "else" + line 412, "pan.___", state 413, "(1)" + line 412, "pan.___", state 414, "(1)" + line 412, "pan.___", state 414, "(1)" + line 416, "pan.___", state 422, "(1)" + line 416, "pan.___", state 423, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 423, "else" + line 416, "pan.___", state 426, "(1)" + line 416, "pan.___", state 427, "(1)" + line 416, "pan.___", state 427, "(1)" + line 414, "pan.___", state 432, "((i<1))" + line 414, "pan.___", state 432, "((i>=1))" + line 421, "pan.___", state 439, "(1)" + line 421, "pan.___", state 440, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 440, "else" + line 421, "pan.___", state 443, "(1)" + line 421, "pan.___", state 444, "(1)" + line 421, "pan.___", state 444, "(1)" + line 425, "pan.___", state 452, "(1)" + line 425, "pan.___", state 453, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 453, "else" + line 425, "pan.___", state 456, "(1)" + line 425, "pan.___", state 457, "(1)" + line 425, "pan.___", state 457, "(1)" + line 423, "pan.___", state 462, "((i<2))" + line 423, "pan.___", state 462, "((i>=2))" + line 430, "pan.___", state 466, "(1)" + line 430, "pan.___", state 466, "(1)" + line 1063, "pan.___", state 477, "_proc_urcu_writer = (_proc_urcu_writer&~(((1<<8)|(1<<7))))" + line 395, "pan.___", state 482, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 488, "(1)" + line 399, "pan.___", state 496, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 502, "(1)" + line 399, "pan.___", state 503, "(1)" + line 399, "pan.___", state 503, "(1)" + line 397, "pan.___", state 508, "((i<1))" + line 397, "pan.___", state 508, "((i>=1))" + line 404, "pan.___", state 514, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 520, "(1)" + line 404, "pan.___", state 521, "(1)" + line 404, "pan.___", state 521, "(1)" + line 408, "pan.___", state 528, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 534, "(1)" + line 408, "pan.___", state 535, "(1)" + line 408, "pan.___", state 535, "(1)" + line 406, "pan.___", state 540, "((i<2))" + line 406, "pan.___", state 540, "((i>=2))" + line 412, "pan.___", state 547, "(1)" + line 412, "pan.___", state 548, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 548, "else" + line 412, "pan.___", state 551, "(1)" + line 412, "pan.___", state 552, "(1)" + line 412, "pan.___", state 552, "(1)" + line 416, "pan.___", state 560, "(1)" + line 416, "pan.___", state 561, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 561, "else" + line 416, "pan.___", state 564, "(1)" + line 416, "pan.___", state 565, "(1)" + line 416, "pan.___", state 565, "(1)" + line 414, "pan.___", state 570, "((i<1))" + line 414, "pan.___", state 570, "((i>=1))" + line 421, "pan.___", state 577, "(1)" + line 421, "pan.___", state 578, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 578, "else" + line 421, "pan.___", state 581, "(1)" + line 421, "pan.___", state 582, "(1)" + line 421, "pan.___", state 582, "(1)" + line 425, "pan.___", state 590, "(1)" + line 425, "pan.___", state 591, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 591, "else" + line 425, "pan.___", state 594, "(1)" + line 425, "pan.___", state 595, "(1)" + line 425, "pan.___", state 595, "(1)" + line 430, "pan.___", state 604, "(1)" + line 430, "pan.___", state 604, "(1)" + line 395, "pan.___", state 611, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 625, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 643, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 412, "pan.___", state 676, "(1)" + line 416, "pan.___", state 689, "(1)" + line 421, "pan.___", state 706, "(1)" + line 425, "pan.___", state 719, "(1)" + line 399, "pan.___", state 756, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 774, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 788, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 820, "(1)" + line 421, "pan.___", state 837, "(1)" + line 425, "pan.___", state 850, "(1)" + line 1135, "pan.___", state 877, "_proc_urcu_writer = (_proc_urcu_writer|(1<<13))" + line 250, "pan.___", state 905, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 907, "(1)" + line 254, "pan.___", state 914, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 916, "(1)" + line 254, "pan.___", state 917, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 917, "else" + line 252, "pan.___", state 922, "((i<1))" + line 252, "pan.___", state 922, "((i>=1))" + line 258, "pan.___", state 927, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 929, "(1)" + line 258, "pan.___", state 930, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 930, "else" + line 262, "pan.___", state 936, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 938, "(1)" + line 262, "pan.___", state 939, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 939, "else" + line 260, "pan.___", state 944, "((i<2))" + line 260, "pan.___", state 944, "((i>=2))" + line 227, "pan.___", state 952, "(1)" + line 231, "pan.___", state 960, "(1)" + line 231, "pan.___", state 961, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 961, "else" + line 229, "pan.___", state 966, "((i<1))" + line 229, "pan.___", state 966, "((i>=1))" + line 235, "pan.___", state 972, "(1)" + line 235, "pan.___", state 973, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 973, "else" + line 239, "pan.___", state 980, "(1)" + line 239, "pan.___", state 981, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 981, "else" + line 244, "pan.___", state 990, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 990, "else" + line 1189, "pan.___", state 1006, "((i<1))" + line 1189, "pan.___", state 1006, "((i>=1))" + line 250, "pan.___", state 1011, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1013, "(1)" + line 254, "pan.___", state 1020, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1022, "(1)" + line 254, "pan.___", state 1023, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1023, "else" + line 252, "pan.___", state 1028, "((i<1))" + line 252, "pan.___", state 1028, "((i>=1))" + line 258, "pan.___", state 1033, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1035, "(1)" + line 258, "pan.___", state 1036, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1036, "else" + line 262, "pan.___", state 1042, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1044, "(1)" + line 262, "pan.___", state 1045, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1045, "else" + line 260, "pan.___", state 1050, "((i<2))" + line 260, "pan.___", state 1050, "((i>=2))" + line 227, "pan.___", state 1058, "(1)" + line 231, "pan.___", state 1066, "(1)" + line 231, "pan.___", state 1067, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1067, "else" + line 229, "pan.___", state 1072, "((i<1))" + line 229, "pan.___", state 1072, "((i>=1))" + line 235, "pan.___", state 1078, "(1)" + line 235, "pan.___", state 1079, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1079, "else" + line 239, "pan.___", state 1086, "(1)" + line 239, "pan.___", state 1087, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1087, "else" + line 244, "pan.___", state 1096, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1096, "else" + line 277, "pan.___", state 1098, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 1098, "else" + line 1189, "pan.___", state 1099, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 1189, "pan.___", state 1099, "else" + line 250, "pan.___", state 1103, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1105, "(1)" + line 254, "pan.___", state 1112, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1114, "(1)" + line 254, "pan.___", state 1115, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1115, "else" + line 252, "pan.___", state 1120, "((i<1))" + line 252, "pan.___", state 1120, "((i>=1))" + line 258, "pan.___", state 1125, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1127, "(1)" + line 258, "pan.___", state 1128, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1128, "else" + line 262, "pan.___", state 1134, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1136, "(1)" + line 262, "pan.___", state 1137, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1137, "else" + line 260, "pan.___", state 1142, "((i<2))" + line 260, "pan.___", state 1142, "((i>=2))" + line 227, "pan.___", state 1150, "(1)" + line 231, "pan.___", state 1158, "(1)" + line 231, "pan.___", state 1159, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1159, "else" + line 229, "pan.___", state 1164, "((i<1))" + line 229, "pan.___", state 1164, "((i>=1))" + line 235, "pan.___", state 1170, "(1)" + line 235, "pan.___", state 1171, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1171, "else" + line 239, "pan.___", state 1178, "(1)" + line 239, "pan.___", state 1179, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1179, "else" + line 244, "pan.___", state 1188, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1188, "else" + line 1193, "pan.___", state 1191, "i = 0" + line 1193, "pan.___", state 1193, "reader_barrier = 1" + line 1193, "pan.___", state 1204, "((i<1))" + line 1193, "pan.___", state 1204, "((i>=1))" + line 250, "pan.___", state 1209, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1211, "(1)" + line 254, "pan.___", state 1218, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1220, "(1)" + line 254, "pan.___", state 1221, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1221, "else" + line 252, "pan.___", state 1226, "((i<1))" + line 252, "pan.___", state 1226, "((i>=1))" + line 258, "pan.___", state 1231, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1233, "(1)" + line 258, "pan.___", state 1234, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1234, "else" + line 262, "pan.___", state 1240, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1242, "(1)" + line 262, "pan.___", state 1243, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1243, "else" + line 260, "pan.___", state 1248, "((i<2))" + line 260, "pan.___", state 1248, "((i>=2))" + line 227, "pan.___", state 1256, "(1)" + line 231, "pan.___", state 1264, "(1)" + line 231, "pan.___", state 1265, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1265, "else" + line 229, "pan.___", state 1270, "((i<1))" + line 229, "pan.___", state 1270, "((i>=1))" + line 235, "pan.___", state 1276, "(1)" + line 235, "pan.___", state 1277, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1277, "else" + line 239, "pan.___", state 1284, "(1)" + line 239, "pan.___", state 1285, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1285, "else" + line 244, "pan.___", state 1294, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1294, "else" + line 277, "pan.___", state 1296, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 1296, "else" + line 1193, "pan.___", state 1297, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 1193, "pan.___", state 1297, "else" + line 254, "pan.___", state 1310, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1323, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1332, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1348, "(1)" + line 231, "pan.___", state 1356, "(1)" + line 235, "pan.___", state 1368, "(1)" + line 239, "pan.___", state 1376, "(1)" + line 250, "pan.___", state 1407, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1416, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1429, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1438, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1454, "(1)" + line 231, "pan.___", state 1462, "(1)" + line 235, "pan.___", state 1474, "(1)" + line 239, "pan.___", state 1482, "(1)" + line 250, "pan.___", state 1499, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1501, "(1)" + line 254, "pan.___", state 1508, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1510, "(1)" + line 254, "pan.___", state 1511, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1511, "else" + line 252, "pan.___", state 1516, "((i<1))" + line 252, "pan.___", state 1516, "((i>=1))" + line 258, "pan.___", state 1521, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1523, "(1)" + line 258, "pan.___", state 1524, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1524, "else" + line 262, "pan.___", state 1530, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1532, "(1)" + line 262, "pan.___", state 1533, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1533, "else" + line 260, "pan.___", state 1538, "((i<2))" + line 260, "pan.___", state 1538, "((i>=2))" + line 227, "pan.___", state 1546, "(1)" + line 231, "pan.___", state 1554, "(1)" + line 231, "pan.___", state 1555, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1555, "else" + line 229, "pan.___", state 1560, "((i<1))" + line 229, "pan.___", state 1560, "((i>=1))" + line 235, "pan.___", state 1566, "(1)" + line 235, "pan.___", state 1567, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1567, "else" + line 239, "pan.___", state 1574, "(1)" + line 239, "pan.___", state 1575, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1575, "else" + line 244, "pan.___", state 1584, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1584, "else" + line 1200, "pan.___", state 1587, "i = 0" + line 1200, "pan.___", state 1589, "reader_barrier = 1" + line 1200, "pan.___", state 1600, "((i<1))" + line 1200, "pan.___", state 1600, "((i>=1))" + line 250, "pan.___", state 1605, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1607, "(1)" + line 254, "pan.___", state 1614, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1616, "(1)" + line 254, "pan.___", state 1617, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1617, "else" + line 252, "pan.___", state 1622, "((i<1))" + line 252, "pan.___", state 1622, "((i>=1))" + line 258, "pan.___", state 1627, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1629, "(1)" + line 258, "pan.___", state 1630, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1630, "else" + line 262, "pan.___", state 1636, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1638, "(1)" + line 262, "pan.___", state 1639, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1639, "else" + line 260, "pan.___", state 1644, "((i<2))" + line 260, "pan.___", state 1644, "((i>=2))" + line 227, "pan.___", state 1652, "(1)" + line 231, "pan.___", state 1660, "(1)" + line 231, "pan.___", state 1661, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1661, "else" + line 229, "pan.___", state 1666, "((i<1))" + line 229, "pan.___", state 1666, "((i>=1))" + line 235, "pan.___", state 1672, "(1)" + line 235, "pan.___", state 1673, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1673, "else" + line 239, "pan.___", state 1680, "(1)" + line 239, "pan.___", state 1681, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1681, "else" + line 244, "pan.___", state 1690, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1690, "else" + line 277, "pan.___", state 1692, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 1692, "else" + line 1200, "pan.___", state 1693, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 1200, "pan.___", state 1693, "else" + line 1204, "pan.___", state 1696, "-end-" + (310 of 1696 states) +unreached in proctype :init: + line 1215, "pan.___", state 9, "((j<2))" + line 1215, "pan.___", state 9, "((j>=2))" + line 1216, "pan.___", state 20, "((j<2))" + line 1216, "pan.___", state 20, "((j>=2))" + line 1221, "pan.___", state 33, "((j<2))" + line 1221, "pan.___", state 33, "((j>=2))" + line 1219, "pan.___", state 43, "((i<1))" + line 1219, "pan.___", state 43, "((i>=1))" + line 1229, "pan.___", state 54, "((j<2))" + line 1229, "pan.___", state 54, "((j>=2))" + line 1233, "pan.___", state 67, "((j<2))" + line 1233, "pan.___", state 67, "((j>=2))" + (6 of 78 states) +unreached in proctype :never: + line 1263, "pan.___", state 8, "-end-" + (1 of 8 states) + +pan: elapsed time 92.4 seconds +pan: rate 5975.3706 states/second +pan: avg transition delay 1.2521e-06 usec +cp .input.spin urcu_free_no_mb.spin.input +cp .input.spin.trail urcu_free_no_mb.spin.input.trail diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_mb.spin.input b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_mb.spin.input new file mode 100644 index 0000000..a930be8 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_mb.spin.input @@ -0,0 +1,1240 @@ +#define NO_MB + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_mb.spin.input.trail b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_mb.spin.input.trail new file mode 100644 index 0000000..582fc24 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_mb.spin.input.trail @@ -0,0 +1,1423 @@ +-2:3:-2 +-4:-4:-4 +1:0:4649 +2:3:4569 +3:3:4572 +4:3:4572 +5:3:4575 +6:3:4583 +7:3:4583 +8:3:4586 +9:3:4592 +10:3:4596 +11:3:4596 +12:3:4599 +13:3:4609 +14:3:4617 +15:3:4617 +16:3:4620 +17:3:4626 +18:3:4630 +19:3:4630 +20:3:4633 +21:3:4639 +22:3:4643 +23:3:4644 +24:0:4649 +25:3:4646 +26:0:4649 +27:2:2875 +28:0:4649 +29:2:2881 +30:0:4649 +31:2:2882 +32:0:4649 +33:2:2884 +34:0:4649 +35:2:2885 +36:0:4649 +37:2:2886 +38:0:4649 +39:2:2887 +40:0:4649 +41:2:2888 +42:2:2889 +43:2:2893 +44:2:2894 +45:2:2902 +46:2:2903 +47:2:2907 +48:2:2908 +49:2:2916 +50:2:2921 +51:2:2925 +52:2:2926 +53:2:2934 +54:2:2935 +55:2:2939 +56:2:2940 +57:2:2934 +58:2:2935 +59:2:2939 +60:2:2940 +61:2:2948 +62:2:2953 +63:2:2954 +64:2:2965 +65:2:2966 +66:2:2967 +67:2:2978 +68:2:2983 +69:2:2984 +70:2:2995 +71:2:2996 +72:2:2997 +73:2:2995 +74:2:2996 +75:2:2997 +76:2:3008 +77:2:3016 +78:0:4649 +79:2:2887 +80:0:4649 +81:2:3020 +82:2:3024 +83:2:3025 +84:2:3029 +85:2:3033 +86:2:3034 +87:2:3038 +88:2:3046 +89:2:3047 +90:2:3051 +91:2:3055 +92:2:3056 +93:2:3051 +94:2:3052 +95:2:3060 +96:0:4649 +97:2:2887 +98:0:4649 +99:2:3068 +100:2:3069 +101:2:3070 +102:0:4649 +103:2:2887 +104:0:4649 +105:2:3078 +106:0:4649 +107:2:2887 +108:0:4649 +109:2:3081 +110:2:3082 +111:2:3086 +112:2:3087 +113:2:3095 +114:2:3096 +115:2:3100 +116:2:3101 +117:2:3109 +118:2:3114 +119:2:3115 +120:2:3127 +121:2:3128 +122:2:3132 +123:2:3133 +124:2:3127 +125:2:3128 +126:2:3132 +127:2:3133 +128:2:3141 +129:2:3146 +130:2:3147 +131:2:3158 +132:2:3159 +133:2:3160 +134:2:3171 +135:2:3176 +136:2:3177 +137:2:3188 +138:2:3189 +139:2:3190 +140:2:3188 +141:2:3189 +142:2:3190 +143:2:3201 +144:2:3208 +145:0:4649 +146:2:2887 +147:0:4649 +148:2:3212 +149:2:3213 +150:2:3214 +151:2:3226 +152:2:3227 +153:2:3231 +154:2:3232 +155:2:3240 +156:2:3245 +157:2:3249 +158:2:3250 +159:2:3258 +160:2:3259 +161:2:3263 +162:2:3264 +163:2:3258 +164:2:3259 +165:2:3263 +166:2:3264 +167:2:3272 +168:2:3277 +169:2:3278 +170:2:3289 +171:2:3290 +172:2:3291 +173:2:3302 +174:2:3307 +175:2:3308 +176:2:3319 +177:2:3320 +178:2:3321 +179:2:3319 +180:2:3320 +181:2:3321 +182:2:3332 +183:2:3343 +184:2:3344 +185:0:4649 +186:2:2887 +187:0:4649 +188:2:3350 +189:2:3351 +190:2:3355 +191:2:3356 +192:2:3364 +193:2:3365 +194:2:3369 +195:2:3370 +196:2:3378 +197:2:3383 +198:2:3387 +199:2:3388 +200:2:3396 +201:2:3397 +202:2:3401 +203:2:3402 +204:2:3396 +205:2:3397 +206:2:3401 +207:2:3402 +208:2:3410 +209:2:3415 +210:2:3416 +211:2:3427 +212:2:3428 +213:2:3429 +214:2:3440 +215:2:3445 +216:2:3446 +217:2:3457 +218:2:3458 +219:2:3459 +220:2:3457 +221:2:3458 +222:2:3459 +223:2:3470 +224:0:4649 +225:2:2887 +226:0:4649 +227:2:3479 +228:2:3480 +229:2:3484 +230:2:3485 +231:2:3493 +232:2:3494 +233:2:3498 +234:2:3499 +235:2:3507 +236:2:3512 +237:2:3516 +238:2:3517 +239:2:3525 +240:2:3526 +241:2:3530 +242:2:3531 +243:2:3525 +244:2:3526 +245:2:3530 +246:2:3531 +247:2:3539 +248:2:3544 +249:2:3545 +250:2:3556 +251:2:3557 +252:2:3558 +253:2:3569 +254:2:3574 +255:2:3575 +256:2:3586 +257:2:3587 +258:2:3588 +259:2:3586 +260:2:3587 +261:2:3588 +262:2:3599 +263:2:3606 +264:0:4649 +265:2:2887 +266:0:4649 +267:2:3610 +268:2:3611 +269:2:3612 +270:2:3624 +271:2:3625 +272:2:3629 +273:2:3630 +274:2:3638 +275:2:3643 +276:2:3647 +277:2:3648 +278:2:3656 +279:2:3657 +280:2:3661 +281:2:3662 +282:2:3656 +283:2:3657 +284:2:3661 +285:2:3662 +286:2:3670 +287:2:3675 +288:2:3676 +289:2:3687 +290:2:3688 +291:2:3689 +292:2:3700 +293:2:3705 +294:2:3706 +295:2:3717 +296:2:3718 +297:2:3719 +298:2:3717 +299:2:3718 +300:2:3719 +301:2:3730 +302:2:3740 +303:2:3741 +304:0:4649 +305:2:2887 +306:0:4649 +307:2:3750 +308:2:3751 +309:0:4649 +310:2:2887 +311:0:4649 +312:2:3755 +313:0:4649 +314:2:3763 +315:0:4649 +316:2:2882 +317:0:4649 +318:2:2884 +319:0:4649 +320:2:2885 +321:0:4649 +322:2:2886 +323:0:4649 +324:2:2887 +325:0:4649 +326:2:2888 +327:2:2889 +328:2:2893 +329:2:2894 +330:2:2902 +331:2:2903 +332:2:2907 +333:2:2908 +334:2:2916 +335:2:2921 +336:2:2925 +337:2:2926 +338:2:2934 +339:2:2935 +340:2:2936 +341:2:2934 +342:2:2935 +343:2:2939 +344:2:2940 +345:2:2948 +346:2:2953 +347:2:2954 +348:2:2965 +349:2:2966 +350:2:2967 +351:2:2978 +352:2:2983 +353:2:2984 +354:2:2995 +355:2:2996 +356:2:2997 +357:2:2995 +358:2:2996 +359:2:2997 +360:2:3008 +361:2:3016 +362:0:4649 +363:2:2887 +364:0:4649 +365:2:3020 +366:2:3024 +367:2:3025 +368:2:3029 +369:2:3033 +370:2:3034 +371:2:3038 +372:2:3046 +373:2:3047 +374:2:3051 +375:2:3052 +376:2:3051 +377:2:3055 +378:2:3056 +379:2:3060 +380:0:4649 +381:2:2887 +382:0:4649 +383:2:3068 +384:2:3069 +385:2:3070 +386:0:4649 +387:2:2887 +388:0:4649 +389:2:3078 +390:0:4649 +391:2:2887 +392:0:4649 +393:2:3081 +394:2:3082 +395:2:3086 +396:2:3087 +397:2:3095 +398:2:3096 +399:2:3100 +400:2:3101 +401:2:3109 +402:2:3114 +403:2:3115 +404:2:3127 +405:2:3128 +406:2:3132 +407:2:3133 +408:2:3127 +409:2:3128 +410:2:3132 +411:2:3133 +412:2:3141 +413:2:3146 +414:2:3147 +415:2:3158 +416:2:3159 +417:2:3160 +418:2:3171 +419:2:3176 +420:2:3177 +421:2:3188 +422:2:3189 +423:2:3190 +424:2:3188 +425:2:3189 +426:2:3190 +427:2:3201 +428:2:3208 +429:0:4649 +430:2:2887 +431:0:4649 +432:2:3212 +433:2:3213 +434:2:3214 +435:2:3226 +436:2:3227 +437:2:3231 +438:2:3232 +439:2:3240 +440:2:3245 +441:2:3249 +442:2:3250 +443:2:3258 +444:2:3259 +445:2:3263 +446:2:3264 +447:2:3258 +448:2:3259 +449:2:3263 +450:2:3264 +451:2:3272 +452:2:3277 +453:2:3278 +454:2:3289 +455:2:3290 +456:2:3291 +457:2:3302 +458:2:3307 +459:2:3308 +460:2:3319 +461:2:3320 +462:2:3321 +463:2:3319 +464:2:3320 +465:2:3321 +466:2:3332 +467:2:3343 +468:2:3344 +469:0:4649 +470:2:2887 +471:0:4649 +472:2:3350 +473:2:3351 +474:2:3355 +475:2:3356 +476:2:3364 +477:2:3365 +478:2:3369 +479:2:3370 +480:2:3378 +481:2:3383 +482:2:3387 +483:2:3388 +484:2:3396 +485:2:3397 +486:2:3401 +487:2:3402 +488:2:3396 +489:2:3397 +490:2:3401 +491:2:3402 +492:2:3410 +493:2:3415 +494:2:3416 +495:2:3427 +496:2:3428 +497:2:3429 +498:2:3440 +499:2:3445 +500:2:3446 +501:2:3457 +502:2:3458 +503:2:3459 +504:2:3457 +505:2:3458 +506:2:3459 +507:2:3470 +508:0:4649 +509:2:2887 +510:0:4649 +511:2:3479 +512:2:3480 +513:2:3484 +514:2:3485 +515:2:3493 +516:2:3494 +517:2:3498 +518:2:3499 +519:2:3507 +520:2:3512 +521:2:3516 +522:2:3517 +523:2:3525 +524:2:3526 +525:2:3530 +526:2:3531 +527:2:3525 +528:2:3526 +529:2:3530 +530:2:3531 +531:2:3539 +532:2:3544 +533:2:3545 +534:2:3556 +535:2:3557 +536:2:3558 +537:2:3569 +538:2:3574 +539:2:3575 +540:2:3586 +541:2:3587 +542:2:3588 +543:2:3586 +544:2:3587 +545:2:3588 +546:2:3599 +547:2:3606 +548:0:4649 +549:2:2887 +550:0:4649 +551:2:3610 +552:2:3611 +553:2:3612 +554:2:3624 +555:2:3625 +556:2:3629 +557:2:3630 +558:2:3638 +559:2:3643 +560:2:3647 +561:2:3648 +562:2:3656 +563:2:3657 +564:2:3661 +565:2:3662 +566:2:3656 +567:2:3657 +568:2:3661 +569:2:3662 +570:2:3670 +571:2:3675 +572:2:3676 +573:2:3687 +574:2:3688 +575:2:3689 +576:2:3700 +577:2:3705 +578:2:3706 +579:2:3717 +580:2:3718 +581:2:3719 +582:2:3717 +583:2:3718 +584:2:3719 +585:2:3730 +586:2:3740 +587:2:3741 +588:0:4649 +589:2:2887 +590:0:4649 +591:2:3750 +592:2:3751 +593:0:4649 +594:2:2887 +595:0:4649 +596:2:3755 +597:0:4649 +598:2:3763 +599:0:4649 +600:2:2882 +601:0:4649 +602:2:2884 +603:0:4649 +604:2:2885 +605:0:4649 +606:2:2886 +607:0:4649 +608:2:2887 +609:0:4649 +610:2:2888 +611:2:2889 +612:2:2893 +613:2:2894 +614:2:2902 +615:2:2903 +616:2:2907 +617:2:2908 +618:2:2916 +619:2:2921 +620:2:2925 +621:2:2926 +622:2:2934 +623:2:2935 +624:2:2939 +625:2:2940 +626:2:2934 +627:2:2935 +628:2:2936 +629:2:2948 +630:2:2953 +631:2:2954 +632:2:2965 +633:2:2966 +634:2:2967 +635:2:2978 +636:2:2983 +637:2:2984 +638:2:2995 +639:2:2996 +640:2:2997 +641:2:2995 +642:2:2996 +643:2:2997 +644:2:3008 +645:2:3016 +646:0:4649 +647:2:2887 +648:0:4649 +649:2:3020 +650:2:3024 +651:2:3025 +652:2:3029 +653:2:3033 +654:2:3034 +655:2:3038 +656:2:3046 +657:2:3047 +658:2:3051 +659:2:3055 +660:2:3056 +661:2:3051 +662:2:3052 +663:2:3060 +664:0:4649 +665:2:2887 +666:0:4649 +667:2:3068 +668:2:3069 +669:2:3070 +670:0:4649 +671:2:2887 +672:0:4649 +673:2:3078 +674:0:4649 +675:2:2887 +676:0:4649 +677:2:3081 +678:2:3082 +679:2:3086 +680:2:3087 +681:2:3095 +682:2:3096 +683:2:3100 +684:2:3101 +685:2:3109 +686:2:3114 +687:2:3115 +688:2:3127 +689:2:3128 +690:2:3132 +691:2:3133 +692:2:3127 +693:2:3128 +694:2:3132 +695:2:3133 +696:2:3141 +697:2:3146 +698:2:3147 +699:2:3158 +700:2:3159 +701:2:3160 +702:2:3171 +703:2:3176 +704:2:3177 +705:2:3188 +706:2:3189 +707:2:3190 +708:2:3188 +709:2:3189 +710:2:3190 +711:2:3201 +712:2:3208 +713:0:4649 +714:2:2887 +715:0:4649 +716:2:3212 +717:2:3213 +718:2:3214 +719:2:3226 +720:2:3227 +721:2:3231 +722:2:3232 +723:2:3240 +724:2:3245 +725:2:3249 +726:2:3250 +727:2:3258 +728:2:3259 +729:2:3263 +730:2:3264 +731:2:3258 +732:2:3259 +733:2:3263 +734:2:3264 +735:2:3272 +736:2:3277 +737:2:3278 +738:2:3289 +739:2:3290 +740:2:3291 +741:2:3302 +742:2:3307 +743:2:3308 +744:2:3319 +745:2:3320 +746:2:3321 +747:2:3319 +748:2:3320 +749:2:3321 +750:2:3332 +751:2:3343 +752:2:3344 +753:0:4649 +754:2:2887 +755:0:4649 +756:2:3350 +757:2:3351 +758:2:3355 +759:2:3356 +760:2:3364 +761:2:3365 +762:2:3369 +763:2:3370 +764:2:3378 +765:2:3383 +766:2:3387 +767:2:3388 +768:2:3396 +769:2:3397 +770:2:3401 +771:2:3402 +772:2:3396 +773:2:3397 +774:2:3401 +775:2:3402 +776:2:3410 +777:2:3415 +778:2:3416 +779:2:3427 +780:2:3428 +781:2:3429 +782:2:3440 +783:2:3445 +784:2:3446 +785:2:3457 +786:2:3458 +787:2:3459 +788:2:3457 +789:2:3458 +790:2:3459 +791:2:3470 +792:0:4649 +793:2:2887 +794:0:4649 +795:2:3610 +796:2:3611 +797:2:3615 +798:2:3616 +799:2:3624 +800:2:3625 +801:2:3629 +802:2:3630 +803:2:3638 +804:2:3643 +805:2:3647 +806:2:3648 +807:2:3656 +808:2:3657 +809:2:3661 +810:2:3662 +811:2:3656 +812:2:3657 +813:2:3661 +814:2:3662 +815:2:3670 +816:2:3675 +817:2:3676 +818:2:3687 +819:2:3688 +820:2:3689 +821:2:3700 +822:2:3705 +823:2:3706 +824:2:3717 +825:2:3718 +826:2:3719 +827:2:3717 +828:2:3718 +829:2:3719 +830:2:3730 +831:2:3740 +832:2:3741 +833:0:4649 +834:2:2887 +835:0:4649 +836:2:3750 +837:2:3751 +838:0:4649 +839:2:2887 +840:0:4649 +841:2:3479 +842:2:3480 +843:2:3484 +844:2:3485 +845:2:3493 +846:2:3494 +847:2:3498 +848:2:3499 +849:2:3507 +850:2:3512 +851:2:3516 +852:2:3517 +853:2:3525 +854:2:3526 +855:2:3527 +856:2:3525 +857:2:3526 +858:2:3530 +859:2:3531 +860:2:3539 +861:2:3544 +862:2:3545 +863:2:3556 +864:2:3557 +865:2:3558 +866:2:3569 +867:2:3574 +868:2:3575 +869:2:3586 +870:2:3587 +871:2:3588 +872:2:3586 +873:2:3587 +874:2:3588 +875:2:3599 +876:2:3606 +877:0:4649 +878:2:2887 +879:0:4649 +880:2:3755 +881:0:4649 +882:2:3763 +883:0:4649 +884:2:3764 +885:0:4649 +886:2:3769 +887:0:4649 +888:1:2 +889:0:4649 +890:2:3770 +891:0:4649 +892:1:8 +893:0:4649 +894:2:3769 +895:0:4649 +896:1:9 +897:0:4649 +898:2:3770 +899:0:4649 +900:1:10 +901:0:4649 +902:2:3769 +903:0:4649 +904:1:11 +905:0:4649 +906:2:3770 +907:0:4649 +908:1:12 +909:0:4649 +910:2:3769 +911:0:4649 +912:1:13 +913:0:4649 +914:2:3770 +915:0:4649 +916:1:14 +917:0:4649 +918:2:3769 +919:0:4649 +920:1:15 +921:0:4649 +922:2:3770 +923:0:4649 +924:1:16 +925:0:4649 +926:2:3769 +927:0:4649 +928:1:17 +929:0:4649 +930:2:3770 +931:0:4649 +932:1:18 +933:0:4649 +934:2:3769 +935:0:4649 +936:1:19 +937:0:4649 +938:2:3770 +939:0:4649 +940:1:20 +941:0:4649 +942:2:3769 +943:0:4649 +944:1:21 +945:0:4649 +946:2:3770 +947:0:4649 +948:1:122 +949:0:4649 +950:2:3769 +951:0:4649 +952:1:124 +953:0:4649 +954:2:3770 +955:0:4649 +956:1:23 +957:0:4649 +958:2:3769 +959:0:4649 +960:1:130 +961:1:131 +962:1:135 +963:1:136 +964:1:144 +965:1:145 +966:1:149 +967:1:150 +968:1:158 +969:1:163 +970:1:167 +971:1:168 +972:1:176 +973:1:177 +974:1:181 +975:1:182 +976:1:176 +977:1:177 +978:1:181 +979:1:182 +980:1:190 +981:1:195 +982:1:196 +983:1:207 +984:1:208 +985:1:209 +986:1:220 +987:1:232 +988:1:233 +989:1:237 +990:1:238 +991:1:239 +992:1:237 +993:1:238 +994:1:239 +995:1:250 +996:0:4649 +997:2:3770 +998:0:4649 +999:1:19 +1000:0:4649 +1001:2:3769 +1002:0:4649 +1003:1:20 +1004:0:4649 +1005:2:3770 +1006:0:4649 +1007:1:21 +1008:0:4649 +1009:2:3769 +1010:0:4649 +1011:1:122 +1012:0:4649 +1013:2:3770 +1014:0:4649 +1015:1:124 +1016:0:4649 +1017:2:3769 +1018:0:4649 +1019:1:23 +1020:0:4649 +1021:2:3770 +1022:0:4649 +1023:1:259 +1024:1:260 +1025:0:4649 +1026:2:3769 +1027:0:4649 +1028:1:19 +1029:0:4649 +1030:2:3770 +1031:0:4649 +1032:1:20 +1033:0:4649 +1034:2:3769 +1035:0:4649 +1036:1:21 +1037:0:4649 +1038:2:3770 +1039:0:4649 +1040:1:122 +1041:0:4649 +1042:2:3769 +1043:0:4649 +1044:1:124 +1045:0:4649 +1046:2:3770 +1047:0:4649 +1048:1:23 +1049:0:4649 +1050:2:3769 +1051:0:4649 +1052:1:266 +1053:1:267 +1054:1:271 +1055:1:272 +1056:1:280 +1057:1:281 +1058:1:285 +1059:1:286 +1060:1:294 +1061:1:299 +1062:1:303 +1063:1:304 +1064:1:312 +1065:1:313 +1066:1:317 +1067:1:318 +1068:1:312 +1069:1:313 +1070:1:317 +1071:1:318 +1072:1:326 +1073:1:331 +1074:1:332 +1075:1:343 +1076:1:344 +1077:1:345 +1078:1:356 +1079:1:368 +1080:1:369 +1081:1:373 +1082:1:374 +1083:1:375 +1084:1:373 +1085:1:374 +1086:1:375 +1087:1:386 +1088:0:4649 +1089:2:3770 +1090:0:4649 +1091:1:19 +1092:0:4649 +1093:2:3769 +1094:0:4649 +1095:1:20 +1096:0:4649 +1097:2:3770 +1098:0:4649 +1099:1:21 +1100:0:4649 +1101:2:3769 +1102:0:4649 +1103:1:122 +1104:0:4649 +1105:2:3770 +1106:0:4649 +1107:1:124 +1108:0:4649 +1109:2:3769 +1110:0:4649 +1111:1:23 +1112:0:4649 +1113:2:3770 +1114:0:4649 +1115:1:395 +1116:1:396 +1117:1:400 +1118:1:401 +1119:1:409 +1120:1:410 +1121:1:414 +1122:1:415 +1123:1:423 +1124:1:428 +1125:1:432 +1126:1:433 +1127:1:441 +1128:1:442 +1129:1:446 +1130:1:447 +1131:1:441 +1132:1:442 +1133:1:446 +1134:1:447 +1135:1:455 +1136:1:460 +1137:1:461 +1138:1:472 +1139:1:473 +1140:1:474 +1141:1:485 +1142:1:497 +1143:1:498 +1144:1:502 +1145:1:503 +1146:1:504 +1147:1:502 +1148:1:503 +1149:1:504 +1150:1:515 +1151:1:522 +1152:0:4649 +1153:2:3769 +1154:0:4649 +1155:1:19 +1156:0:4649 +1157:2:3770 +1158:0:4649 +1159:1:20 +1160:0:4649 +1161:2:3769 +1162:0:4649 +1163:1:21 +1164:0:4649 +1165:2:3770 +1166:0:4649 +1167:1:122 +1168:0:4649 +1169:2:3769 +1170:0:4649 +1171:1:124 +1172:0:4649 +1173:2:3770 +1174:0:4649 +1175:1:23 +1176:0:4649 +1177:2:3769 +1178:0:4649 +1179:1:660 +1180:1:661 +1181:1:665 +1182:1:666 +1183:1:674 +1184:1:675 +1185:1:676 +1186:1:688 +1187:1:693 +1188:1:697 +1189:1:698 +1190:1:706 +1191:1:707 +1192:1:711 +1193:1:712 +1194:1:706 +1195:1:707 +1196:1:711 +1197:1:712 +1198:1:720 +1199:1:725 +1200:1:726 +1201:1:737 +1202:1:738 +1203:1:739 +1204:1:750 +1205:1:762 +1206:1:763 +1207:1:767 +1208:1:768 +1209:1:769 +1210:1:767 +1211:1:768 +1212:1:769 +1213:1:780 +1214:0:4649 +1215:2:3770 +1216:0:4649 +1217:1:19 +1218:0:4649 +1219:2:3769 +1220:0:4649 +1221:1:20 +1222:0:4649 +1223:2:3770 +1224:0:4649 +1225:1:21 +1226:0:4649 +1227:2:3769 +1228:0:4649 +1229:1:122 +1230:0:4649 +1231:2:3770 +1232:0:4649 +1233:1:124 +1234:0:4649 +1235:2:3769 +1236:0:4649 +1237:1:23 +1238:0:4649 +1239:2:3770 +1240:0:4649 +1241:1:789 +1242:1:792 +1243:1:793 +1244:0:4649 +1245:2:3769 +1246:0:4649 +1247:1:19 +1248:0:4649 +1249:2:3770 +1250:0:4649 +1251:1:20 +1252:0:4649 +1253:2:3769 +1254:0:4649 +1255:1:21 +1256:0:4649 +1257:2:3770 +1258:0:4649 +1259:1:122 +1260:0:4649 +1261:2:3769 +1262:0:4649 +1263:1:124 +1264:0:4649 +1265:2:3770 +1266:0:4649 +1267:1:23 +1268:0:4649 +1269:2:3769 +1270:0:4649 +1271:1:1056 +1272:1:1057 +1273:1:1061 +1274:1:1062 +1275:1:1070 +1276:1:1071 +1277:1:1075 +1278:1:1076 +1279:1:1084 +1280:1:1089 +1281:1:1093 +1282:1:1094 +1283:1:1102 +1284:1:1103 +1285:1:1107 +1286:1:1108 +1287:1:1102 +1288:1:1103 +1289:1:1107 +1290:1:1108 +1291:1:1116 +1292:1:1121 +1293:1:1122 +1294:1:1133 +1295:1:1134 +1296:1:1135 +1297:1:1146 +1298:1:1158 +1299:1:1159 +1300:1:1163 +1301:1:1164 +1302:1:1165 +1303:1:1163 +1304:1:1164 +1305:1:1165 +1306:1:1176 +1307:1:1183 +1308:1:1187 +1309:0:4649 +1310:2:3770 +1311:0:4649 +1312:1:19 +1313:0:4649 +1314:2:3769 +1315:0:4649 +1316:1:20 +1317:0:4649 +1318:2:3770 +1319:0:4649 +1320:1:21 +1321:0:4649 +1322:2:3769 +1323:0:4649 +1324:1:122 +1325:0:4649 +1326:2:3770 +1327:0:4649 +1328:1:124 +1329:0:4649 +1330:2:3769 +1331:0:4649 +1332:1:23 +1333:0:4649 +1334:2:3770 +1335:0:4649 +1336:1:1188 +1337:1:1189 +1338:1:1193 +1339:1:1194 +1340:1:1202 +1341:1:1203 +1342:1:1204 +1343:1:1216 +1344:1:1221 +1345:1:1225 +1346:1:1226 +1347:1:1234 +1348:1:1235 +1349:1:1239 +1350:1:1240 +1351:1:1234 +1352:1:1235 +1353:1:1239 +1354:1:1240 +1355:1:1248 +1356:1:1253 +1357:1:1254 +1358:1:1265 +1359:1:1266 +1360:1:1267 +1361:1:1278 +1362:1:1290 +1363:1:1291 +1364:1:1295 +1365:1:1296 +1366:1:1297 +1367:1:1295 +1368:1:1296 +1369:1:1297 +1370:1:1308 +1371:0:4649 +1372:2:3769 +1373:0:4649 +1374:1:19 +1375:0:4649 +1376:2:3770 +1377:0:4649 +1378:1:20 +1379:0:4649 +1380:2:3769 +1381:0:4649 +1382:1:21 +1383:0:4649 +1384:2:3770 +1385:0:4649 +1386:1:122 +1387:0:4649 +1388:2:3769 +1389:0:4649 +1390:1:124 +1391:0:4649 +1392:2:3770 +1393:0:4649 +1394:1:23 +1395:0:4649 +1396:2:3769 +1397:0:4649 +1398:1:1317 +1399:0:4649 +1400:2:3770 +1401:0:4649 +1402:1:2781 +1403:1:2788 +1404:1:2789 +1405:1:2796 +1406:1:2801 +1407:1:2808 +1408:1:2809 +1409:1:2808 +1410:1:2809 +1411:1:2816 +1412:1:2820 +1413:0:4649 +1414:2:3769 +1415:0:4649 +1416:1:1319 +1417:1:1320 +1418:0:4647 +1419:2:3770 +1420:0:4653 +1421:1:2465 diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_rmb.define b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_rmb.define new file mode 100644 index 0000000..73e61a4 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_rmb.define @@ -0,0 +1 @@ +#define NO_RMB diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_rmb.log b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_rmb.log new file mode 100644 index 0000000..dd57567 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_rmb.log @@ -0,0 +1,581 @@ +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define >> pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_free.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_free_no_rmb.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1258) +Depth= 7365 States= 1e+06 Transitions= 1.38e+08 Memory= 550.432 t= 168 R= 6e+03 +Depth= 7365 States= 2e+06 Transitions= 4.31e+08 Memory= 634.318 t= 540 R= 4e+03 +pan: claim violated! (at depth 1624) +pan: wrote .input.spin.trail + +(Spin Version 5.1.7 -- 23 December 2008) +Warning: Search not completed + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness disabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 7365, errors: 1 + 2266036 states, stored +5.03936e+08 states, matched +5.0620203e+08 transitions (= stored+matched) +2.8832147e+09 atomic steps +hash conflicts: 3.6698737e+08 (resolved) + +Stats on memory usage (in Megabytes): + 250.683 equivalent memory usage for states (stored*(State-vector + overhead)) + 191.039 actual memory usage for states (compression: 76.21%) + state-vector as stored = 60 byte + 28 byte overhead + 8.000 memory used for hash table (-w20) + 457.764 memory used for DFS stack (-m10000000) + 656.682 total actual memory usage + +unreached in proctype urcu_reader + line 250, "pan.___", state 30, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 52, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 61, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 77, "(1)" + line 231, "pan.___", state 85, "(1)" + line 235, "pan.___", state 97, "(1)" + line 239, "pan.___", state 105, "(1)" + line 395, "pan.___", state 131, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 163, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 177, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 196, "(1)" + line 421, "pan.___", state 226, "(1)" + line 425, "pan.___", state 239, "(1)" + line 670, "pan.___", state 260, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 395, "pan.___", state 267, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 299, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 313, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 332, "(1)" + line 421, "pan.___", state 362, "(1)" + line 425, "pan.___", state 375, "(1)" + line 395, "pan.___", state 396, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 428, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 442, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 461, "(1)" + line 421, "pan.___", state 491, "(1)" + line 425, "pan.___", state 504, "(1)" + line 395, "pan.___", state 527, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 529, "(1)" + line 395, "pan.___", state 530, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 530, "else" + line 395, "pan.___", state 533, "(1)" + line 399, "pan.___", state 541, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 543, "(1)" + line 399, "pan.___", state 544, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 544, "else" + line 399, "pan.___", state 547, "(1)" + line 399, "pan.___", state 548, "(1)" + line 399, "pan.___", state 548, "(1)" + line 397, "pan.___", state 553, "((i<1))" + line 397, "pan.___", state 553, "((i>=1))" + line 404, "pan.___", state 559, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 561, "(1)" + line 404, "pan.___", state 562, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 562, "else" + line 404, "pan.___", state 565, "(1)" + line 404, "pan.___", state 566, "(1)" + line 404, "pan.___", state 566, "(1)" + line 408, "pan.___", state 573, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 575, "(1)" + line 408, "pan.___", state 576, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 576, "else" + line 408, "pan.___", state 579, "(1)" + line 408, "pan.___", state 580, "(1)" + line 408, "pan.___", state 580, "(1)" + line 406, "pan.___", state 585, "((i<2))" + line 406, "pan.___", state 585, "((i>=2))" + line 412, "pan.___", state 592, "(1)" + line 412, "pan.___", state 593, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 593, "else" + line 412, "pan.___", state 596, "(1)" + line 412, "pan.___", state 597, "(1)" + line 412, "pan.___", state 597, "(1)" + line 416, "pan.___", state 605, "(1)" + line 416, "pan.___", state 606, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 606, "else" + line 416, "pan.___", state 609, "(1)" + line 416, "pan.___", state 610, "(1)" + line 416, "pan.___", state 610, "(1)" + line 414, "pan.___", state 615, "((i<1))" + line 414, "pan.___", state 615, "((i>=1))" + line 421, "pan.___", state 622, "(1)" + line 421, "pan.___", state 623, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 623, "else" + line 421, "pan.___", state 626, "(1)" + line 421, "pan.___", state 627, "(1)" + line 421, "pan.___", state 627, "(1)" + line 425, "pan.___", state 635, "(1)" + line 425, "pan.___", state 636, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 636, "else" + line 425, "pan.___", state 639, "(1)" + line 425, "pan.___", state 640, "(1)" + line 425, "pan.___", state 640, "(1)" + line 423, "pan.___", state 645, "((i<2))" + line 423, "pan.___", state 645, "((i>=2))" + line 430, "pan.___", state 649, "(1)" + line 430, "pan.___", state 649, "(1)" + line 670, "pan.___", state 652, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 670, "pan.___", state 653, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 670, "pan.___", state 654, "(1)" + line 395, "pan.___", state 661, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 693, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 707, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 726, "(1)" + line 421, "pan.___", state 756, "(1)" + line 425, "pan.___", state 769, "(1)" + line 395, "pan.___", state 797, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 799, "(1)" + line 395, "pan.___", state 800, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 800, "else" + line 395, "pan.___", state 803, "(1)" + line 399, "pan.___", state 811, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 813, "(1)" + line 399, "pan.___", state 814, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 814, "else" + line 399, "pan.___", state 817, "(1)" + line 399, "pan.___", state 818, "(1)" + line 399, "pan.___", state 818, "(1)" + line 397, "pan.___", state 823, "((i<1))" + line 397, "pan.___", state 823, "((i>=1))" + line 404, "pan.___", state 829, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 831, "(1)" + line 404, "pan.___", state 832, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 832, "else" + line 404, "pan.___", state 835, "(1)" + line 404, "pan.___", state 836, "(1)" + line 404, "pan.___", state 836, "(1)" + line 408, "pan.___", state 843, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 845, "(1)" + line 408, "pan.___", state 846, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 846, "else" + line 408, "pan.___", state 849, "(1)" + line 408, "pan.___", state 850, "(1)" + line 408, "pan.___", state 850, "(1)" + line 406, "pan.___", state 855, "((i<2))" + line 406, "pan.___", state 855, "((i>=2))" + line 412, "pan.___", state 862, "(1)" + line 412, "pan.___", state 863, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 863, "else" + line 412, "pan.___", state 866, "(1)" + line 412, "pan.___", state 867, "(1)" + line 412, "pan.___", state 867, "(1)" + line 416, "pan.___", state 875, "(1)" + line 416, "pan.___", state 876, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 876, "else" + line 416, "pan.___", state 879, "(1)" + line 416, "pan.___", state 880, "(1)" + line 416, "pan.___", state 880, "(1)" + line 414, "pan.___", state 885, "((i<1))" + line 414, "pan.___", state 885, "((i>=1))" + line 421, "pan.___", state 892, "(1)" + line 421, "pan.___", state 893, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 893, "else" + line 421, "pan.___", state 896, "(1)" + line 421, "pan.___", state 897, "(1)" + line 421, "pan.___", state 897, "(1)" + line 425, "pan.___", state 905, "(1)" + line 425, "pan.___", state 906, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 906, "else" + line 425, "pan.___", state 909, "(1)" + line 425, "pan.___", state 910, "(1)" + line 425, "pan.___", state 910, "(1)" + line 430, "pan.___", state 919, "(1)" + line 430, "pan.___", state 919, "(1)" + line 395, "pan.___", state 926, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 928, "(1)" + line 395, "pan.___", state 929, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 929, "else" + line 395, "pan.___", state 932, "(1)" + line 399, "pan.___", state 940, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 942, "(1)" + line 399, "pan.___", state 943, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 943, "else" + line 399, "pan.___", state 946, "(1)" + line 399, "pan.___", state 947, "(1)" + line 399, "pan.___", state 947, "(1)" + line 397, "pan.___", state 952, "((i<1))" + line 397, "pan.___", state 952, "((i>=1))" + line 404, "pan.___", state 958, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 960, "(1)" + line 404, "pan.___", state 961, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 961, "else" + line 404, "pan.___", state 964, "(1)" + line 404, "pan.___", state 965, "(1)" + line 404, "pan.___", state 965, "(1)" + line 408, "pan.___", state 972, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 974, "(1)" + line 408, "pan.___", state 975, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 975, "else" + line 408, "pan.___", state 978, "(1)" + line 408, "pan.___", state 979, "(1)" + line 408, "pan.___", state 979, "(1)" + line 406, "pan.___", state 984, "((i<2))" + line 406, "pan.___", state 984, "((i>=2))" + line 412, "pan.___", state 991, "(1)" + line 412, "pan.___", state 992, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 992, "else" + line 412, "pan.___", state 995, "(1)" + line 412, "pan.___", state 996, "(1)" + line 412, "pan.___", state 996, "(1)" + line 416, "pan.___", state 1004, "(1)" + line 416, "pan.___", state 1005, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 1005, "else" + line 416, "pan.___", state 1008, "(1)" + line 416, "pan.___", state 1009, "(1)" + line 416, "pan.___", state 1009, "(1)" + line 414, "pan.___", state 1014, "((i<1))" + line 414, "pan.___", state 1014, "((i>=1))" + line 421, "pan.___", state 1021, "(1)" + line 421, "pan.___", state 1022, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 1022, "else" + line 421, "pan.___", state 1025, "(1)" + line 421, "pan.___", state 1026, "(1)" + line 421, "pan.___", state 1026, "(1)" + line 425, "pan.___", state 1034, "(1)" + line 425, "pan.___", state 1035, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 1035, "else" + line 425, "pan.___", state 1038, "(1)" + line 425, "pan.___", state 1039, "(1)" + line 425, "pan.___", state 1039, "(1)" + line 423, "pan.___", state 1044, "((i<2))" + line 423, "pan.___", state 1044, "((i>=2))" + line 430, "pan.___", state 1048, "(1)" + line 430, "pan.___", state 1048, "(1)" + line 678, "pan.___", state 1052, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 395, "pan.___", state 1057, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1089, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1103, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1122, "(1)" + line 421, "pan.___", state 1152, "(1)" + line 425, "pan.___", state 1165, "(1)" + line 395, "pan.___", state 1189, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1221, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1235, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1254, "(1)" + line 421, "pan.___", state 1284, "(1)" + line 425, "pan.___", state 1297, "(1)" + line 395, "pan.___", state 1322, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1354, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1368, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1387, "(1)" + line 421, "pan.___", state 1417, "(1)" + line 425, "pan.___", state 1430, "(1)" + line 395, "pan.___", state 1451, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1483, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1497, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1516, "(1)" + line 421, "pan.___", state 1546, "(1)" + line 425, "pan.___", state 1559, "(1)" + line 395, "pan.___", state 1585, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1617, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1631, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1650, "(1)" + line 421, "pan.___", state 1680, "(1)" + line 425, "pan.___", state 1693, "(1)" + line 395, "pan.___", state 1714, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1746, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1760, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1779, "(1)" + line 421, "pan.___", state 1809, "(1)" + line 425, "pan.___", state 1822, "(1)" + line 395, "pan.___", state 1846, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1878, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1892, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1911, "(1)" + line 421, "pan.___", state 1941, "(1)" + line 425, "pan.___", state 1954, "(1)" + line 717, "pan.___", state 1975, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 395, "pan.___", state 1982, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2014, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2028, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2047, "(1)" + line 421, "pan.___", state 2077, "(1)" + line 425, "pan.___", state 2090, "(1)" + line 395, "pan.___", state 2111, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2143, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2157, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2176, "(1)" + line 421, "pan.___", state 2206, "(1)" + line 425, "pan.___", state 2219, "(1)" + line 395, "pan.___", state 2242, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 2244, "(1)" + line 395, "pan.___", state 2245, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 2245, "else" + line 395, "pan.___", state 2248, "(1)" + line 399, "pan.___", state 2256, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2258, "(1)" + line 399, "pan.___", state 2259, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 2259, "else" + line 399, "pan.___", state 2262, "(1)" + line 399, "pan.___", state 2263, "(1)" + line 399, "pan.___", state 2263, "(1)" + line 397, "pan.___", state 2268, "((i<1))" + line 397, "pan.___", state 2268, "((i>=1))" + line 404, "pan.___", state 2274, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2276, "(1)" + line 404, "pan.___", state 2277, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 2277, "else" + line 404, "pan.___", state 2280, "(1)" + line 404, "pan.___", state 2281, "(1)" + line 404, "pan.___", state 2281, "(1)" + line 408, "pan.___", state 2288, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2290, "(1)" + line 408, "pan.___", state 2291, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 2291, "else" + line 408, "pan.___", state 2294, "(1)" + line 408, "pan.___", state 2295, "(1)" + line 408, "pan.___", state 2295, "(1)" + line 406, "pan.___", state 2300, "((i<2))" + line 406, "pan.___", state 2300, "((i>=2))" + line 412, "pan.___", state 2307, "(1)" + line 412, "pan.___", state 2308, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 2308, "else" + line 412, "pan.___", state 2311, "(1)" + line 412, "pan.___", state 2312, "(1)" + line 412, "pan.___", state 2312, "(1)" + line 416, "pan.___", state 2320, "(1)" + line 416, "pan.___", state 2321, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 2321, "else" + line 416, "pan.___", state 2324, "(1)" + line 416, "pan.___", state 2325, "(1)" + line 416, "pan.___", state 2325, "(1)" + line 414, "pan.___", state 2330, "((i<1))" + line 414, "pan.___", state 2330, "((i>=1))" + line 421, "pan.___", state 2337, "(1)" + line 421, "pan.___", state 2338, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 2338, "else" + line 421, "pan.___", state 2341, "(1)" + line 421, "pan.___", state 2342, "(1)" + line 421, "pan.___", state 2342, "(1)" + line 425, "pan.___", state 2350, "(1)" + line 425, "pan.___", state 2351, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 2351, "else" + line 425, "pan.___", state 2354, "(1)" + line 425, "pan.___", state 2355, "(1)" + line 425, "pan.___", state 2355, "(1)" + line 423, "pan.___", state 2360, "((i<2))" + line 423, "pan.___", state 2360, "((i>=2))" + line 430, "pan.___", state 2364, "(1)" + line 430, "pan.___", state 2364, "(1)" + line 717, "pan.___", state 2367, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 717, "pan.___", state 2368, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 717, "pan.___", state 2369, "(1)" + line 395, "pan.___", state 2376, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2408, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2422, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2441, "(1)" + line 421, "pan.___", state 2471, "(1)" + line 425, "pan.___", state 2484, "(1)" + line 395, "pan.___", state 2511, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2543, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2557, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2576, "(1)" + line 421, "pan.___", state 2606, "(1)" + line 425, "pan.___", state 2619, "(1)" + line 395, "pan.___", state 2640, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2672, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2686, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2705, "(1)" + line 421, "pan.___", state 2735, "(1)" + line 425, "pan.___", state 2748, "(1)" + line 395, "pan.___", state 2781, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2813, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2827, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2846, "(1)" + line 421, "pan.___", state 2876, "(1)" + line 425, "pan.___", state 2889, "(1)" + line 395, "pan.___", state 2908, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2940, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2954, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2973, "(1)" + line 421, "pan.___", state 3003, "(1)" + line 425, "pan.___", state 3016, "(1)" + line 877, "pan.___", state 3037, "-end-" + (284 of 3037 states) +unreached in proctype urcu_writer + line 395, "pan.___", state 18, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 24, "(1)" + line 399, "pan.___", state 32, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 38, "(1)" + line 399, "pan.___", state 39, "(1)" + line 399, "pan.___", state 39, "(1)" + line 397, "pan.___", state 44, "((i<1))" + line 397, "pan.___", state 44, "((i>=1))" + line 404, "pan.___", state 50, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 56, "(1)" + line 404, "pan.___", state 57, "(1)" + line 404, "pan.___", state 57, "(1)" + line 408, "pan.___", state 70, "(1)" + line 408, "pan.___", state 71, "(1)" + line 408, "pan.___", state 71, "(1)" + line 406, "pan.___", state 76, "((i<2))" + line 406, "pan.___", state 76, "((i>=2))" + line 412, "pan.___", state 83, "(1)" + line 412, "pan.___", state 84, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 84, "else" + line 412, "pan.___", state 87, "(1)" + line 412, "pan.___", state 88, "(1)" + line 412, "pan.___", state 88, "(1)" + line 416, "pan.___", state 96, "(1)" + line 416, "pan.___", state 97, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 97, "else" + line 416, "pan.___", state 100, "(1)" + line 416, "pan.___", state 101, "(1)" + line 416, "pan.___", state 101, "(1)" + line 414, "pan.___", state 106, "((i<1))" + line 414, "pan.___", state 106, "((i>=1))" + line 421, "pan.___", state 113, "(1)" + line 421, "pan.___", state 114, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 114, "else" + line 421, "pan.___", state 117, "(1)" + line 421, "pan.___", state 118, "(1)" + line 421, "pan.___", state 118, "(1)" + line 425, "pan.___", state 126, "(1)" + line 425, "pan.___", state 127, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 127, "else" + line 425, "pan.___", state 130, "(1)" + line 425, "pan.___", state 131, "(1)" + line 425, "pan.___", state 131, "(1)" + line 423, "pan.___", state 136, "((i<2))" + line 423, "pan.___", state 136, "((i>=2))" + line 430, "pan.___", state 140, "(1)" + line 430, "pan.___", state 140, "(1)" + line 250, "pan.___", state 149, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 158, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 171, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 211, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 225, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 243, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 257, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 276, "(1)" + line 416, "pan.___", state 289, "(1)" + line 421, "pan.___", state 306, "(1)" + line 425, "pan.___", state 319, "(1)" + line 399, "pan.___", state 356, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 374, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 388, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 420, "(1)" + line 421, "pan.___", state 437, "(1)" + line 425, "pan.___", state 450, "(1)" + line 399, "pan.___", state 494, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 512, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 526, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 558, "(1)" + line 421, "pan.___", state 575, "(1)" + line 425, "pan.___", state 588, "(1)" + line 399, "pan.___", state 623, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 641, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 655, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 687, "(1)" + line 421, "pan.___", state 704, "(1)" + line 425, "pan.___", state 717, "(1)" + line 399, "pan.___", state 754, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 772, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 786, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 818, "(1)" + line 421, "pan.___", state 835, "(1)" + line 425, "pan.___", state 848, "(1)" + line 250, "pan.___", state 903, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 912, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 927, "(1)" + line 262, "pan.___", state 934, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 950, "(1)" + line 231, "pan.___", state 958, "(1)" + line 235, "pan.___", state 970, "(1)" + line 239, "pan.___", state 978, "(1)" + line 250, "pan.___", state 1009, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1018, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1031, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1040, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1056, "(1)" + line 231, "pan.___", state 1064, "(1)" + line 235, "pan.___", state 1076, "(1)" + line 239, "pan.___", state 1084, "(1)" + line 254, "pan.___", state 1110, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1123, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1132, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1148, "(1)" + line 231, "pan.___", state 1156, "(1)" + line 235, "pan.___", state 1168, "(1)" + line 239, "pan.___", state 1176, "(1)" + line 250, "pan.___", state 1207, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1216, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1229, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1238, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1254, "(1)" + line 231, "pan.___", state 1262, "(1)" + line 235, "pan.___", state 1274, "(1)" + line 239, "pan.___", state 1282, "(1)" + line 254, "pan.___", state 1308, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1321, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1330, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1346, "(1)" + line 231, "pan.___", state 1354, "(1)" + line 235, "pan.___", state 1366, "(1)" + line 239, "pan.___", state 1374, "(1)" + line 250, "pan.___", state 1405, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1414, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1427, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1436, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1452, "(1)" + line 231, "pan.___", state 1460, "(1)" + line 235, "pan.___", state 1472, "(1)" + line 239, "pan.___", state 1480, "(1)" + line 254, "pan.___", state 1506, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1519, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1528, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1544, "(1)" + line 231, "pan.___", state 1552, "(1)" + line 235, "pan.___", state 1564, "(1)" + line 239, "pan.___", state 1572, "(1)" + line 250, "pan.___", state 1603, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1612, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1625, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1634, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1650, "(1)" + line 231, "pan.___", state 1658, "(1)" + line 235, "pan.___", state 1670, "(1)" + line 239, "pan.___", state 1678, "(1)" + line 1204, "pan.___", state 1694, "-end-" + (128 of 1694 states) +unreached in proctype :init: + line 1215, "pan.___", state 9, "((j<2))" + line 1215, "pan.___", state 9, "((j>=2))" + line 1216, "pan.___", state 20, "((j<2))" + line 1216, "pan.___", state 20, "((j>=2))" + line 1221, "pan.___", state 33, "((j<2))" + line 1221, "pan.___", state 33, "((j>=2))" + line 1219, "pan.___", state 43, "((i<1))" + line 1219, "pan.___", state 43, "((i>=1))" + line 1229, "pan.___", state 54, "((j<2))" + line 1229, "pan.___", state 54, "((j>=2))" + line 1233, "pan.___", state 67, "((j<2))" + line 1233, "pan.___", state 67, "((j>=2))" + (6 of 78 states) +unreached in proctype :never: + line 1263, "pan.___", state 8, "-end-" + (1 of 8 states) + +pan: elapsed time 638 seconds +pan: rate 3551.057 states/second +pan: avg transition delay 1.2606e-06 usec +cp .input.spin urcu_free_no_rmb.spin.input +cp .input.spin.trail urcu_free_no_rmb.spin.input.trail diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_rmb.spin.input b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_rmb.spin.input new file mode 100644 index 0000000..f653370 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_rmb.spin.input @@ -0,0 +1,1240 @@ +#define NO_RMB + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_rmb.spin.input.trail b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_rmb.spin.input.trail new file mode 100644 index 0000000..ad65225 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_rmb.spin.input.trail @@ -0,0 +1,1627 @@ +-2:3:-2 +-4:-4:-4 +1:0:4811 +2:3:4731 +3:3:4734 +4:3:4734 +5:3:4737 +6:3:4745 +7:3:4745 +8:3:4748 +9:3:4754 +10:3:4758 +11:3:4758 +12:3:4761 +13:3:4771 +14:3:4779 +15:3:4779 +16:3:4782 +17:3:4788 +18:3:4792 +19:3:4792 +20:3:4795 +21:3:4801 +22:3:4805 +23:3:4806 +24:0:4811 +25:3:4808 +26:0:4811 +27:2:3039 +28:0:4811 +29:2:3045 +30:0:4811 +31:2:3046 +32:0:4811 +33:2:3048 +34:0:4811 +35:2:3049 +36:0:4811 +37:2:3050 +38:2:3051 +39:2:3055 +40:2:3056 +41:2:3064 +42:2:3065 +43:2:3069 +44:2:3070 +45:2:3078 +46:2:3083 +47:2:3087 +48:2:3088 +49:2:3096 +50:2:3097 +51:2:3101 +52:2:3102 +53:2:3096 +54:2:3097 +55:2:3101 +56:2:3102 +57:2:3110 +58:2:3115 +59:2:3116 +60:2:3127 +61:2:3128 +62:2:3129 +63:2:3140 +64:2:3145 +65:2:3146 +66:2:3157 +67:2:3158 +68:2:3159 +69:2:3157 +70:2:3158 +71:2:3159 +72:2:3170 +73:2:3178 +74:0:4811 +75:2:3049 +76:0:4811 +77:2:3182 +78:2:3186 +79:2:3187 +80:2:3191 +81:2:3195 +82:2:3196 +83:2:3200 +84:2:3208 +85:2:3209 +86:2:3213 +87:2:3217 +88:2:3218 +89:2:3213 +90:2:3214 +91:2:3222 +92:0:4811 +93:2:3049 +94:0:4811 +95:2:3230 +96:2:3231 +97:2:3232 +98:0:4811 +99:2:3049 +100:0:4811 +101:2:3237 +102:0:4811 +103:2:3940 +104:2:3941 +105:2:3945 +106:2:3949 +107:2:3950 +108:2:3954 +109:2:3959 +110:2:3967 +111:2:3971 +112:2:3972 +113:2:3967 +114:2:3971 +115:2:3972 +116:2:3976 +117:2:3983 +118:2:3990 +119:2:3991 +120:2:3998 +121:2:4003 +122:2:4010 +123:2:4011 +124:2:4010 +125:2:4011 +126:2:4018 +127:2:4022 +128:0:4811 +129:2:4027 +130:0:4811 +131:2:4028 +132:0:4811 +133:2:4029 +134:0:4811 +135:2:4030 +136:0:4811 +137:1:2 +138:0:4811 +139:2:4031 +140:0:4811 +141:1:8 +142:0:4811 +143:1:9 +144:0:4811 +145:2:4030 +146:0:4811 +147:1:10 +148:0:4811 +149:2:4031 +150:0:4811 +151:1:11 +152:0:4811 +153:2:4030 +154:0:4811 +155:1:12 +156:0:4811 +157:2:4031 +158:0:4811 +159:1:13 +160:0:4811 +161:2:4030 +162:0:4811 +163:1:14 +164:0:4811 +165:2:4031 +166:0:4811 +167:1:15 +168:0:4811 +169:1:16 +170:0:4811 +171:2:4030 +172:0:4811 +173:1:17 +174:0:4811 +175:2:4031 +176:0:4811 +177:1:26 +178:0:4811 +179:2:4030 +180:0:4811 +181:1:30 +182:1:31 +183:1:35 +184:1:39 +185:1:40 +186:1:44 +187:1:52 +188:1:53 +189:1:57 +190:1:61 +191:1:62 +192:1:57 +193:1:61 +194:1:62 +195:1:66 +196:1:73 +197:1:80 +198:1:81 +199:1:88 +200:1:93 +201:1:100 +202:1:101 +203:1:100 +204:1:101 +205:1:108 +206:1:112 +207:0:4811 +208:2:4031 +209:0:4811 +210:1:117 +211:0:4811 +212:2:4032 +213:0:4811 +214:2:4037 +215:0:4811 +216:2:4038 +217:0:4811 +218:2:4046 +219:2:4047 +220:2:4051 +221:2:4055 +222:2:4056 +223:2:4060 +224:2:4068 +225:2:4069 +226:2:4073 +227:2:4077 +228:2:4078 +229:2:4073 +230:2:4077 +231:2:4078 +232:2:4082 +233:2:4089 +234:2:4096 +235:2:4097 +236:2:4104 +237:2:4109 +238:2:4116 +239:2:4117 +240:2:4116 +241:2:4117 +242:2:4124 +243:2:4128 +244:0:4811 +245:2:3239 +246:2:3921 +247:0:4811 +248:2:3049 +249:0:4811 +250:2:3240 +251:0:4811 +252:2:3049 +253:0:4811 +254:2:3243 +255:2:3244 +256:2:3248 +257:2:3249 +258:2:3257 +259:2:3258 +260:2:3262 +261:2:3263 +262:2:3271 +263:2:3276 +264:2:3280 +265:2:3281 +266:2:3289 +267:2:3290 +268:2:3294 +269:2:3295 +270:2:3289 +271:2:3290 +272:2:3294 +273:2:3295 +274:2:3303 +275:2:3308 +276:2:3309 +277:2:3320 +278:2:3321 +279:2:3322 +280:2:3333 +281:2:3338 +282:2:3339 +283:2:3350 +284:2:3351 +285:2:3352 +286:2:3350 +287:2:3351 +288:2:3352 +289:2:3363 +290:2:3370 +291:0:4811 +292:2:3049 +293:0:4811 +294:2:3374 +295:2:3375 +296:2:3376 +297:2:3388 +298:2:3389 +299:2:3393 +300:2:3394 +301:2:3402 +302:2:3407 +303:2:3411 +304:2:3412 +305:2:3420 +306:2:3421 +307:2:3425 +308:2:3426 +309:2:3420 +310:2:3421 +311:2:3425 +312:2:3426 +313:2:3434 +314:2:3439 +315:2:3440 +316:2:3451 +317:2:3452 +318:2:3453 +319:2:3464 +320:2:3469 +321:2:3470 +322:2:3481 +323:2:3482 +324:2:3483 +325:2:3481 +326:2:3482 +327:2:3483 +328:2:3494 +329:2:3505 +330:2:3506 +331:0:4811 +332:2:3049 +333:0:4811 +334:2:3512 +335:2:3513 +336:2:3517 +337:2:3518 +338:2:3526 +339:2:3527 +340:2:3531 +341:2:3532 +342:2:3540 +343:2:3545 +344:2:3549 +345:2:3550 +346:2:3558 +347:2:3559 +348:2:3563 +349:2:3564 +350:2:3558 +351:2:3559 +352:2:3563 +353:2:3564 +354:2:3572 +355:2:3577 +356:2:3578 +357:2:3589 +358:2:3590 +359:2:3591 +360:2:3602 +361:2:3607 +362:2:3608 +363:2:3619 +364:2:3620 +365:2:3621 +366:2:3619 +367:2:3620 +368:2:3621 +369:2:3632 +370:0:4811 +371:2:3049 +372:0:4811 +373:2:3641 +374:2:3642 +375:2:3646 +376:2:3647 +377:2:3655 +378:2:3656 +379:2:3660 +380:2:3661 +381:2:3669 +382:2:3674 +383:2:3678 +384:2:3679 +385:2:3687 +386:2:3688 +387:2:3692 +388:2:3693 +389:2:3687 +390:2:3688 +391:2:3692 +392:2:3693 +393:2:3701 +394:2:3706 +395:2:3707 +396:2:3718 +397:2:3719 +398:2:3720 +399:2:3731 +400:2:3736 +401:2:3737 +402:2:3748 +403:2:3749 +404:2:3750 +405:2:3748 +406:2:3749 +407:2:3750 +408:2:3761 +409:2:3768 +410:0:4811 +411:2:3049 +412:0:4811 +413:2:3772 +414:2:3773 +415:2:3774 +416:2:3786 +417:2:3787 +418:2:3791 +419:2:3792 +420:2:3800 +421:2:3805 +422:2:3809 +423:2:3810 +424:2:3818 +425:2:3819 +426:2:3823 +427:2:3824 +428:2:3818 +429:2:3819 +430:2:3823 +431:2:3824 +432:2:3832 +433:2:3837 +434:2:3838 +435:2:3849 +436:2:3850 +437:2:3851 +438:2:3862 +439:2:3867 +440:2:3868 +441:2:3879 +442:2:3880 +443:2:3881 +444:2:3879 +445:2:3880 +446:2:3881 +447:2:3892 +448:2:3902 +449:2:3903 +450:0:4811 +451:2:3049 +452:0:4811 +453:2:3909 +454:0:4811 +455:2:4534 +456:2:4535 +457:2:4539 +458:2:4543 +459:2:4544 +460:2:4548 +461:2:4556 +462:2:4557 +463:2:4561 +464:2:4565 +465:2:4566 +466:2:4561 +467:2:4565 +468:2:4566 +469:2:4570 +470:2:4577 +471:2:4584 +472:2:4585 +473:2:4592 +474:2:4597 +475:2:4604 +476:2:4605 +477:2:4604 +478:2:4605 +479:2:4612 +480:2:4616 +481:0:4811 +482:2:4621 +483:0:4811 +484:2:4622 +485:0:4811 +486:2:4623 +487:0:4811 +488:2:4624 +489:0:4811 +490:1:26 +491:0:4811 +492:2:4625 +493:0:4811 +494:1:30 +495:1:31 +496:1:35 +497:1:39 +498:1:40 +499:1:44 +500:1:52 +501:1:53 +502:1:57 +503:1:61 +504:1:62 +505:1:57 +506:1:61 +507:1:62 +508:1:66 +509:1:73 +510:1:80 +511:1:81 +512:1:88 +513:1:93 +514:1:100 +515:1:101 +516:1:100 +517:1:101 +518:1:108 +519:1:112 +520:0:4811 +521:2:4624 +522:0:4811 +523:1:117 +524:0:4811 +525:2:4625 +526:0:4811 +527:2:4626 +528:0:4811 +529:2:4631 +530:0:4811 +531:2:4632 +532:0:4811 +533:2:4640 +534:2:4641 +535:2:4645 +536:2:4649 +537:2:4650 +538:2:4654 +539:2:4662 +540:2:4663 +541:2:4667 +542:2:4671 +543:2:4672 +544:2:4667 +545:2:4671 +546:2:4672 +547:2:4676 +548:2:4683 +549:2:4690 +550:2:4691 +551:2:4698 +552:2:4703 +553:2:4710 +554:2:4711 +555:2:4710 +556:2:4711 +557:2:4718 +558:2:4722 +559:0:4811 +560:2:3911 +561:2:3921 +562:0:4811 +563:2:3049 +564:0:4811 +565:2:3912 +566:2:3913 +567:0:4811 +568:2:3049 +569:0:4811 +570:2:3917 +571:0:4811 +572:2:3925 +573:0:4811 +574:2:3046 +575:0:4811 +576:2:3048 +577:0:4811 +578:2:3049 +579:0:4811 +580:2:3050 +581:2:3051 +582:2:3055 +583:2:3056 +584:2:3064 +585:2:3065 +586:2:3069 +587:2:3070 +588:2:3078 +589:2:3083 +590:2:3087 +591:2:3088 +592:2:3096 +593:2:3097 +594:2:3098 +595:2:3096 +596:2:3097 +597:2:3101 +598:2:3102 +599:2:3110 +600:2:3115 +601:2:3116 +602:2:3127 +603:2:3128 +604:2:3129 +605:2:3140 +606:2:3145 +607:2:3146 +608:2:3157 +609:2:3158 +610:2:3159 +611:2:3157 +612:2:3158 +613:2:3159 +614:2:3170 +615:2:3178 +616:0:4811 +617:2:3049 +618:0:4811 +619:2:3182 +620:2:3186 +621:2:3187 +622:2:3191 +623:2:3195 +624:2:3196 +625:2:3200 +626:2:3208 +627:2:3209 +628:2:3213 +629:2:3214 +630:2:3213 +631:2:3217 +632:2:3218 +633:2:3222 +634:0:4811 +635:2:3049 +636:0:4811 +637:2:3230 +638:2:3231 +639:2:3232 +640:0:4811 +641:2:3049 +642:0:4811 +643:2:3237 +644:0:4811 +645:2:3940 +646:2:3941 +647:2:3945 +648:2:3949 +649:2:3950 +650:2:3954 +651:2:3959 +652:2:3967 +653:2:3971 +654:2:3972 +655:2:3967 +656:2:3971 +657:2:3972 +658:2:3976 +659:2:3983 +660:2:3990 +661:2:3991 +662:2:3998 +663:2:4003 +664:2:4010 +665:2:4011 +666:2:4010 +667:2:4011 +668:2:4018 +669:2:4022 +670:0:4811 +671:2:4027 +672:0:4811 +673:2:4028 +674:0:4811 +675:2:4029 +676:0:4811 +677:2:4030 +678:0:4811 +679:1:26 +680:0:4811 +681:2:4031 +682:0:4811 +683:1:30 +684:1:31 +685:1:35 +686:1:39 +687:1:40 +688:1:44 +689:1:52 +690:1:53 +691:1:57 +692:1:61 +693:1:62 +694:1:57 +695:1:61 +696:1:62 +697:1:66 +698:1:73 +699:1:80 +700:1:81 +701:1:88 +702:1:93 +703:1:100 +704:1:101 +705:1:100 +706:1:101 +707:1:108 +708:1:112 +709:0:4811 +710:2:4030 +711:0:4811 +712:1:117 +713:0:4811 +714:2:4031 +715:0:4811 +716:2:4032 +717:0:4811 +718:2:4037 +719:0:4811 +720:2:4038 +721:0:4811 +722:2:4046 +723:2:4047 +724:2:4051 +725:2:4055 +726:2:4056 +727:2:4060 +728:2:4068 +729:2:4069 +730:2:4073 +731:2:4077 +732:2:4078 +733:2:4073 +734:2:4077 +735:2:4078 +736:2:4082 +737:2:4089 +738:2:4096 +739:2:4097 +740:2:4104 +741:2:4109 +742:2:4116 +743:2:4117 +744:2:4116 +745:2:4117 +746:2:4124 +747:2:4128 +748:0:4811 +749:2:3239 +750:2:3921 +751:0:4811 +752:2:3049 +753:0:4811 +754:2:3240 +755:0:4811 +756:2:3049 +757:0:4811 +758:2:3243 +759:2:3244 +760:2:3248 +761:2:3249 +762:2:3257 +763:2:3258 +764:2:3262 +765:2:3263 +766:2:3271 +767:2:3276 +768:2:3280 +769:2:3281 +770:2:3289 +771:2:3290 +772:2:3294 +773:2:3295 +774:2:3289 +775:2:3290 +776:2:3294 +777:2:3295 +778:2:3303 +779:2:3308 +780:2:3309 +781:2:3320 +782:2:3321 +783:2:3322 +784:2:3333 +785:2:3338 +786:2:3339 +787:2:3350 +788:2:3351 +789:2:3352 +790:2:3350 +791:2:3351 +792:2:3352 +793:2:3363 +794:2:3370 +795:0:4811 +796:2:3049 +797:0:4811 +798:2:3374 +799:2:3375 +800:2:3376 +801:2:3388 +802:2:3389 +803:2:3393 +804:2:3394 +805:2:3402 +806:2:3407 +807:2:3411 +808:2:3412 +809:2:3420 +810:2:3421 +811:2:3425 +812:2:3426 +813:2:3420 +814:2:3421 +815:2:3425 +816:2:3426 +817:2:3434 +818:2:3439 +819:2:3440 +820:2:3451 +821:2:3452 +822:2:3453 +823:2:3464 +824:2:3469 +825:2:3470 +826:2:3481 +827:2:3482 +828:2:3483 +829:2:3481 +830:2:3482 +831:2:3483 +832:2:3494 +833:2:3505 +834:2:3506 +835:0:4811 +836:2:3049 +837:0:4811 +838:2:3512 +839:2:3513 +840:2:3517 +841:2:3518 +842:2:3526 +843:2:3527 +844:2:3531 +845:2:3532 +846:2:3540 +847:2:3545 +848:2:3549 +849:2:3550 +850:2:3558 +851:2:3559 +852:2:3563 +853:2:3564 +854:2:3558 +855:2:3559 +856:2:3563 +857:2:3564 +858:2:3572 +859:2:3577 +860:2:3578 +861:2:3589 +862:2:3590 +863:2:3591 +864:2:3602 +865:2:3607 +866:2:3608 +867:2:3619 +868:2:3620 +869:2:3621 +870:2:3619 +871:2:3620 +872:2:3621 +873:2:3632 +874:0:4811 +875:2:3049 +876:0:4811 +877:2:3641 +878:2:3642 +879:2:3646 +880:2:3647 +881:2:3655 +882:2:3656 +883:2:3660 +884:2:3661 +885:2:3669 +886:2:3674 +887:2:3678 +888:2:3679 +889:2:3687 +890:2:3688 +891:2:3692 +892:2:3693 +893:2:3687 +894:2:3688 +895:2:3692 +896:2:3693 +897:2:3701 +898:2:3706 +899:2:3707 +900:2:3718 +901:2:3719 +902:2:3720 +903:2:3731 +904:2:3736 +905:2:3737 +906:2:3748 +907:2:3749 +908:2:3750 +909:2:3748 +910:2:3749 +911:2:3750 +912:2:3761 +913:2:3768 +914:0:4811 +915:2:3049 +916:0:4811 +917:2:3772 +918:2:3773 +919:2:3774 +920:2:3786 +921:2:3787 +922:2:3791 +923:2:3792 +924:2:3800 +925:2:3805 +926:2:3809 +927:2:3810 +928:2:3818 +929:2:3819 +930:2:3823 +931:2:3824 +932:2:3818 +933:2:3819 +934:2:3823 +935:2:3824 +936:2:3832 +937:2:3837 +938:2:3838 +939:2:3849 +940:2:3850 +941:2:3851 +942:2:3862 +943:2:3867 +944:2:3868 +945:2:3879 +946:2:3880 +947:2:3881 +948:2:3879 +949:2:3880 +950:2:3881 +951:2:3892 +952:2:3902 +953:2:3903 +954:0:4811 +955:2:3049 +956:0:4811 +957:2:3909 +958:0:4811 +959:2:4534 +960:2:4535 +961:2:4539 +962:2:4543 +963:2:4544 +964:2:4548 +965:2:4556 +966:2:4557 +967:2:4561 +968:2:4565 +969:2:4566 +970:2:4561 +971:2:4565 +972:2:4566 +973:2:4570 +974:2:4577 +975:2:4584 +976:2:4585 +977:2:4592 +978:2:4597 +979:2:4604 +980:2:4605 +981:2:4604 +982:2:4605 +983:2:4612 +984:2:4616 +985:0:4811 +986:2:4621 +987:0:4811 +988:2:4622 +989:0:4811 +990:2:4623 +991:0:4811 +992:2:4624 +993:0:4811 +994:1:26 +995:0:4811 +996:2:4625 +997:0:4811 +998:1:30 +999:1:31 +1000:1:35 +1001:1:39 +1002:1:40 +1003:1:44 +1004:1:52 +1005:1:53 +1006:1:57 +1007:1:61 +1008:1:62 +1009:1:57 +1010:1:61 +1011:1:62 +1012:1:66 +1013:1:73 +1014:1:80 +1015:1:81 +1016:1:88 +1017:1:93 +1018:1:100 +1019:1:101 +1020:1:100 +1021:1:101 +1022:1:108 +1023:1:112 +1024:0:4811 +1025:2:4624 +1026:0:4811 +1027:1:117 +1028:0:4811 +1029:2:4625 +1030:0:4811 +1031:2:4626 +1032:0:4811 +1033:2:4631 +1034:0:4811 +1035:2:4632 +1036:0:4811 +1037:2:4640 +1038:2:4641 +1039:2:4645 +1040:2:4649 +1041:2:4650 +1042:2:4654 +1043:2:4662 +1044:2:4663 +1045:2:4667 +1046:2:4671 +1047:2:4672 +1048:2:4667 +1049:2:4671 +1050:2:4672 +1051:2:4676 +1052:2:4683 +1053:2:4690 +1054:2:4691 +1055:2:4698 +1056:2:4703 +1057:2:4710 +1058:2:4711 +1059:2:4710 +1060:2:4711 +1061:2:4718 +1062:2:4722 +1063:0:4811 +1064:2:3911 +1065:2:3921 +1066:0:4811 +1067:2:3049 +1068:0:4811 +1069:2:3912 +1070:2:3913 +1071:0:4811 +1072:2:3049 +1073:0:4811 +1074:2:3917 +1075:0:4811 +1076:2:3925 +1077:0:4811 +1078:2:3046 +1079:0:4811 +1080:2:3048 +1081:0:4811 +1082:2:3049 +1083:0:4811 +1084:2:3050 +1085:2:3051 +1086:2:3055 +1087:2:3056 +1088:2:3064 +1089:2:3065 +1090:2:3069 +1091:2:3070 +1092:2:3078 +1093:2:3083 +1094:2:3087 +1095:2:3088 +1096:2:3096 +1097:2:3097 +1098:2:3101 +1099:2:3102 +1100:2:3096 +1101:2:3097 +1102:2:3098 +1103:2:3110 +1104:2:3115 +1105:2:3116 +1106:2:3127 +1107:2:3128 +1108:2:3129 +1109:2:3140 +1110:2:3145 +1111:2:3146 +1112:2:3157 +1113:2:3158 +1114:2:3159 +1115:2:3157 +1116:2:3158 +1117:2:3159 +1118:2:3170 +1119:2:3178 +1120:0:4811 +1121:2:3049 +1122:0:4811 +1123:1:118 +1124:0:4811 +1125:1:120 +1126:0:4811 +1127:1:19 +1128:0:4811 +1129:1:126 +1130:1:127 +1131:1:131 +1132:1:132 +1133:1:140 +1134:1:141 +1135:1:145 +1136:1:146 +1137:1:154 +1138:1:159 +1139:1:163 +1140:1:164 +1141:1:172 +1142:1:173 +1143:1:177 +1144:1:178 +1145:1:172 +1146:1:173 +1147:1:177 +1148:1:178 +1149:1:186 +1150:1:191 +1151:1:192 +1152:1:203 +1153:1:204 +1154:1:205 +1155:1:216 +1156:1:221 +1157:1:222 +1158:1:233 +1159:1:234 +1160:1:235 +1161:1:233 +1162:1:234 +1163:1:235 +1164:1:246 +1165:0:4811 +1166:1:15 +1167:0:4811 +1168:1:16 +1169:0:4811 +1170:2:3182 +1171:2:3186 +1172:2:3187 +1173:2:3191 +1174:2:3195 +1175:2:3196 +1176:2:3200 +1177:2:3208 +1178:2:3209 +1179:2:3213 +1180:2:3217 +1181:2:3218 +1182:2:3213 +1183:2:3214 +1184:2:3222 +1185:0:4811 +1186:2:3049 +1187:0:4811 +1188:2:3230 +1189:2:3231 +1190:2:3232 +1191:0:4811 +1192:2:3049 +1193:0:4811 +1194:2:3237 +1195:0:4811 +1196:2:3940 +1197:2:3941 +1198:2:3945 +1199:2:3949 +1200:2:3950 +1201:2:3954 +1202:2:3959 +1203:2:3967 +1204:2:3971 +1205:2:3972 +1206:2:3967 +1207:2:3971 +1208:2:3972 +1209:2:3976 +1210:2:3983 +1211:2:3990 +1212:2:3991 +1213:2:3998 +1214:2:4003 +1215:2:4010 +1216:2:4011 +1217:2:4010 +1218:2:4011 +1219:2:4018 +1220:2:4022 +1221:0:4811 +1222:2:4027 +1223:0:4811 +1224:2:4028 +1225:0:4811 +1226:2:4029 +1227:0:4811 +1228:2:4030 +1229:0:4811 +1230:1:17 +1231:0:4811 +1232:2:4031 +1233:0:4811 +1234:1:118 +1235:0:4811 +1236:1:120 +1237:0:4811 +1238:2:4030 +1239:0:4811 +1240:1:19 +1241:0:4811 +1242:2:4031 +1243:0:4811 +1244:1:255 +1245:1:256 +1246:0:4811 +1247:1:15 +1248:0:4811 +1249:1:16 +1250:0:4811 +1251:2:4030 +1252:0:4811 +1253:1:17 +1254:0:4811 +1255:2:4031 +1256:0:4811 +1257:1:118 +1258:0:4811 +1259:1:120 +1260:0:4811 +1261:2:4030 +1262:0:4811 +1263:1:19 +1264:0:4811 +1265:2:4031 +1266:0:4811 +1267:1:262 +1268:1:263 +1269:1:267 +1270:1:268 +1271:1:276 +1272:1:277 +1273:1:281 +1274:1:282 +1275:1:290 +1276:1:295 +1277:1:299 +1278:1:300 +1279:1:308 +1280:1:309 +1281:1:313 +1282:1:314 +1283:1:308 +1284:1:309 +1285:1:313 +1286:1:314 +1287:1:322 +1288:1:327 +1289:1:328 +1290:1:339 +1291:1:340 +1292:1:341 +1293:1:352 +1294:1:357 +1295:1:358 +1296:1:369 +1297:1:370 +1298:1:371 +1299:1:369 +1300:1:377 +1301:1:378 +1302:1:382 +1303:0:4811 +1304:1:15 +1305:0:4811 +1306:1:16 +1307:0:4811 +1308:2:4030 +1309:0:4811 +1310:1:17 +1311:0:4811 +1312:2:4031 +1313:0:4811 +1314:1:118 +1315:0:4811 +1316:1:120 +1317:0:4811 +1318:2:4030 +1319:0:4811 +1320:1:19 +1321:0:4811 +1322:2:4031 +1323:0:4811 +1324:1:391 +1325:1:392 +1326:1:396 +1327:1:397 +1328:1:405 +1329:1:406 +1330:1:410 +1331:1:411 +1332:1:419 +1333:1:424 +1334:1:428 +1335:1:429 +1336:1:437 +1337:1:438 +1338:1:442 +1339:1:443 +1340:1:437 +1341:1:438 +1342:1:442 +1343:1:443 +1344:1:451 +1345:1:456 +1346:1:457 +1347:1:468 +1348:1:469 +1349:1:470 +1350:1:481 +1351:1:486 +1352:1:487 +1353:1:498 +1354:1:499 +1355:1:500 +1356:1:498 +1357:1:506 +1358:1:507 +1359:1:511 +1360:1:518 +1361:0:4811 +1362:1:15 +1363:0:4811 +1364:1:16 +1365:0:4811 +1366:2:4030 +1367:0:4811 +1368:1:17 +1369:0:4811 +1370:2:4031 +1371:0:4811 +1372:1:118 +1373:0:4811 +1374:1:120 +1375:0:4811 +1376:2:4030 +1377:0:4811 +1378:1:19 +1379:0:4811 +1380:2:4031 +1381:0:4811 +1382:1:656 +1383:1:657 +1384:1:661 +1385:1:662 +1386:1:670 +1387:1:671 +1388:1:672 +1389:1:684 +1390:1:689 +1391:1:693 +1392:1:694 +1393:1:702 +1394:1:703 +1395:1:707 +1396:1:708 +1397:1:702 +1398:1:703 +1399:1:707 +1400:1:708 +1401:1:716 +1402:1:721 +1403:1:722 +1404:1:733 +1405:1:734 +1406:1:735 +1407:1:746 +1408:1:751 +1409:1:752 +1410:1:763 +1411:1:764 +1412:1:765 +1413:1:763 +1414:1:771 +1415:1:772 +1416:1:776 +1417:0:4811 +1418:1:15 +1419:0:4811 +1420:1:16 +1421:0:4811 +1422:2:4030 +1423:0:4811 +1424:1:17 +1425:0:4811 +1426:2:4031 +1427:0:4811 +1428:1:118 +1429:0:4811 +1430:1:120 +1431:0:4811 +1432:2:4030 +1433:0:4811 +1434:1:19 +1435:0:4811 +1436:2:4031 +1437:0:4811 +1438:1:785 +1439:1:788 +1440:1:789 +1441:0:4811 +1442:1:15 +1443:0:4811 +1444:1:16 +1445:0:4811 +1446:2:4030 +1447:0:4811 +1448:1:17 +1449:0:4811 +1450:2:4031 +1451:0:4811 +1452:1:118 +1453:0:4811 +1454:1:120 +1455:0:4811 +1456:2:4030 +1457:0:4811 +1458:1:19 +1459:0:4811 +1460:2:4031 +1461:0:4811 +1462:1:1052 +1463:1:1053 +1464:1:1057 +1465:1:1058 +1466:1:1066 +1467:1:1067 +1468:1:1071 +1469:1:1072 +1470:1:1080 +1471:1:1085 +1472:1:1089 +1473:1:1090 +1474:1:1098 +1475:1:1099 +1476:1:1103 +1477:1:1104 +1478:1:1098 +1479:1:1099 +1480:1:1103 +1481:1:1104 +1482:1:1112 +1483:1:1117 +1484:1:1118 +1485:1:1129 +1486:1:1130 +1487:1:1131 +1488:1:1142 +1489:1:1147 +1490:1:1148 +1491:1:1159 +1492:1:1160 +1493:1:1161 +1494:1:1159 +1495:1:1167 +1496:1:1168 +1497:1:1172 +1498:1:1179 +1499:1:1183 +1500:0:4811 +1501:1:15 +1502:0:4811 +1503:1:16 +1504:0:4811 +1505:2:4030 +1506:0:4811 +1507:1:17 +1508:0:4811 +1509:2:4031 +1510:0:4811 +1511:1:118 +1512:0:4811 +1513:1:120 +1514:0:4811 +1515:2:4030 +1516:0:4811 +1517:1:19 +1518:0:4811 +1519:2:4031 +1520:0:4811 +1521:1:1184 +1522:1:1185 +1523:1:1189 +1524:1:1190 +1525:1:1198 +1526:1:1199 +1527:1:1200 +1528:1:1212 +1529:1:1217 +1530:1:1221 +1531:1:1222 +1532:1:1230 +1533:1:1231 +1534:1:1235 +1535:1:1236 +1536:1:1230 +1537:1:1231 +1538:1:1235 +1539:1:1236 +1540:1:1244 +1541:1:1249 +1542:1:1250 +1543:1:1261 +1544:1:1262 +1545:1:1263 +1546:1:1274 +1547:1:1279 +1548:1:1280 +1549:1:1291 +1550:1:1292 +1551:1:1293 +1552:1:1291 +1553:1:1299 +1554:1:1300 +1555:1:1304 +1556:0:4811 +1557:1:15 +1558:0:4811 +1559:1:16 +1560:0:4811 +1561:2:4030 +1562:0:4811 +1563:1:17 +1564:0:4811 +1565:2:4031 +1566:0:4811 +1567:1:118 +1568:0:4811 +1569:1:120 +1570:0:4811 +1571:2:4030 +1572:0:4811 +1573:1:19 +1574:0:4811 +1575:2:4031 +1576:0:4811 +1577:1:1313 +1578:0:4811 +1579:2:4030 +1580:0:4811 +1581:1:2777 +1582:1:2781 +1583:1:2782 +1584:1:2790 +1585:1:2791 +1586:1:2795 +1587:1:2796 +1588:1:2804 +1589:1:2809 +1590:1:2813 +1591:1:2814 +1592:1:2822 +1593:1:2823 +1594:1:2827 +1595:1:2828 +1596:1:2822 +1597:1:2823 +1598:1:2827 +1599:1:2828 +1600:1:2836 +1601:1:2841 +1602:1:2842 +1603:1:2853 +1604:1:2854 +1605:1:2855 +1606:1:2866 +1607:1:2871 +1608:1:2872 +1609:1:2883 +1610:1:2884 +1611:1:2885 +1612:1:2883 +1613:1:2891 +1614:1:2892 +1615:1:2896 +1616:1:2900 +1617:0:4811 +1618:2:4031 +1619:0:4811 +1620:1:1315 +1621:1:1316 +1622:0:4809 +1623:1:15 +1624:0:4815 +1625:1:120 diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_wmb.define b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_wmb.define new file mode 100644 index 0000000..710f29d --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_wmb.define @@ -0,0 +1 @@ +#define NO_WMB diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_wmb.log b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_wmb.log new file mode 100644 index 0000000..c8da68c --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_wmb.log @@ -0,0 +1,560 @@ +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define >> pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_free.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_free_no_wmb.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1258) +Depth= 7141 States= 1e+06 Transitions= 1.25e+08 Memory= 550.432 t= 155 R= 6e+03 +Depth= 7141 States= 2e+06 Transitions= 4.09e+08 Memory= 634.318 t= 526 R= 4e+03 +Depth= 7141 States= 3e+06 Transitions= 5.78e+08 Memory= 718.303 t= 751 R= 4e+03 +pan: resizing hashtable to -w22.. done +Depth= 7141 States= 4e+06 Transitions= 8.27e+08 Memory= 833.311 t= 1.07e+03 R= 4e+03 +Depth= 7141 States= 5e+06 Transitions= 1.08e+09 Memory= 917.295 t= 1.39e+03 R= 4e+03 +Depth= 7141 States= 6e+06 Transitions= 1.57e+09 Memory= 1001.279 t= 2.04e+03 R= 3e+03 +Depth= 7141 States= 7e+06 Transitions= 1.97e+09 Memory= 1085.264 t= 2.58e+03 R= 3e+03 +Depth= 7141 States= 8e+06 Transitions= 2.31e+09 Memory= 1169.151 t= 3.03e+03 R= 3e+03 +Depth= 7141 States= 9e+06 Transitions= 2.62e+09 Memory= 1253.135 t= 3.44e+03 R= 3e+03 +pan: resizing hashtable to -w24.. done +Depth= 7141 States= 1e+07 Transitions= 2.83e+09 Memory= 1461.115 t= 3.72e+03 R= 3e+03 +Depth= 7141 States= 1.1e+07 Transitions= 3.05e+09 Memory= 1545.100 t= 3.99e+03 R= 3e+03 +Depth= 7141 States= 1.2e+07 Transitions= 3.25e+09 Memory= 1629.084 t= 4.25e+03 R= 3e+03 +Depth= 7141 States= 1.3e+07 Transitions= 3.55e+09 Memory= 1713.068 t= 4.64e+03 R= 3e+03 +Depth= 7141 States= 1.4e+07 Transitions= 3.84e+09 Memory= 1797.053 t= 5.01e+03 R= 3e+03 +Depth= 7141 States= 1.5e+07 Transitions= 3.96e+09 Memory= 1881.037 t= 5.17e+03 R= 3e+03 +pan: claim violated! (at depth 1482) +pan: wrote .input.spin.trail + +(Spin Version 5.1.7 -- 23 December 2008) +Warning: Search not completed + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness disabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 7141, errors: 1 + 15755160 states, stored +4.1726493e+09 states, matched +4.1884045e+09 transitions (= stored+matched) +2.431858e+10 atomic steps +hash conflicts: 2.849112e+09 (resolved) + +Stats on memory usage (in Megabytes): + 1742.934 equivalent memory usage for states (stored*(State-vector + overhead)) + 1359.449 actual memory usage for states (compression: 78.00%) + state-vector as stored = 62 byte + 28 byte overhead + 128.000 memory used for hash table (-w24) + 457.764 memory used for DFS stack (-m10000000) + 1944.416 total actual memory usage + +unreached in proctype urcu_reader + line 250, "pan.___", state 30, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 52, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 61, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 77, "(1)" + line 231, "pan.___", state 85, "(1)" + line 235, "pan.___", state 97, "(1)" + line 239, "pan.___", state 105, "(1)" + line 395, "pan.___", state 131, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 163, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 177, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 196, "(1)" + line 421, "pan.___", state 226, "(1)" + line 425, "pan.___", state 239, "(1)" + line 670, "pan.___", state 260, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 395, "pan.___", state 267, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 299, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 313, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 332, "(1)" + line 421, "pan.___", state 362, "(1)" + line 425, "pan.___", state 375, "(1)" + line 395, "pan.___", state 396, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 428, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 442, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 461, "(1)" + line 421, "pan.___", state 491, "(1)" + line 425, "pan.___", state 504, "(1)" + line 395, "pan.___", state 527, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 529, "(1)" + line 395, "pan.___", state 530, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 530, "else" + line 395, "pan.___", state 533, "(1)" + line 399, "pan.___", state 541, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 543, "(1)" + line 399, "pan.___", state 544, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 544, "else" + line 399, "pan.___", state 547, "(1)" + line 399, "pan.___", state 548, "(1)" + line 399, "pan.___", state 548, "(1)" + line 397, "pan.___", state 553, "((i<1))" + line 397, "pan.___", state 553, "((i>=1))" + line 404, "pan.___", state 559, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 561, "(1)" + line 404, "pan.___", state 562, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 562, "else" + line 404, "pan.___", state 565, "(1)" + line 404, "pan.___", state 566, "(1)" + line 404, "pan.___", state 566, "(1)" + line 408, "pan.___", state 573, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 575, "(1)" + line 408, "pan.___", state 576, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 576, "else" + line 408, "pan.___", state 579, "(1)" + line 408, "pan.___", state 580, "(1)" + line 408, "pan.___", state 580, "(1)" + line 406, "pan.___", state 585, "((i<2))" + line 406, "pan.___", state 585, "((i>=2))" + line 412, "pan.___", state 592, "(1)" + line 412, "pan.___", state 593, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 593, "else" + line 412, "pan.___", state 596, "(1)" + line 412, "pan.___", state 597, "(1)" + line 412, "pan.___", state 597, "(1)" + line 416, "pan.___", state 605, "(1)" + line 416, "pan.___", state 606, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 606, "else" + line 416, "pan.___", state 609, "(1)" + line 416, "pan.___", state 610, "(1)" + line 416, "pan.___", state 610, "(1)" + line 414, "pan.___", state 615, "((i<1))" + line 414, "pan.___", state 615, "((i>=1))" + line 421, "pan.___", state 622, "(1)" + line 421, "pan.___", state 623, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 623, "else" + line 421, "pan.___", state 626, "(1)" + line 421, "pan.___", state 627, "(1)" + line 421, "pan.___", state 627, "(1)" + line 425, "pan.___", state 635, "(1)" + line 425, "pan.___", state 636, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 636, "else" + line 425, "pan.___", state 639, "(1)" + line 425, "pan.___", state 640, "(1)" + line 425, "pan.___", state 640, "(1)" + line 423, "pan.___", state 645, "((i<2))" + line 423, "pan.___", state 645, "((i>=2))" + line 430, "pan.___", state 649, "(1)" + line 430, "pan.___", state 649, "(1)" + line 670, "pan.___", state 652, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 670, "pan.___", state 653, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 670, "pan.___", state 654, "(1)" + line 395, "pan.___", state 661, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 693, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 707, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 726, "(1)" + line 421, "pan.___", state 756, "(1)" + line 425, "pan.___", state 769, "(1)" + line 395, "pan.___", state 797, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 799, "(1)" + line 395, "pan.___", state 800, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 800, "else" + line 395, "pan.___", state 803, "(1)" + line 399, "pan.___", state 811, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 813, "(1)" + line 399, "pan.___", state 814, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 814, "else" + line 399, "pan.___", state 817, "(1)" + line 399, "pan.___", state 818, "(1)" + line 399, "pan.___", state 818, "(1)" + line 397, "pan.___", state 823, "((i<1))" + line 397, "pan.___", state 823, "((i>=1))" + line 404, "pan.___", state 829, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 831, "(1)" + line 404, "pan.___", state 832, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 832, "else" + line 404, "pan.___", state 835, "(1)" + line 404, "pan.___", state 836, "(1)" + line 404, "pan.___", state 836, "(1)" + line 408, "pan.___", state 843, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 845, "(1)" + line 408, "pan.___", state 846, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 846, "else" + line 408, "pan.___", state 849, "(1)" + line 408, "pan.___", state 850, "(1)" + line 408, "pan.___", state 850, "(1)" + line 406, "pan.___", state 855, "((i<2))" + line 406, "pan.___", state 855, "((i>=2))" + line 412, "pan.___", state 862, "(1)" + line 412, "pan.___", state 863, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 863, "else" + line 412, "pan.___", state 866, "(1)" + line 412, "pan.___", state 867, "(1)" + line 412, "pan.___", state 867, "(1)" + line 416, "pan.___", state 875, "(1)" + line 416, "pan.___", state 876, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 876, "else" + line 416, "pan.___", state 879, "(1)" + line 416, "pan.___", state 880, "(1)" + line 416, "pan.___", state 880, "(1)" + line 414, "pan.___", state 885, "((i<1))" + line 414, "pan.___", state 885, "((i>=1))" + line 421, "pan.___", state 892, "(1)" + line 421, "pan.___", state 893, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 893, "else" + line 421, "pan.___", state 896, "(1)" + line 421, "pan.___", state 897, "(1)" + line 421, "pan.___", state 897, "(1)" + line 425, "pan.___", state 905, "(1)" + line 425, "pan.___", state 906, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 906, "else" + line 425, "pan.___", state 909, "(1)" + line 425, "pan.___", state 910, "(1)" + line 425, "pan.___", state 910, "(1)" + line 430, "pan.___", state 919, "(1)" + line 430, "pan.___", state 919, "(1)" + line 395, "pan.___", state 926, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 928, "(1)" + line 395, "pan.___", state 929, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 929, "else" + line 395, "pan.___", state 932, "(1)" + line 399, "pan.___", state 940, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 942, "(1)" + line 399, "pan.___", state 943, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 943, "else" + line 399, "pan.___", state 946, "(1)" + line 399, "pan.___", state 947, "(1)" + line 399, "pan.___", state 947, "(1)" + line 397, "pan.___", state 952, "((i<1))" + line 397, "pan.___", state 952, "((i>=1))" + line 404, "pan.___", state 958, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 960, "(1)" + line 404, "pan.___", state 961, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 961, "else" + line 404, "pan.___", state 964, "(1)" + line 404, "pan.___", state 965, "(1)" + line 404, "pan.___", state 965, "(1)" + line 408, "pan.___", state 972, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 974, "(1)" + line 408, "pan.___", state 975, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 975, "else" + line 408, "pan.___", state 978, "(1)" + line 408, "pan.___", state 979, "(1)" + line 408, "pan.___", state 979, "(1)" + line 406, "pan.___", state 984, "((i<2))" + line 406, "pan.___", state 984, "((i>=2))" + line 412, "pan.___", state 991, "(1)" + line 412, "pan.___", state 992, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 992, "else" + line 412, "pan.___", state 995, "(1)" + line 412, "pan.___", state 996, "(1)" + line 412, "pan.___", state 996, "(1)" + line 416, "pan.___", state 1004, "(1)" + line 416, "pan.___", state 1005, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 1005, "else" + line 416, "pan.___", state 1008, "(1)" + line 416, "pan.___", state 1009, "(1)" + line 416, "pan.___", state 1009, "(1)" + line 414, "pan.___", state 1014, "((i<1))" + line 414, "pan.___", state 1014, "((i>=1))" + line 421, "pan.___", state 1021, "(1)" + line 421, "pan.___", state 1022, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 1022, "else" + line 421, "pan.___", state 1025, "(1)" + line 421, "pan.___", state 1026, "(1)" + line 421, "pan.___", state 1026, "(1)" + line 425, "pan.___", state 1034, "(1)" + line 425, "pan.___", state 1035, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 1035, "else" + line 425, "pan.___", state 1038, "(1)" + line 425, "pan.___", state 1039, "(1)" + line 425, "pan.___", state 1039, "(1)" + line 423, "pan.___", state 1044, "((i<2))" + line 423, "pan.___", state 1044, "((i>=2))" + line 430, "pan.___", state 1048, "(1)" + line 430, "pan.___", state 1048, "(1)" + line 678, "pan.___", state 1052, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 395, "pan.___", state 1057, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1089, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1103, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1122, "(1)" + line 421, "pan.___", state 1152, "(1)" + line 425, "pan.___", state 1165, "(1)" + line 395, "pan.___", state 1189, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1221, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1235, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1254, "(1)" + line 421, "pan.___", state 1284, "(1)" + line 425, "pan.___", state 1297, "(1)" + line 395, "pan.___", state 1322, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1354, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1368, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1387, "(1)" + line 421, "pan.___", state 1417, "(1)" + line 425, "pan.___", state 1430, "(1)" + line 395, "pan.___", state 1451, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1483, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1497, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1516, "(1)" + line 421, "pan.___", state 1546, "(1)" + line 425, "pan.___", state 1559, "(1)" + line 395, "pan.___", state 1585, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1617, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1631, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1650, "(1)" + line 421, "pan.___", state 1680, "(1)" + line 425, "pan.___", state 1693, "(1)" + line 395, "pan.___", state 1714, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1746, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1760, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1779, "(1)" + line 421, "pan.___", state 1809, "(1)" + line 425, "pan.___", state 1822, "(1)" + line 395, "pan.___", state 1846, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1878, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1892, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1911, "(1)" + line 421, "pan.___", state 1941, "(1)" + line 425, "pan.___", state 1954, "(1)" + line 717, "pan.___", state 1975, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 395, "pan.___", state 1982, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2014, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2028, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2047, "(1)" + line 421, "pan.___", state 2077, "(1)" + line 425, "pan.___", state 2090, "(1)" + line 395, "pan.___", state 2111, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2143, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2157, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2176, "(1)" + line 421, "pan.___", state 2206, "(1)" + line 425, "pan.___", state 2219, "(1)" + line 395, "pan.___", state 2242, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 2244, "(1)" + line 395, "pan.___", state 2245, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 2245, "else" + line 395, "pan.___", state 2248, "(1)" + line 399, "pan.___", state 2256, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2258, "(1)" + line 399, "pan.___", state 2259, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 2259, "else" + line 399, "pan.___", state 2262, "(1)" + line 399, "pan.___", state 2263, "(1)" + line 399, "pan.___", state 2263, "(1)" + line 397, "pan.___", state 2268, "((i<1))" + line 397, "pan.___", state 2268, "((i>=1))" + line 404, "pan.___", state 2274, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2276, "(1)" + line 404, "pan.___", state 2277, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 2277, "else" + line 404, "pan.___", state 2280, "(1)" + line 404, "pan.___", state 2281, "(1)" + line 404, "pan.___", state 2281, "(1)" + line 408, "pan.___", state 2288, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2290, "(1)" + line 408, "pan.___", state 2291, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 2291, "else" + line 408, "pan.___", state 2294, "(1)" + line 408, "pan.___", state 2295, "(1)" + line 408, "pan.___", state 2295, "(1)" + line 406, "pan.___", state 2300, "((i<2))" + line 406, "pan.___", state 2300, "((i>=2))" + line 412, "pan.___", state 2307, "(1)" + line 412, "pan.___", state 2308, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 2308, "else" + line 412, "pan.___", state 2311, "(1)" + line 412, "pan.___", state 2312, "(1)" + line 412, "pan.___", state 2312, "(1)" + line 416, "pan.___", state 2320, "(1)" + line 416, "pan.___", state 2321, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 2321, "else" + line 416, "pan.___", state 2324, "(1)" + line 416, "pan.___", state 2325, "(1)" + line 416, "pan.___", state 2325, "(1)" + line 414, "pan.___", state 2330, "((i<1))" + line 414, "pan.___", state 2330, "((i>=1))" + line 421, "pan.___", state 2337, "(1)" + line 421, "pan.___", state 2338, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 2338, "else" + line 421, "pan.___", state 2341, "(1)" + line 421, "pan.___", state 2342, "(1)" + line 421, "pan.___", state 2342, "(1)" + line 425, "pan.___", state 2350, "(1)" + line 425, "pan.___", state 2351, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 2351, "else" + line 425, "pan.___", state 2354, "(1)" + line 425, "pan.___", state 2355, "(1)" + line 425, "pan.___", state 2355, "(1)" + line 423, "pan.___", state 2360, "((i<2))" + line 423, "pan.___", state 2360, "((i>=2))" + line 430, "pan.___", state 2364, "(1)" + line 430, "pan.___", state 2364, "(1)" + line 717, "pan.___", state 2367, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 717, "pan.___", state 2368, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 717, "pan.___", state 2369, "(1)" + line 395, "pan.___", state 2376, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2408, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2422, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2441, "(1)" + line 421, "pan.___", state 2471, "(1)" + line 425, "pan.___", state 2484, "(1)" + line 395, "pan.___", state 2511, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2543, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2557, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2576, "(1)" + line 421, "pan.___", state 2606, "(1)" + line 425, "pan.___", state 2619, "(1)" + line 395, "pan.___", state 2640, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2672, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2686, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2705, "(1)" + line 421, "pan.___", state 2735, "(1)" + line 425, "pan.___", state 2748, "(1)" + line 227, "pan.___", state 2781, "(1)" + line 235, "pan.___", state 2801, "(1)" + line 239, "pan.___", state 2809, "(1)" + line 227, "pan.___", state 2824, "(1)" + line 235, "pan.___", state 2844, "(1)" + line 239, "pan.___", state 2852, "(1)" + line 877, "pan.___", state 2869, "-end-" + (278 of 2869 states) +unreached in proctype urcu_writer + line 395, "pan.___", state 19, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 33, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 412, "pan.___", state 84, "(1)" + line 416, "pan.___", state 97, "(1)" + line 250, "pan.___", state 150, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 152, "(1)" + line 254, "pan.___", state 159, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 161, "(1)" + line 254, "pan.___", state 162, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 162, "else" + line 252, "pan.___", state 167, "((i<1))" + line 252, "pan.___", state 167, "((i>=1))" + line 258, "pan.___", state 172, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 174, "(1)" + line 258, "pan.___", state 175, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 175, "else" + line 262, "pan.___", state 181, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 183, "(1)" + line 262, "pan.___", state 184, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 184, "else" + line 267, "pan.___", state 193, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 267, "pan.___", state 193, "else" + line 395, "pan.___", state 212, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 226, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 244, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 258, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 277, "(1)" + line 416, "pan.___", state 290, "(1)" + line 421, "pan.___", state 307, "(1)" + line 425, "pan.___", state 320, "(1)" + line 399, "pan.___", state 357, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 375, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 389, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 421, "(1)" + line 421, "pan.___", state 438, "(1)" + line 425, "pan.___", state 451, "(1)" + line 399, "pan.___", state 495, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 513, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 527, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 559, "(1)" + line 421, "pan.___", state 576, "(1)" + line 425, "pan.___", state 589, "(1)" + line 399, "pan.___", state 624, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 642, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 656, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 688, "(1)" + line 421, "pan.___", state 705, "(1)" + line 425, "pan.___", state 718, "(1)" + line 399, "pan.___", state 755, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 773, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 787, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 819, "(1)" + line 421, "pan.___", state 836, "(1)" + line 425, "pan.___", state 849, "(1)" + line 250, "pan.___", state 904, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 913, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 227, "pan.___", state 951, "(1)" + line 231, "pan.___", state 959, "(1)" + line 235, "pan.___", state 971, "(1)" + line 239, "pan.___", state 979, "(1)" + line 250, "pan.___", state 1010, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1019, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1032, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1041, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1057, "(1)" + line 231, "pan.___", state 1065, "(1)" + line 235, "pan.___", state 1077, "(1)" + line 239, "pan.___", state 1085, "(1)" + line 254, "pan.___", state 1111, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1124, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1133, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1149, "(1)" + line 231, "pan.___", state 1157, "(1)" + line 235, "pan.___", state 1169, "(1)" + line 239, "pan.___", state 1177, "(1)" + line 250, "pan.___", state 1208, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1217, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1230, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1239, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1255, "(1)" + line 231, "pan.___", state 1263, "(1)" + line 235, "pan.___", state 1275, "(1)" + line 239, "pan.___", state 1283, "(1)" + line 254, "pan.___", state 1309, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1322, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1331, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1347, "(1)" + line 231, "pan.___", state 1355, "(1)" + line 235, "pan.___", state 1367, "(1)" + line 239, "pan.___", state 1375, "(1)" + line 250, "pan.___", state 1406, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1415, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1428, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1437, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1453, "(1)" + line 231, "pan.___", state 1461, "(1)" + line 235, "pan.___", state 1473, "(1)" + line 239, "pan.___", state 1481, "(1)" + line 254, "pan.___", state 1507, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1520, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1529, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1545, "(1)" + line 231, "pan.___", state 1553, "(1)" + line 235, "pan.___", state 1565, "(1)" + line 239, "pan.___", state 1573, "(1)" + line 250, "pan.___", state 1604, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1613, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1626, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1635, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1651, "(1)" + line 231, "pan.___", state 1659, "(1)" + line 235, "pan.___", state 1671, "(1)" + line 239, "pan.___", state 1679, "(1)" + line 1204, "pan.___", state 1695, "-end-" + (109 of 1695 states) +unreached in proctype :init: + line 1215, "pan.___", state 9, "((j<2))" + line 1215, "pan.___", state 9, "((j>=2))" + line 1216, "pan.___", state 20, "((j<2))" + line 1216, "pan.___", state 20, "((j>=2))" + line 1221, "pan.___", state 33, "((j<2))" + line 1221, "pan.___", state 33, "((j>=2))" + line 1219, "pan.___", state 43, "((i<1))" + line 1219, "pan.___", state 43, "((i>=1))" + line 1229, "pan.___", state 54, "((j<2))" + line 1229, "pan.___", state 54, "((j>=2))" + line 1233, "pan.___", state 67, "((j<2))" + line 1233, "pan.___", state 67, "((j>=2))" + (6 of 78 states) +unreached in proctype :never: + line 1263, "pan.___", state 8, "-end-" + (1 of 8 states) + +pan: elapsed time 5.46e+03 seconds +pan: rate 2887.6389 states/second +pan: avg transition delay 1.3027e-06 usec +cp .input.spin urcu_free_no_wmb.spin.input +cp .input.spin.trail urcu_free_no_wmb.spin.input.trail diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_wmb.spin.input b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_wmb.spin.input new file mode 100644 index 0000000..2ff2df1 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_wmb.spin.input @@ -0,0 +1,1240 @@ +#define NO_WMB + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_wmb.spin.input.trail b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_wmb.spin.input.trail new file mode 100644 index 0000000..ddfccff --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free_no_wmb.spin.input.trail @@ -0,0 +1,1485 @@ +-2:3:-2 +-4:-4:-4 +1:0:4644 +2:3:4564 +3:3:4567 +4:3:4567 +5:3:4570 +6:3:4578 +7:3:4578 +8:3:4581 +9:3:4587 +10:3:4591 +11:3:4591 +12:3:4594 +13:3:4604 +14:3:4612 +15:3:4612 +16:3:4615 +17:3:4621 +18:3:4625 +19:3:4625 +20:3:4628 +21:3:4634 +22:3:4638 +23:3:4639 +24:0:4644 +25:3:4641 +26:0:4644 +27:2:2871 +28:0:4644 +29:2:2877 +30:0:4644 +31:2:2878 +32:0:4644 +33:2:2880 +34:0:4644 +35:2:2881 +36:0:4644 +37:2:2882 +38:0:4644 +39:2:2883 +40:2:2884 +41:2:2888 +42:2:2889 +43:2:2897 +44:2:2898 +45:2:2902 +46:2:2903 +47:2:2911 +48:2:2916 +49:2:2920 +50:2:2921 +51:2:2929 +52:2:2930 +53:2:2934 +54:2:2935 +55:2:2929 +56:2:2930 +57:2:2934 +58:2:2935 +59:2:2943 +60:2:2948 +61:2:2949 +62:2:2960 +63:2:2961 +64:2:2962 +65:2:2973 +66:2:2978 +67:2:2979 +68:2:2990 +69:2:2991 +70:2:2992 +71:2:2990 +72:2:2991 +73:2:2992 +74:2:3003 +75:2:3011 +76:0:4644 +77:2:2882 +78:0:4644 +79:2:3063 +80:2:3064 +81:2:3065 +82:0:4644 +83:2:2882 +84:0:4644 +85:2:3070 +86:0:4644 +87:2:3773 +88:2:3774 +89:2:3778 +90:2:3782 +91:2:3783 +92:2:3787 +93:2:3792 +94:2:3800 +95:2:3804 +96:2:3805 +97:2:3800 +98:2:3801 +99:2:3809 +100:2:3816 +101:2:3823 +102:2:3824 +103:2:3831 +104:2:3836 +105:2:3843 +106:2:3844 +107:2:3843 +108:2:3844 +109:2:3851 +110:2:3855 +111:0:4644 +112:2:3860 +113:0:4644 +114:2:3861 +115:0:4644 +116:2:3862 +117:0:4644 +118:2:3863 +119:0:4644 +120:1:2 +121:0:4644 +122:2:3864 +123:0:4644 +124:1:8 +125:0:4644 +126:1:9 +127:0:4644 +128:2:3863 +129:0:4644 +130:1:10 +131:0:4644 +132:2:3864 +133:0:4644 +134:1:11 +135:0:4644 +136:2:3863 +137:0:4644 +138:1:12 +139:0:4644 +140:2:3864 +141:0:4644 +142:1:13 +143:0:4644 +144:2:3863 +145:0:4644 +146:1:14 +147:0:4644 +148:2:3864 +149:0:4644 +150:1:15 +151:0:4644 +152:1:16 +153:0:4644 +154:2:3863 +155:0:4644 +156:1:17 +157:0:4644 +158:2:3864 +159:0:4644 +160:1:26 +161:0:4644 +162:2:3863 +163:0:4644 +164:1:30 +165:1:31 +166:1:35 +167:1:39 +168:1:40 +169:1:44 +170:1:52 +171:1:53 +172:1:57 +173:1:61 +174:1:62 +175:1:57 +176:1:61 +177:1:62 +178:1:66 +179:1:73 +180:1:80 +181:1:81 +182:1:88 +183:1:93 +184:1:100 +185:1:101 +186:1:100 +187:1:101 +188:1:108 +189:1:112 +190:0:4644 +191:2:3864 +192:0:4644 +193:1:117 +194:0:4644 +195:2:3865 +196:0:4644 +197:2:3870 +198:0:4644 +199:2:3871 +200:0:4644 +201:2:3879 +202:2:3880 +203:2:3884 +204:2:3888 +205:2:3889 +206:2:3893 +207:2:3901 +208:2:3902 +209:2:3906 +210:2:3910 +211:2:3911 +212:2:3906 +213:2:3910 +214:2:3911 +215:2:3915 +216:2:3922 +217:2:3929 +218:2:3930 +219:2:3937 +220:2:3942 +221:2:3949 +222:2:3950 +223:2:3949 +224:2:3950 +225:2:3957 +226:2:3961 +227:0:4644 +228:2:3072 +229:2:3754 +230:0:4644 +231:2:2882 +232:0:4644 +233:2:3073 +234:0:4644 +235:2:2882 +236:0:4644 +237:2:3076 +238:2:3077 +239:2:3081 +240:2:3082 +241:2:3090 +242:2:3091 +243:2:3095 +244:2:3096 +245:2:3104 +246:2:3109 +247:2:3113 +248:2:3114 +249:2:3122 +250:2:3123 +251:2:3127 +252:2:3128 +253:2:3122 +254:2:3123 +255:2:3127 +256:2:3128 +257:2:3136 +258:2:3141 +259:2:3142 +260:2:3153 +261:2:3154 +262:2:3155 +263:2:3166 +264:2:3171 +265:2:3172 +266:2:3183 +267:2:3184 +268:2:3185 +269:2:3183 +270:2:3184 +271:2:3185 +272:2:3196 +273:2:3203 +274:0:4644 +275:2:2882 +276:0:4644 +277:2:3207 +278:2:3208 +279:2:3209 +280:2:3221 +281:2:3222 +282:2:3226 +283:2:3227 +284:2:3235 +285:2:3240 +286:2:3244 +287:2:3245 +288:2:3253 +289:2:3254 +290:2:3258 +291:2:3259 +292:2:3253 +293:2:3254 +294:2:3258 +295:2:3259 +296:2:3267 +297:2:3272 +298:2:3273 +299:2:3284 +300:2:3285 +301:2:3286 +302:2:3297 +303:2:3302 +304:2:3303 +305:2:3314 +306:2:3315 +307:2:3316 +308:2:3314 +309:2:3315 +310:2:3316 +311:2:3327 +312:2:3338 +313:2:3339 +314:0:4644 +315:2:2882 +316:0:4644 +317:2:3345 +318:2:3346 +319:2:3350 +320:2:3351 +321:2:3359 +322:2:3360 +323:2:3364 +324:2:3365 +325:2:3373 +326:2:3378 +327:2:3382 +328:2:3383 +329:2:3391 +330:2:3392 +331:2:3396 +332:2:3397 +333:2:3391 +334:2:3392 +335:2:3396 +336:2:3397 +337:2:3405 +338:2:3410 +339:2:3411 +340:2:3422 +341:2:3423 +342:2:3424 +343:2:3435 +344:2:3440 +345:2:3441 +346:2:3452 +347:2:3453 +348:2:3454 +349:2:3452 +350:2:3453 +351:2:3454 +352:2:3465 +353:0:4644 +354:2:2882 +355:0:4644 +356:2:3474 +357:2:3475 +358:2:3479 +359:2:3480 +360:2:3488 +361:2:3489 +362:2:3493 +363:2:3494 +364:2:3502 +365:2:3507 +366:2:3511 +367:2:3512 +368:2:3520 +369:2:3521 +370:2:3525 +371:2:3526 +372:2:3520 +373:2:3521 +374:2:3525 +375:2:3526 +376:2:3534 +377:2:3539 +378:2:3540 +379:2:3551 +380:2:3552 +381:2:3553 +382:2:3564 +383:2:3569 +384:2:3570 +385:2:3581 +386:2:3582 +387:2:3583 +388:2:3581 +389:2:3582 +390:2:3583 +391:2:3594 +392:2:3601 +393:0:4644 +394:2:2882 +395:0:4644 +396:2:3605 +397:2:3606 +398:2:3607 +399:2:3619 +400:2:3620 +401:2:3624 +402:2:3625 +403:2:3633 +404:2:3638 +405:2:3642 +406:2:3643 +407:2:3651 +408:2:3652 +409:2:3656 +410:2:3657 +411:2:3651 +412:2:3652 +413:2:3656 +414:2:3657 +415:2:3665 +416:2:3670 +417:2:3671 +418:2:3682 +419:2:3683 +420:2:3684 +421:2:3695 +422:2:3700 +423:2:3701 +424:2:3712 +425:2:3713 +426:2:3714 +427:2:3712 +428:2:3713 +429:2:3714 +430:2:3725 +431:2:3735 +432:2:3736 +433:0:4644 +434:2:2882 +435:0:4644 +436:2:3742 +437:0:4644 +438:2:4367 +439:2:4368 +440:2:4372 +441:2:4376 +442:2:4377 +443:2:4381 +444:2:4389 +445:2:4390 +446:2:4394 +447:2:4398 +448:2:4399 +449:2:4394 +450:2:4398 +451:2:4399 +452:2:4403 +453:2:4410 +454:2:4417 +455:2:4418 +456:2:4425 +457:2:4430 +458:2:4437 +459:2:4438 +460:2:4437 +461:2:4438 +462:2:4445 +463:2:4449 +464:0:4644 +465:2:4454 +466:0:4644 +467:2:4455 +468:0:4644 +469:2:4456 +470:0:4644 +471:2:4457 +472:0:4644 +473:1:26 +474:0:4644 +475:2:4458 +476:0:4644 +477:1:30 +478:1:31 +479:1:35 +480:1:39 +481:1:40 +482:1:44 +483:1:52 +484:1:53 +485:1:57 +486:1:61 +487:1:62 +488:1:57 +489:1:61 +490:1:62 +491:1:66 +492:1:73 +493:1:80 +494:1:81 +495:1:88 +496:1:93 +497:1:100 +498:1:101 +499:1:100 +500:1:101 +501:1:108 +502:1:112 +503:0:4644 +504:2:4457 +505:0:4644 +506:1:117 +507:0:4644 +508:2:4458 +509:0:4644 +510:2:4459 +511:0:4644 +512:2:4464 +513:0:4644 +514:2:4465 +515:0:4644 +516:2:4473 +517:2:4474 +518:2:4478 +519:2:4482 +520:2:4483 +521:2:4487 +522:2:4495 +523:2:4496 +524:2:4500 +525:2:4504 +526:2:4505 +527:2:4500 +528:2:4504 +529:2:4505 +530:2:4509 +531:2:4516 +532:2:4523 +533:2:4524 +534:2:4531 +535:2:4536 +536:2:4543 +537:2:4544 +538:2:4543 +539:2:4544 +540:2:4551 +541:2:4555 +542:0:4644 +543:2:3744 +544:2:3754 +545:0:4644 +546:2:2882 +547:0:4644 +548:2:3745 +549:2:3746 +550:0:4644 +551:2:2882 +552:0:4644 +553:2:3750 +554:0:4644 +555:2:3758 +556:0:4644 +557:2:2878 +558:0:4644 +559:2:2880 +560:0:4644 +561:2:2881 +562:0:4644 +563:2:2882 +564:0:4644 +565:2:3063 +566:2:3064 +567:2:3065 +568:0:4644 +569:2:2882 +570:0:4644 +571:2:2883 +572:2:2884 +573:2:2888 +574:2:2889 +575:2:2897 +576:2:2898 +577:2:2902 +578:2:2903 +579:2:2911 +580:2:2916 +581:2:2917 +582:2:2929 +583:2:2930 +584:2:2931 +585:2:2929 +586:2:2930 +587:2:2934 +588:2:2935 +589:2:2943 +590:2:2948 +591:2:2949 +592:2:2960 +593:2:2961 +594:2:2962 +595:2:2973 +596:2:2978 +597:2:2979 +598:2:2990 +599:2:2991 +600:2:2992 +601:2:2990 +602:2:2991 +603:2:2992 +604:2:3003 +605:2:3011 +606:0:4644 +607:2:2882 +608:0:4644 +609:2:3070 +610:0:4644 +611:2:3773 +612:2:3774 +613:2:3778 +614:2:3782 +615:2:3783 +616:2:3787 +617:2:3795 +618:2:3796 +619:2:3800 +620:2:3801 +621:2:3800 +622:2:3804 +623:2:3805 +624:2:3809 +625:2:3816 +626:2:3823 +627:2:3824 +628:2:3831 +629:2:3836 +630:2:3843 +631:2:3844 +632:2:3843 +633:2:3844 +634:2:3851 +635:2:3855 +636:0:4644 +637:2:3860 +638:0:4644 +639:2:3861 +640:0:4644 +641:2:3862 +642:0:4644 +643:2:3863 +644:0:4644 +645:1:26 +646:0:4644 +647:2:3864 +648:0:4644 +649:1:30 +650:1:31 +651:1:35 +652:1:39 +653:1:40 +654:1:44 +655:1:52 +656:1:53 +657:1:57 +658:1:61 +659:1:62 +660:1:57 +661:1:61 +662:1:62 +663:1:66 +664:1:73 +665:1:80 +666:1:81 +667:1:88 +668:1:93 +669:1:100 +670:1:101 +671:1:100 +672:1:101 +673:1:108 +674:1:112 +675:0:4644 +676:2:3863 +677:0:4644 +678:1:117 +679:0:4644 +680:2:3864 +681:0:4644 +682:2:3865 +683:0:4644 +684:2:3870 +685:0:4644 +686:2:3871 +687:0:4644 +688:2:3879 +689:2:3880 +690:2:3884 +691:2:3888 +692:2:3889 +693:2:3893 +694:2:3901 +695:2:3902 +696:2:3906 +697:2:3910 +698:2:3911 +699:2:3906 +700:2:3910 +701:2:3911 +702:2:3915 +703:2:3922 +704:2:3929 +705:2:3930 +706:2:3937 +707:2:3942 +708:2:3949 +709:2:3950 +710:2:3949 +711:2:3950 +712:2:3957 +713:2:3961 +714:0:4644 +715:2:3072 +716:2:3754 +717:0:4644 +718:2:2882 +719:0:4644 +720:2:3073 +721:0:4644 +722:2:2882 +723:0:4644 +724:2:3076 +725:2:3077 +726:2:3081 +727:2:3082 +728:2:3090 +729:2:3091 +730:2:3095 +731:2:3096 +732:2:3104 +733:2:3109 +734:2:3113 +735:2:3114 +736:2:3122 +737:2:3123 +738:2:3127 +739:2:3128 +740:2:3122 +741:2:3123 +742:2:3127 +743:2:3128 +744:2:3136 +745:2:3141 +746:2:3142 +747:2:3153 +748:2:3154 +749:2:3155 +750:2:3166 +751:2:3171 +752:2:3172 +753:2:3183 +754:2:3184 +755:2:3185 +756:2:3183 +757:2:3184 +758:2:3185 +759:2:3196 +760:2:3203 +761:0:4644 +762:2:2882 +763:0:4644 +764:2:3207 +765:2:3208 +766:2:3209 +767:2:3221 +768:2:3222 +769:2:3226 +770:2:3227 +771:2:3235 +772:2:3240 +773:2:3244 +774:2:3245 +775:2:3253 +776:2:3254 +777:2:3258 +778:2:3259 +779:2:3253 +780:2:3254 +781:2:3258 +782:2:3259 +783:2:3267 +784:2:3272 +785:2:3273 +786:2:3284 +787:2:3285 +788:2:3286 +789:2:3297 +790:2:3302 +791:2:3303 +792:2:3314 +793:2:3315 +794:2:3316 +795:2:3314 +796:2:3315 +797:2:3316 +798:2:3327 +799:2:3338 +800:2:3339 +801:0:4644 +802:2:2882 +803:0:4644 +804:2:3345 +805:2:3346 +806:2:3350 +807:2:3351 +808:2:3359 +809:2:3360 +810:2:3364 +811:2:3365 +812:2:3373 +813:2:3378 +814:2:3382 +815:2:3383 +816:2:3391 +817:2:3392 +818:2:3396 +819:2:3397 +820:2:3391 +821:2:3392 +822:2:3396 +823:2:3397 +824:2:3405 +825:2:3410 +826:2:3411 +827:2:3422 +828:2:3423 +829:2:3424 +830:2:3435 +831:2:3440 +832:2:3441 +833:2:3452 +834:2:3453 +835:2:3454 +836:2:3452 +837:2:3453 +838:2:3454 +839:2:3465 +840:0:4644 +841:2:2882 +842:0:4644 +843:2:3474 +844:2:3475 +845:2:3479 +846:2:3480 +847:2:3488 +848:2:3489 +849:2:3493 +850:2:3494 +851:2:3502 +852:2:3507 +853:2:3511 +854:2:3512 +855:2:3520 +856:2:3521 +857:2:3525 +858:2:3526 +859:2:3520 +860:2:3521 +861:2:3525 +862:2:3526 +863:2:3534 +864:2:3539 +865:2:3540 +866:2:3551 +867:2:3552 +868:2:3553 +869:2:3564 +870:2:3569 +871:2:3570 +872:2:3581 +873:2:3582 +874:2:3583 +875:2:3581 +876:2:3582 +877:2:3583 +878:2:3594 +879:2:3601 +880:0:4644 +881:2:2882 +882:0:4644 +883:2:3605 +884:2:3606 +885:2:3607 +886:2:3619 +887:2:3620 +888:2:3624 +889:2:3625 +890:2:3633 +891:2:3638 +892:2:3642 +893:2:3643 +894:2:3651 +895:2:3652 +896:2:3656 +897:2:3657 +898:2:3651 +899:2:3652 +900:2:3656 +901:2:3657 +902:2:3665 +903:2:3670 +904:2:3671 +905:2:3682 +906:2:3683 +907:2:3684 +908:2:3695 +909:2:3700 +910:2:3701 +911:2:3712 +912:2:3713 +913:2:3714 +914:2:3712 +915:2:3713 +916:2:3714 +917:2:3725 +918:2:3735 +919:2:3736 +920:0:4644 +921:2:2882 +922:0:4644 +923:2:3742 +924:0:4644 +925:2:4367 +926:2:4368 +927:2:4372 +928:2:4376 +929:2:4377 +930:2:4381 +931:2:4389 +932:2:4390 +933:2:4394 +934:2:4398 +935:2:4399 +936:2:4394 +937:2:4398 +938:2:4399 +939:2:4403 +940:2:4410 +941:2:4417 +942:2:4418 +943:2:4425 +944:2:4430 +945:2:4437 +946:2:4438 +947:2:4437 +948:2:4438 +949:2:4445 +950:2:4449 +951:0:4644 +952:2:4454 +953:0:4644 +954:2:4455 +955:0:4644 +956:2:4456 +957:0:4644 +958:2:4457 +959:0:4644 +960:1:26 +961:0:4644 +962:2:4458 +963:0:4644 +964:1:30 +965:1:31 +966:1:35 +967:1:39 +968:1:40 +969:1:44 +970:1:52 +971:1:53 +972:1:57 +973:1:61 +974:1:62 +975:1:57 +976:1:61 +977:1:62 +978:1:66 +979:1:73 +980:1:80 +981:1:81 +982:1:88 +983:1:93 +984:1:100 +985:1:101 +986:1:100 +987:1:101 +988:1:108 +989:1:112 +990:0:4644 +991:2:4457 +992:0:4644 +993:1:117 +994:0:4644 +995:2:4458 +996:0:4644 +997:2:4459 +998:0:4644 +999:2:4464 +1000:0:4644 +1001:2:4465 +1002:0:4644 +1003:2:4473 +1004:2:4474 +1005:2:4478 +1006:2:4482 +1007:2:4483 +1008:2:4487 +1009:2:4495 +1010:2:4496 +1011:2:4500 +1012:2:4504 +1013:2:4505 +1014:2:4500 +1015:2:4504 +1016:2:4505 +1017:2:4509 +1018:2:4516 +1019:2:4523 +1020:2:4524 +1021:2:4531 +1022:2:4536 +1023:2:4543 +1024:2:4544 +1025:2:4543 +1026:2:4544 +1027:2:4551 +1028:2:4555 +1029:0:4644 +1030:2:3744 +1031:2:3754 +1032:0:4644 +1033:2:2882 +1034:0:4644 +1035:2:3745 +1036:2:3746 +1037:0:4644 +1038:2:2882 +1039:0:4644 +1040:2:3750 +1041:0:4644 +1042:2:3758 +1043:0:4644 +1044:2:2878 +1045:0:4644 +1046:2:2880 +1047:0:4644 +1048:2:2881 +1049:0:4644 +1050:2:2882 +1051:0:4644 +1052:2:2883 +1053:2:2884 +1054:2:2888 +1055:2:2889 +1056:2:2897 +1057:2:2898 +1058:2:2902 +1059:2:2903 +1060:2:2911 +1061:2:2916 +1062:2:2920 +1063:2:2921 +1064:2:2929 +1065:2:2930 +1066:2:2934 +1067:2:2935 +1068:2:2929 +1069:2:2930 +1070:2:2931 +1071:2:2943 +1072:2:2948 +1073:2:2949 +1074:2:2960 +1075:2:2961 +1076:2:2962 +1077:2:2973 +1078:2:2978 +1079:2:2979 +1080:2:2990 +1081:2:2991 +1082:2:2992 +1083:2:2990 +1084:2:2991 +1085:2:2992 +1086:2:3003 +1087:2:3011 +1088:0:4644 +1089:2:2882 +1090:0:4644 +1091:2:3063 +1092:2:3064 +1093:2:3065 +1094:0:4644 +1095:2:2882 +1096:0:4644 +1097:2:3070 +1098:0:4644 +1099:1:118 +1100:0:4644 +1101:1:120 +1102:0:4644 +1103:1:19 +1104:0:4644 +1105:1:126 +1106:1:127 +1107:1:131 +1108:1:132 +1109:1:140 +1110:1:141 +1111:1:145 +1112:1:146 +1113:1:154 +1114:1:159 +1115:1:163 +1116:1:164 +1117:1:172 +1118:1:173 +1119:1:177 +1120:1:178 +1121:1:172 +1122:1:173 +1123:1:177 +1124:1:178 +1125:1:186 +1126:1:191 +1127:1:192 +1128:1:203 +1129:1:204 +1130:1:205 +1131:1:216 +1132:1:221 +1133:1:222 +1134:1:233 +1135:1:234 +1136:1:235 +1137:1:233 +1138:1:234 +1139:1:235 +1140:1:246 +1141:0:4644 +1142:1:15 +1143:0:4644 +1144:1:16 +1145:0:4644 +1146:1:17 +1147:0:4644 +1148:1:118 +1149:0:4644 +1150:1:120 +1151:0:4644 +1152:1:19 +1153:0:4644 +1154:1:255 +1155:1:256 +1156:0:4644 +1157:1:15 +1158:0:4644 +1159:1:16 +1160:0:4644 +1161:1:17 +1162:0:4644 +1163:1:118 +1164:0:4644 +1165:1:120 +1166:0:4644 +1167:1:19 +1168:0:4644 +1169:1:262 +1170:1:263 +1171:1:267 +1172:1:268 +1173:1:276 +1174:1:277 +1175:1:281 +1176:1:282 +1177:1:290 +1178:1:295 +1179:1:299 +1180:1:300 +1181:1:308 +1182:1:309 +1183:1:313 +1184:1:314 +1185:1:308 +1186:1:309 +1187:1:313 +1188:1:314 +1189:1:322 +1190:1:327 +1191:1:328 +1192:1:339 +1193:1:340 +1194:1:341 +1195:1:352 +1196:1:357 +1197:1:358 +1198:1:369 +1199:1:370 +1200:1:371 +1201:1:369 +1202:1:370 +1203:1:371 +1204:1:382 +1205:0:4644 +1206:1:15 +1207:0:4644 +1208:1:16 +1209:0:4644 +1210:1:17 +1211:0:4644 +1212:1:118 +1213:0:4644 +1214:1:120 +1215:0:4644 +1216:1:19 +1217:0:4644 +1218:1:391 +1219:1:392 +1220:1:396 +1221:1:397 +1222:1:405 +1223:1:406 +1224:1:410 +1225:1:411 +1226:1:419 +1227:1:424 +1228:1:428 +1229:1:429 +1230:1:437 +1231:1:438 +1232:1:442 +1233:1:443 +1234:1:437 +1235:1:438 +1236:1:442 +1237:1:443 +1238:1:451 +1239:1:456 +1240:1:457 +1241:1:468 +1242:1:469 +1243:1:470 +1244:1:481 +1245:1:486 +1246:1:487 +1247:1:498 +1248:1:499 +1249:1:500 +1250:1:498 +1251:1:499 +1252:1:500 +1253:1:511 +1254:1:518 +1255:0:4644 +1256:1:15 +1257:0:4644 +1258:1:16 +1259:0:4644 +1260:1:17 +1261:0:4644 +1262:1:118 +1263:0:4644 +1264:1:120 +1265:0:4644 +1266:1:19 +1267:0:4644 +1268:1:656 +1269:1:657 +1270:1:661 +1271:1:662 +1272:1:670 +1273:1:671 +1274:1:672 +1275:1:684 +1276:1:689 +1277:1:693 +1278:1:694 +1279:1:702 +1280:1:703 +1281:1:707 +1282:1:708 +1283:1:702 +1284:1:703 +1285:1:707 +1286:1:708 +1287:1:716 +1288:1:721 +1289:1:722 +1290:1:733 +1291:1:734 +1292:1:735 +1293:1:746 +1294:1:751 +1295:1:752 +1296:1:763 +1297:1:764 +1298:1:765 +1299:1:763 +1300:1:764 +1301:1:765 +1302:1:776 +1303:0:4644 +1304:1:15 +1305:0:4644 +1306:1:16 +1307:0:4644 +1308:1:17 +1309:0:4644 +1310:1:118 +1311:0:4644 +1312:1:120 +1313:0:4644 +1314:1:19 +1315:0:4644 +1316:1:785 +1317:1:788 +1318:1:789 +1319:0:4644 +1320:1:15 +1321:0:4644 +1322:1:16 +1323:0:4644 +1324:1:17 +1325:0:4644 +1326:1:118 +1327:0:4644 +1328:1:120 +1329:0:4644 +1330:1:19 +1331:0:4644 +1332:1:1052 +1333:1:1053 +1334:1:1057 +1335:1:1058 +1336:1:1066 +1337:1:1067 +1338:1:1071 +1339:1:1072 +1340:1:1080 +1341:1:1085 +1342:1:1089 +1343:1:1090 +1344:1:1098 +1345:1:1099 +1346:1:1103 +1347:1:1104 +1348:1:1098 +1349:1:1099 +1350:1:1103 +1351:1:1104 +1352:1:1112 +1353:1:1117 +1354:1:1118 +1355:1:1129 +1356:1:1130 +1357:1:1131 +1358:1:1142 +1359:1:1147 +1360:1:1148 +1361:1:1159 +1362:1:1160 +1363:1:1161 +1364:1:1159 +1365:1:1160 +1366:1:1161 +1367:1:1172 +1368:1:1179 +1369:1:1183 +1370:0:4644 +1371:1:15 +1372:0:4644 +1373:1:16 +1374:0:4644 +1375:1:17 +1376:0:4644 +1377:1:118 +1378:0:4644 +1379:1:120 +1380:0:4644 +1381:1:19 +1382:0:4644 +1383:1:1184 +1384:1:1185 +1385:1:1189 +1386:1:1190 +1387:1:1198 +1388:1:1199 +1389:1:1200 +1390:1:1212 +1391:1:1217 +1392:1:1221 +1393:1:1222 +1394:1:1230 +1395:1:1231 +1396:1:1235 +1397:1:1236 +1398:1:1230 +1399:1:1231 +1400:1:1235 +1401:1:1236 +1402:1:1244 +1403:1:1249 +1404:1:1250 +1405:1:1261 +1406:1:1262 +1407:1:1263 +1408:1:1274 +1409:1:1279 +1410:1:1280 +1411:1:1291 +1412:1:1292 +1413:1:1293 +1414:1:1291 +1415:1:1292 +1416:1:1293 +1417:1:1304 +1418:0:4644 +1419:1:15 +1420:0:4644 +1421:1:16 +1422:0:4644 +1423:1:17 +1424:0:4644 +1425:1:118 +1426:0:4644 +1427:1:120 +1428:0:4644 +1429:1:19 +1430:0:4644 +1431:1:1313 +1432:0:4644 +1433:1:2777 +1434:1:2784 +1435:1:2785 +1436:1:2792 +1437:1:2797 +1438:1:2804 +1439:1:2805 +1440:1:2804 +1441:1:2805 +1442:1:2812 +1443:1:2816 +1444:0:4644 +1445:2:3773 +1446:2:3774 +1447:2:3778 +1448:2:3782 +1449:2:3783 +1450:2:3787 +1451:2:3792 +1452:2:3800 +1453:2:3804 +1454:2:3805 +1455:2:3800 +1456:2:3801 +1457:2:3809 +1458:2:3816 +1459:2:3823 +1460:2:3824 +1461:2:3831 +1462:2:3836 +1463:2:3843 +1464:2:3844 +1465:2:3843 +1466:2:3844 +1467:2:3851 +1468:2:3855 +1469:0:4644 +1470:2:3860 +1471:0:4644 +1472:2:3861 +1473:0:4644 +1474:2:3862 +1475:0:4644 +1476:2:3863 +1477:0:4644 +1478:1:1315 +1479:1:1316 +1480:0:4642 +1481:2:3864 +1482:0:4648 +1483:1:2474 diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free_single_flip.define b/formal-model/results/urcu-controldataflow-ipi/urcu_free_single_flip.define new file mode 100644 index 0000000..5e642ef --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free_single_flip.define @@ -0,0 +1 @@ +#define SINGLE_FLIP diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free_single_flip.log b/formal-model/results/urcu-controldataflow-ipi/urcu_free_single_flip.log new file mode 100644 index 0000000..eedc9f4 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free_single_flip.log @@ -0,0 +1,761 @@ +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define >> pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_free.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_free_single_flip.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1258) +Depth= 6859 States= 1e+06 Transitions= 1.64e+08 Memory= 550.432 t= 209 R= 5e+03 +Depth= 6859 States= 2e+06 Transitions= 3.19e+08 Memory= 634.318 t= 409 R= 5e+03 +Depth= 6859 States= 3e+06 Transitions= 4.93e+08 Memory= 718.303 t= 643 R= 5e+03 +pan: resizing hashtable to -w22.. done +Depth= 6859 States= 4e+06 Transitions= 6.91e+08 Memory= 833.311 t= 903 R= 4e+03 +Depth= 6859 States= 5e+06 Transitions= 9e+08 Memory= 917.295 t= 1.17e+03 R= 4e+03 +Depth= 6859 States= 6e+06 Transitions= 1.08e+09 Memory= 1001.279 t= 1.41e+03 R= 4e+03 +pan: claim violated! (at depth 1383) +pan: wrote .input.spin.trail + +(Spin Version 5.1.7 -- 23 December 2008) +Warning: Search not completed + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness disabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 6859, errors: 1 + 6177712 states, stored +1.1177865e+09 states, matched +1.1239642e+09 transitions (= stored+matched) +6.3626905e+09 atomic steps +hash conflicts: 8.98825e+08 (resolved) + +Stats on memory usage (in Megabytes): + 683.417 equivalent memory usage for states (stored*(State-vector + overhead)) + 526.801 actual memory usage for states (compression: 77.08%) + state-vector as stored = 61 byte + 28 byte overhead + 32.000 memory used for hash table (-w22) + 457.764 memory used for DFS stack (-m10000000) + 1016.221 total actual memory usage + +unreached in proctype urcu_reader + line 250, "pan.___", state 30, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 52, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 61, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 77, "(1)" + line 231, "pan.___", state 85, "(1)" + line 235, "pan.___", state 97, "(1)" + line 239, "pan.___", state 105, "(1)" + line 395, "pan.___", state 131, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 163, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 177, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 196, "(1)" + line 421, "pan.___", state 226, "(1)" + line 425, "pan.___", state 239, "(1)" + line 670, "pan.___", state 260, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 395, "pan.___", state 267, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 299, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 313, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 332, "(1)" + line 421, "pan.___", state 362, "(1)" + line 425, "pan.___", state 375, "(1)" + line 395, "pan.___", state 396, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 428, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 442, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 461, "(1)" + line 421, "pan.___", state 491, "(1)" + line 425, "pan.___", state 504, "(1)" + line 395, "pan.___", state 527, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 529, "(1)" + line 395, "pan.___", state 530, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 530, "else" + line 395, "pan.___", state 533, "(1)" + line 399, "pan.___", state 541, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 543, "(1)" + line 399, "pan.___", state 544, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 544, "else" + line 399, "pan.___", state 547, "(1)" + line 399, "pan.___", state 548, "(1)" + line 399, "pan.___", state 548, "(1)" + line 397, "pan.___", state 553, "((i<1))" + line 397, "pan.___", state 553, "((i>=1))" + line 404, "pan.___", state 559, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 561, "(1)" + line 404, "pan.___", state 562, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 562, "else" + line 404, "pan.___", state 565, "(1)" + line 404, "pan.___", state 566, "(1)" + line 404, "pan.___", state 566, "(1)" + line 408, "pan.___", state 573, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 575, "(1)" + line 408, "pan.___", state 576, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 576, "else" + line 408, "pan.___", state 579, "(1)" + line 408, "pan.___", state 580, "(1)" + line 408, "pan.___", state 580, "(1)" + line 406, "pan.___", state 585, "((i<2))" + line 406, "pan.___", state 585, "((i>=2))" + line 412, "pan.___", state 592, "(1)" + line 412, "pan.___", state 593, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 593, "else" + line 412, "pan.___", state 596, "(1)" + line 412, "pan.___", state 597, "(1)" + line 412, "pan.___", state 597, "(1)" + line 416, "pan.___", state 605, "(1)" + line 416, "pan.___", state 606, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 606, "else" + line 416, "pan.___", state 609, "(1)" + line 416, "pan.___", state 610, "(1)" + line 416, "pan.___", state 610, "(1)" + line 414, "pan.___", state 615, "((i<1))" + line 414, "pan.___", state 615, "((i>=1))" + line 421, "pan.___", state 622, "(1)" + line 421, "pan.___", state 623, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 623, "else" + line 421, "pan.___", state 626, "(1)" + line 421, "pan.___", state 627, "(1)" + line 421, "pan.___", state 627, "(1)" + line 425, "pan.___", state 635, "(1)" + line 425, "pan.___", state 636, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 636, "else" + line 425, "pan.___", state 639, "(1)" + line 425, "pan.___", state 640, "(1)" + line 425, "pan.___", state 640, "(1)" + line 423, "pan.___", state 645, "((i<2))" + line 423, "pan.___", state 645, "((i>=2))" + line 430, "pan.___", state 649, "(1)" + line 430, "pan.___", state 649, "(1)" + line 670, "pan.___", state 652, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 670, "pan.___", state 653, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 670, "pan.___", state 654, "(1)" + line 395, "pan.___", state 661, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 693, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 707, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 726, "(1)" + line 421, "pan.___", state 756, "(1)" + line 425, "pan.___", state 769, "(1)" + line 395, "pan.___", state 797, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 799, "(1)" + line 395, "pan.___", state 800, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 800, "else" + line 395, "pan.___", state 803, "(1)" + line 399, "pan.___", state 811, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 813, "(1)" + line 399, "pan.___", state 814, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 814, "else" + line 399, "pan.___", state 817, "(1)" + line 399, "pan.___", state 818, "(1)" + line 399, "pan.___", state 818, "(1)" + line 397, "pan.___", state 823, "((i<1))" + line 397, "pan.___", state 823, "((i>=1))" + line 404, "pan.___", state 829, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 831, "(1)" + line 404, "pan.___", state 832, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 832, "else" + line 404, "pan.___", state 835, "(1)" + line 404, "pan.___", state 836, "(1)" + line 404, "pan.___", state 836, "(1)" + line 408, "pan.___", state 843, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 845, "(1)" + line 408, "pan.___", state 846, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 846, "else" + line 408, "pan.___", state 849, "(1)" + line 408, "pan.___", state 850, "(1)" + line 408, "pan.___", state 850, "(1)" + line 406, "pan.___", state 855, "((i<2))" + line 406, "pan.___", state 855, "((i>=2))" + line 412, "pan.___", state 862, "(1)" + line 412, "pan.___", state 863, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 863, "else" + line 412, "pan.___", state 866, "(1)" + line 412, "pan.___", state 867, "(1)" + line 412, "pan.___", state 867, "(1)" + line 416, "pan.___", state 875, "(1)" + line 416, "pan.___", state 876, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 876, "else" + line 416, "pan.___", state 879, "(1)" + line 416, "pan.___", state 880, "(1)" + line 416, "pan.___", state 880, "(1)" + line 414, "pan.___", state 885, "((i<1))" + line 414, "pan.___", state 885, "((i>=1))" + line 421, "pan.___", state 892, "(1)" + line 421, "pan.___", state 893, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 893, "else" + line 421, "pan.___", state 896, "(1)" + line 421, "pan.___", state 897, "(1)" + line 421, "pan.___", state 897, "(1)" + line 425, "pan.___", state 905, "(1)" + line 425, "pan.___", state 906, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 906, "else" + line 425, "pan.___", state 909, "(1)" + line 425, "pan.___", state 910, "(1)" + line 425, "pan.___", state 910, "(1)" + line 430, "pan.___", state 919, "(1)" + line 430, "pan.___", state 919, "(1)" + line 395, "pan.___", state 926, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 928, "(1)" + line 395, "pan.___", state 929, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 929, "else" + line 395, "pan.___", state 932, "(1)" + line 399, "pan.___", state 940, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 942, "(1)" + line 399, "pan.___", state 943, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 943, "else" + line 399, "pan.___", state 946, "(1)" + line 399, "pan.___", state 947, "(1)" + line 399, "pan.___", state 947, "(1)" + line 397, "pan.___", state 952, "((i<1))" + line 397, "pan.___", state 952, "((i>=1))" + line 404, "pan.___", state 958, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 960, "(1)" + line 404, "pan.___", state 961, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 961, "else" + line 404, "pan.___", state 964, "(1)" + line 404, "pan.___", state 965, "(1)" + line 404, "pan.___", state 965, "(1)" + line 408, "pan.___", state 972, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 974, "(1)" + line 408, "pan.___", state 975, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 975, "else" + line 408, "pan.___", state 978, "(1)" + line 408, "pan.___", state 979, "(1)" + line 408, "pan.___", state 979, "(1)" + line 406, "pan.___", state 984, "((i<2))" + line 406, "pan.___", state 984, "((i>=2))" + line 412, "pan.___", state 991, "(1)" + line 412, "pan.___", state 992, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 992, "else" + line 412, "pan.___", state 995, "(1)" + line 412, "pan.___", state 996, "(1)" + line 412, "pan.___", state 996, "(1)" + line 416, "pan.___", state 1004, "(1)" + line 416, "pan.___", state 1005, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 1005, "else" + line 416, "pan.___", state 1008, "(1)" + line 416, "pan.___", state 1009, "(1)" + line 416, "pan.___", state 1009, "(1)" + line 414, "pan.___", state 1014, "((i<1))" + line 414, "pan.___", state 1014, "((i>=1))" + line 421, "pan.___", state 1021, "(1)" + line 421, "pan.___", state 1022, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 1022, "else" + line 421, "pan.___", state 1025, "(1)" + line 421, "pan.___", state 1026, "(1)" + line 421, "pan.___", state 1026, "(1)" + line 425, "pan.___", state 1034, "(1)" + line 425, "pan.___", state 1035, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 1035, "else" + line 425, "pan.___", state 1038, "(1)" + line 425, "pan.___", state 1039, "(1)" + line 425, "pan.___", state 1039, "(1)" + line 423, "pan.___", state 1044, "((i<2))" + line 423, "pan.___", state 1044, "((i>=2))" + line 430, "pan.___", state 1048, "(1)" + line 430, "pan.___", state 1048, "(1)" + line 678, "pan.___", state 1052, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 395, "pan.___", state 1057, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1089, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1103, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1122, "(1)" + line 421, "pan.___", state 1152, "(1)" + line 425, "pan.___", state 1165, "(1)" + line 395, "pan.___", state 1189, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1221, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1235, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1254, "(1)" + line 421, "pan.___", state 1284, "(1)" + line 425, "pan.___", state 1297, "(1)" + line 395, "pan.___", state 1322, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1354, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1368, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1387, "(1)" + line 421, "pan.___", state 1417, "(1)" + line 425, "pan.___", state 1430, "(1)" + line 395, "pan.___", state 1451, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1483, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1497, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1516, "(1)" + line 421, "pan.___", state 1546, "(1)" + line 425, "pan.___", state 1559, "(1)" + line 395, "pan.___", state 1585, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1617, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1631, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1650, "(1)" + line 421, "pan.___", state 1680, "(1)" + line 425, "pan.___", state 1693, "(1)" + line 395, "pan.___", state 1714, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1746, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1760, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1779, "(1)" + line 421, "pan.___", state 1809, "(1)" + line 425, "pan.___", state 1822, "(1)" + line 395, "pan.___", state 1846, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1878, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1892, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1911, "(1)" + line 421, "pan.___", state 1941, "(1)" + line 425, "pan.___", state 1954, "(1)" + line 717, "pan.___", state 1975, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 395, "pan.___", state 1982, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2014, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2028, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2047, "(1)" + line 421, "pan.___", state 2077, "(1)" + line 425, "pan.___", state 2090, "(1)" + line 395, "pan.___", state 2111, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2143, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2157, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2176, "(1)" + line 421, "pan.___", state 2206, "(1)" + line 425, "pan.___", state 2219, "(1)" + line 395, "pan.___", state 2242, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 2244, "(1)" + line 395, "pan.___", state 2245, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 2245, "else" + line 395, "pan.___", state 2248, "(1)" + line 399, "pan.___", state 2256, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2258, "(1)" + line 399, "pan.___", state 2259, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 2259, "else" + line 399, "pan.___", state 2262, "(1)" + line 399, "pan.___", state 2263, "(1)" + line 399, "pan.___", state 2263, "(1)" + line 397, "pan.___", state 2268, "((i<1))" + line 397, "pan.___", state 2268, "((i>=1))" + line 404, "pan.___", state 2274, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2276, "(1)" + line 404, "pan.___", state 2277, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 2277, "else" + line 404, "pan.___", state 2280, "(1)" + line 404, "pan.___", state 2281, "(1)" + line 404, "pan.___", state 2281, "(1)" + line 408, "pan.___", state 2288, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2290, "(1)" + line 408, "pan.___", state 2291, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 2291, "else" + line 408, "pan.___", state 2294, "(1)" + line 408, "pan.___", state 2295, "(1)" + line 408, "pan.___", state 2295, "(1)" + line 406, "pan.___", state 2300, "((i<2))" + line 406, "pan.___", state 2300, "((i>=2))" + line 412, "pan.___", state 2307, "(1)" + line 412, "pan.___", state 2308, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 2308, "else" + line 412, "pan.___", state 2311, "(1)" + line 412, "pan.___", state 2312, "(1)" + line 412, "pan.___", state 2312, "(1)" + line 416, "pan.___", state 2320, "(1)" + line 416, "pan.___", state 2321, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 2321, "else" + line 416, "pan.___", state 2324, "(1)" + line 416, "pan.___", state 2325, "(1)" + line 416, "pan.___", state 2325, "(1)" + line 414, "pan.___", state 2330, "((i<1))" + line 414, "pan.___", state 2330, "((i>=1))" + line 421, "pan.___", state 2337, "(1)" + line 421, "pan.___", state 2338, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 2338, "else" + line 421, "pan.___", state 2341, "(1)" + line 421, "pan.___", state 2342, "(1)" + line 421, "pan.___", state 2342, "(1)" + line 425, "pan.___", state 2350, "(1)" + line 425, "pan.___", state 2351, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 2351, "else" + line 425, "pan.___", state 2354, "(1)" + line 425, "pan.___", state 2355, "(1)" + line 425, "pan.___", state 2355, "(1)" + line 423, "pan.___", state 2360, "((i<2))" + line 423, "pan.___", state 2360, "((i>=2))" + line 430, "pan.___", state 2364, "(1)" + line 430, "pan.___", state 2364, "(1)" + line 717, "pan.___", state 2367, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 717, "pan.___", state 2368, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 717, "pan.___", state 2369, "(1)" + line 395, "pan.___", state 2376, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2408, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2422, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2441, "(1)" + line 421, "pan.___", state 2471, "(1)" + line 425, "pan.___", state 2484, "(1)" + line 395, "pan.___", state 2511, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2543, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2557, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2576, "(1)" + line 421, "pan.___", state 2606, "(1)" + line 425, "pan.___", state 2619, "(1)" + line 395, "pan.___", state 2640, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2672, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2686, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2705, "(1)" + line 421, "pan.___", state 2735, "(1)" + line 425, "pan.___", state 2748, "(1)" + line 227, "pan.___", state 2781, "(1)" + line 235, "pan.___", state 2801, "(1)" + line 239, "pan.___", state 2809, "(1)" + line 227, "pan.___", state 2824, "(1)" + line 235, "pan.___", state 2844, "(1)" + line 239, "pan.___", state 2852, "(1)" + line 877, "pan.___", state 2869, "-end-" + (278 of 2869 states) +unreached in proctype urcu_writer + line 395, "pan.___", state 22, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 36, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 54, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 412, "pan.___", state 87, "(1)" + line 416, "pan.___", state 100, "(1)" + line 421, "pan.___", state 117, "(1)" + line 250, "pan.___", state 153, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 162, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 175, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 215, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 229, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 247, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 261, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 280, "(1)" + line 416, "pan.___", state 293, "(1)" + line 421, "pan.___", state 310, "(1)" + line 425, "pan.___", state 323, "(1)" + line 399, "pan.___", state 360, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 378, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 392, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 424, "(1)" + line 421, "pan.___", state 441, "(1)" + line 425, "pan.___", state 454, "(1)" + line 395, "pan.___", state 483, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 485, "(1)" + line 395, "pan.___", state 486, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 486, "else" + line 395, "pan.___", state 489, "(1)" + line 399, "pan.___", state 497, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 499, "(1)" + line 399, "pan.___", state 500, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 500, "else" + line 399, "pan.___", state 503, "(1)" + line 399, "pan.___", state 504, "(1)" + line 399, "pan.___", state 504, "(1)" + line 397, "pan.___", state 509, "((i<1))" + line 397, "pan.___", state 509, "((i>=1))" + line 404, "pan.___", state 515, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 517, "(1)" + line 404, "pan.___", state 518, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 518, "else" + line 404, "pan.___", state 521, "(1)" + line 404, "pan.___", state 522, "(1)" + line 404, "pan.___", state 522, "(1)" + line 408, "pan.___", state 529, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 531, "(1)" + line 408, "pan.___", state 532, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 532, "else" + line 408, "pan.___", state 535, "(1)" + line 408, "pan.___", state 536, "(1)" + line 408, "pan.___", state 536, "(1)" + line 406, "pan.___", state 541, "((i<2))" + line 406, "pan.___", state 541, "((i>=2))" + line 412, "pan.___", state 548, "(1)" + line 412, "pan.___", state 549, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 549, "else" + line 412, "pan.___", state 552, "(1)" + line 412, "pan.___", state 553, "(1)" + line 412, "pan.___", state 553, "(1)" + line 416, "pan.___", state 561, "(1)" + line 416, "pan.___", state 562, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 562, "else" + line 416, "pan.___", state 565, "(1)" + line 416, "pan.___", state 566, "(1)" + line 416, "pan.___", state 566, "(1)" + line 414, "pan.___", state 571, "((i<1))" + line 414, "pan.___", state 571, "((i>=1))" + line 421, "pan.___", state 578, "(1)" + line 421, "pan.___", state 579, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 579, "else" + line 421, "pan.___", state 582, "(1)" + line 421, "pan.___", state 583, "(1)" + line 421, "pan.___", state 583, "(1)" + line 425, "pan.___", state 591, "(1)" + line 425, "pan.___", state 592, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 592, "else" + line 425, "pan.___", state 595, "(1)" + line 425, "pan.___", state 596, "(1)" + line 425, "pan.___", state 596, "(1)" + line 430, "pan.___", state 605, "(1)" + line 430, "pan.___", state 605, "(1)" + line 395, "pan.___", state 612, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 614, "(1)" + line 395, "pan.___", state 615, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 615, "else" + line 395, "pan.___", state 618, "(1)" + line 399, "pan.___", state 626, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 628, "(1)" + line 399, "pan.___", state 629, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 629, "else" + line 399, "pan.___", state 632, "(1)" + line 399, "pan.___", state 633, "(1)" + line 399, "pan.___", state 633, "(1)" + line 397, "pan.___", state 638, "((i<1))" + line 397, "pan.___", state 638, "((i>=1))" + line 404, "pan.___", state 644, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 646, "(1)" + line 404, "pan.___", state 647, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 647, "else" + line 404, "pan.___", state 650, "(1)" + line 404, "pan.___", state 651, "(1)" + line 404, "pan.___", state 651, "(1)" + line 408, "pan.___", state 658, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 660, "(1)" + line 408, "pan.___", state 661, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 661, "else" + line 408, "pan.___", state 664, "(1)" + line 408, "pan.___", state 665, "(1)" + line 408, "pan.___", state 665, "(1)" + line 406, "pan.___", state 670, "((i<2))" + line 406, "pan.___", state 670, "((i>=2))" + line 412, "pan.___", state 677, "(1)" + line 412, "pan.___", state 678, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 678, "else" + line 412, "pan.___", state 681, "(1)" + line 412, "pan.___", state 682, "(1)" + line 412, "pan.___", state 682, "(1)" + line 416, "pan.___", state 690, "(1)" + line 416, "pan.___", state 691, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 691, "else" + line 416, "pan.___", state 694, "(1)" + line 416, "pan.___", state 695, "(1)" + line 416, "pan.___", state 695, "(1)" + line 414, "pan.___", state 700, "((i<1))" + line 414, "pan.___", state 700, "((i>=1))" + line 421, "pan.___", state 707, "(1)" + line 421, "pan.___", state 708, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 708, "else" + line 421, "pan.___", state 711, "(1)" + line 421, "pan.___", state 712, "(1)" + line 421, "pan.___", state 712, "(1)" + line 425, "pan.___", state 720, "(1)" + line 425, "pan.___", state 721, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 721, "else" + line 425, "pan.___", state 724, "(1)" + line 425, "pan.___", state 725, "(1)" + line 425, "pan.___", state 725, "(1)" + line 423, "pan.___", state 730, "((i<2))" + line 423, "pan.___", state 730, "((i>=2))" + line 430, "pan.___", state 734, "(1)" + line 430, "pan.___", state 734, "(1)" + line 1085, "pan.___", state 738, "_proc_urcu_writer = (_proc_urcu_writer|(1<<10))" + line 395, "pan.___", state 743, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 745, "(1)" + line 395, "pan.___", state 746, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 746, "else" + line 395, "pan.___", state 749, "(1)" + line 399, "pan.___", state 757, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 759, "(1)" + line 399, "pan.___", state 760, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 760, "else" + line 399, "pan.___", state 763, "(1)" + line 399, "pan.___", state 764, "(1)" + line 399, "pan.___", state 764, "(1)" + line 397, "pan.___", state 769, "((i<1))" + line 397, "pan.___", state 769, "((i>=1))" + line 404, "pan.___", state 775, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 777, "(1)" + line 404, "pan.___", state 778, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 778, "else" + line 404, "pan.___", state 781, "(1)" + line 404, "pan.___", state 782, "(1)" + line 404, "pan.___", state 782, "(1)" + line 408, "pan.___", state 789, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 791, "(1)" + line 408, "pan.___", state 792, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 792, "else" + line 408, "pan.___", state 795, "(1)" + line 408, "pan.___", state 796, "(1)" + line 408, "pan.___", state 796, "(1)" + line 406, "pan.___", state 801, "((i<2))" + line 406, "pan.___", state 801, "((i>=2))" + line 412, "pan.___", state 808, "(1)" + line 412, "pan.___", state 809, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 809, "else" + line 412, "pan.___", state 812, "(1)" + line 412, "pan.___", state 813, "(1)" + line 412, "pan.___", state 813, "(1)" + line 416, "pan.___", state 821, "(1)" + line 416, "pan.___", state 822, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 822, "else" + line 416, "pan.___", state 825, "(1)" + line 416, "pan.___", state 826, "(1)" + line 416, "pan.___", state 826, "(1)" + line 414, "pan.___", state 831, "((i<1))" + line 414, "pan.___", state 831, "((i>=1))" + line 421, "pan.___", state 838, "(1)" + line 421, "pan.___", state 839, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 839, "else" + line 421, "pan.___", state 842, "(1)" + line 421, "pan.___", state 843, "(1)" + line 421, "pan.___", state 843, "(1)" + line 425, "pan.___", state 851, "(1)" + line 425, "pan.___", state 852, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 852, "else" + line 425, "pan.___", state 855, "(1)" + line 425, "pan.___", state 856, "(1)" + line 425, "pan.___", state 856, "(1)" + line 423, "pan.___", state 861, "((i<2))" + line 423, "pan.___", state 861, "((i>=2))" + line 430, "pan.___", state 865, "(1)" + line 430, "pan.___", state 865, "(1)" + line 1100, "pan.___", state 870, "_proc_urcu_writer = (_proc_urcu_writer|(1<<11))" + line 1095, "pan.___", state 871, "(((tmp2&((1<<7)-1))&&((tmp2^0)&(1<<7))))" + line 1095, "pan.___", state 871, "else" + line 1120, "pan.___", state 875, "_proc_urcu_writer = (_proc_urcu_writer&~(((1<<12)|(1<<11))))" + line 250, "pan.___", state 906, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 915, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 930, "(1)" + line 262, "pan.___", state 937, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 953, "(1)" + line 231, "pan.___", state 961, "(1)" + line 235, "pan.___", state 973, "(1)" + line 239, "pan.___", state 981, "(1)" + line 250, "pan.___", state 1012, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1021, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1034, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1043, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1059, "(1)" + line 231, "pan.___", state 1067, "(1)" + line 235, "pan.___", state 1079, "(1)" + line 239, "pan.___", state 1087, "(1)" + line 254, "pan.___", state 1113, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1126, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1135, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1151, "(1)" + line 231, "pan.___", state 1159, "(1)" + line 235, "pan.___", state 1171, "(1)" + line 239, "pan.___", state 1179, "(1)" + line 250, "pan.___", state 1210, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1219, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1232, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1241, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1257, "(1)" + line 231, "pan.___", state 1265, "(1)" + line 235, "pan.___", state 1277, "(1)" + line 239, "pan.___", state 1285, "(1)" + line 250, "pan.___", state 1302, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1304, "(1)" + line 254, "pan.___", state 1311, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1313, "(1)" + line 254, "pan.___", state 1314, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1314, "else" + line 252, "pan.___", state 1319, "((i<1))" + line 252, "pan.___", state 1319, "((i>=1))" + line 258, "pan.___", state 1324, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1326, "(1)" + line 258, "pan.___", state 1327, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1327, "else" + line 262, "pan.___", state 1333, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1335, "(1)" + line 262, "pan.___", state 1336, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1336, "else" + line 260, "pan.___", state 1341, "((i<2))" + line 260, "pan.___", state 1341, "((i>=2))" + line 227, "pan.___", state 1349, "(1)" + line 231, "pan.___", state 1357, "(1)" + line 231, "pan.___", state 1358, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1358, "else" + line 229, "pan.___", state 1363, "((i<1))" + line 229, "pan.___", state 1363, "((i>=1))" + line 235, "pan.___", state 1369, "(1)" + line 235, "pan.___", state 1370, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1370, "else" + line 239, "pan.___", state 1377, "(1)" + line 239, "pan.___", state 1378, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1378, "else" + line 244, "pan.___", state 1387, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1387, "else" + line 1196, "pan.___", state 1390, "i = 0" + line 1196, "pan.___", state 1392, "reader_barrier = 1" + line 1196, "pan.___", state 1403, "((i<1))" + line 1196, "pan.___", state 1403, "((i>=1))" + line 250, "pan.___", state 1408, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1410, "(1)" + line 254, "pan.___", state 1417, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1419, "(1)" + line 254, "pan.___", state 1420, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1420, "else" + line 252, "pan.___", state 1425, "((i<1))" + line 252, "pan.___", state 1425, "((i>=1))" + line 258, "pan.___", state 1430, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1432, "(1)" + line 258, "pan.___", state 1433, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1433, "else" + line 262, "pan.___", state 1439, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1441, "(1)" + line 262, "pan.___", state 1442, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1442, "else" + line 260, "pan.___", state 1447, "((i<2))" + line 260, "pan.___", state 1447, "((i>=2))" + line 227, "pan.___", state 1455, "(1)" + line 231, "pan.___", state 1463, "(1)" + line 231, "pan.___", state 1464, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1464, "else" + line 229, "pan.___", state 1469, "((i<1))" + line 229, "pan.___", state 1469, "((i>=1))" + line 235, "pan.___", state 1475, "(1)" + line 235, "pan.___", state 1476, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1476, "else" + line 239, "pan.___", state 1483, "(1)" + line 239, "pan.___", state 1484, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1484, "else" + line 244, "pan.___", state 1493, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1493, "else" + line 277, "pan.___", state 1495, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 1495, "else" + line 1196, "pan.___", state 1496, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 1196, "pan.___", state 1496, "else" + line 254, "pan.___", state 1509, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1522, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1531, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1547, "(1)" + line 231, "pan.___", state 1555, "(1)" + line 235, "pan.___", state 1567, "(1)" + line 239, "pan.___", state 1575, "(1)" + line 250, "pan.___", state 1606, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1615, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1628, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1637, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1653, "(1)" + line 231, "pan.___", state 1661, "(1)" + line 235, "pan.___", state 1673, "(1)" + line 239, "pan.___", state 1681, "(1)" + line 1204, "pan.___", state 1697, "-end-" + (242 of 1697 states) +unreached in proctype :init: + line 1215, "pan.___", state 9, "((j<2))" + line 1215, "pan.___", state 9, "((j>=2))" + line 1216, "pan.___", state 20, "((j<2))" + line 1216, "pan.___", state 20, "((j>=2))" + line 1221, "pan.___", state 33, "((j<2))" + line 1221, "pan.___", state 33, "((j>=2))" + line 1219, "pan.___", state 43, "((i<1))" + line 1219, "pan.___", state 43, "((i>=1))" + line 1229, "pan.___", state 54, "((j<2))" + line 1229, "pan.___", state 54, "((j>=2))" + line 1233, "pan.___", state 67, "((j<2))" + line 1233, "pan.___", state 67, "((j>=2))" + (6 of 78 states) +unreached in proctype :never: + line 1263, "pan.___", state 8, "-end-" + (1 of 8 states) + +pan: elapsed time 1.47e+03 seconds +pan: rate 4207.2476 states/second +pan: avg transition delay 1.3064e-06 usec +cp .input.spin urcu_free_single_flip.spin.input +cp .input.spin.trail urcu_free_single_flip.spin.input.trail diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free_single_flip.spin.input b/formal-model/results/urcu-controldataflow-ipi/urcu_free_single_flip.spin.input new file mode 100644 index 0000000..e7c3890 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free_single_flip.spin.input @@ -0,0 +1,1240 @@ +#define SINGLE_FLIP + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_free_single_flip.spin.input.trail b/formal-model/results/urcu-controldataflow-ipi/urcu_free_single_flip.spin.input.trail new file mode 100644 index 0000000..f09d0eb --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_free_single_flip.spin.input.trail @@ -0,0 +1,1386 @@ +-2:3:-2 +-4:-4:-4 +1:0:4646 +2:3:4566 +3:3:4569 +4:3:4569 +5:3:4572 +6:3:4580 +7:3:4580 +8:3:4583 +9:3:4589 +10:3:4593 +11:3:4593 +12:3:4596 +13:3:4606 +14:3:4614 +15:3:4614 +16:3:4617 +17:3:4623 +18:3:4627 +19:3:4627 +20:3:4630 +21:3:4636 +22:3:4640 +23:3:4641 +24:0:4646 +25:3:4643 +26:0:4646 +27:2:2871 +28:0:4646 +29:2:2877 +30:0:4646 +31:2:2878 +32:0:4646 +33:2:2880 +34:0:4646 +35:2:2881 +36:0:4646 +37:2:2882 +38:0:4646 +39:2:2883 +40:0:4646 +41:2:2884 +42:0:4646 +43:2:2885 +44:0:4646 +45:2:2886 +46:2:2887 +47:2:2891 +48:2:2892 +49:2:2900 +50:2:2901 +51:2:2905 +52:2:2906 +53:2:2914 +54:2:2919 +55:2:2923 +56:2:2924 +57:2:2932 +58:2:2933 +59:2:2937 +60:2:2938 +61:2:2932 +62:2:2933 +63:2:2937 +64:2:2938 +65:2:2946 +66:2:2951 +67:2:2952 +68:2:2963 +69:2:2964 +70:2:2965 +71:2:2976 +72:2:2981 +73:2:2982 +74:2:2993 +75:2:2994 +76:2:2995 +77:2:2993 +78:2:2994 +79:2:2995 +80:2:3006 +81:2:3014 +82:0:4646 +83:2:2885 +84:0:4646 +85:2:3018 +86:2:3022 +87:2:3023 +88:2:3027 +89:2:3031 +90:2:3032 +91:2:3036 +92:2:3044 +93:2:3045 +94:2:3049 +95:2:3053 +96:2:3054 +97:2:3049 +98:2:3050 +99:2:3058 +100:0:4646 +101:2:2885 +102:0:4646 +103:2:3066 +104:2:3067 +105:2:3068 +106:0:4646 +107:2:2885 +108:0:4646 +109:2:3073 +110:0:4646 +111:2:3775 +112:2:3776 +113:2:3780 +114:2:3784 +115:2:3785 +116:2:3789 +117:2:3794 +118:2:3802 +119:2:3806 +120:2:3807 +121:2:3802 +122:2:3806 +123:2:3807 +124:2:3811 +125:2:3818 +126:2:3825 +127:2:3826 +128:2:3833 +129:2:3838 +130:2:3845 +131:2:3846 +132:2:3845 +133:2:3846 +134:2:3853 +135:2:3857 +136:0:4646 +137:2:3862 +138:0:4646 +139:2:3863 +140:0:4646 +141:2:3864 +142:0:4646 +143:2:3865 +144:0:4646 +145:1:2 +146:0:4646 +147:2:3866 +148:0:4646 +149:1:8 +150:0:4646 +151:1:9 +152:0:4646 +153:2:3865 +154:0:4646 +155:1:10 +156:0:4646 +157:2:3866 +158:0:4646 +159:1:11 +160:0:4646 +161:2:3865 +162:0:4646 +163:1:12 +164:0:4646 +165:2:3866 +166:0:4646 +167:1:13 +168:0:4646 +169:2:3865 +170:0:4646 +171:1:14 +172:0:4646 +173:2:3866 +174:0:4646 +175:1:15 +176:0:4646 +177:1:16 +178:0:4646 +179:2:3865 +180:0:4646 +181:1:17 +182:0:4646 +183:2:3866 +184:0:4646 +185:1:26 +186:0:4646 +187:2:3865 +188:0:4646 +189:1:30 +190:1:31 +191:1:35 +192:1:39 +193:1:40 +194:1:44 +195:1:52 +196:1:53 +197:1:57 +198:1:61 +199:1:62 +200:1:57 +201:1:61 +202:1:62 +203:1:66 +204:1:73 +205:1:80 +206:1:81 +207:1:88 +208:1:93 +209:1:100 +210:1:101 +211:1:100 +212:1:101 +213:1:108 +214:1:112 +215:0:4646 +216:2:3866 +217:0:4646 +218:1:117 +219:0:4646 +220:2:3867 +221:0:4646 +222:2:3872 +223:0:4646 +224:2:3873 +225:0:4646 +226:2:3881 +227:2:3882 +228:2:3886 +229:2:3890 +230:2:3891 +231:2:3895 +232:2:3903 +233:2:3904 +234:2:3908 +235:2:3912 +236:2:3913 +237:2:3908 +238:2:3912 +239:2:3913 +240:2:3917 +241:2:3924 +242:2:3931 +243:2:3932 +244:2:3939 +245:2:3944 +246:2:3951 +247:2:3952 +248:2:3951 +249:2:3952 +250:2:3959 +251:2:3963 +252:0:4646 +253:2:3075 +254:2:3756 +255:0:4646 +256:2:2885 +257:0:4646 +258:2:3076 +259:0:4646 +260:2:2885 +261:0:4646 +262:2:3079 +263:2:3080 +264:2:3084 +265:2:3085 +266:2:3093 +267:2:3094 +268:2:3098 +269:2:3099 +270:2:3107 +271:2:3112 +272:2:3116 +273:2:3117 +274:2:3125 +275:2:3126 +276:2:3130 +277:2:3131 +278:2:3125 +279:2:3126 +280:2:3130 +281:2:3131 +282:2:3139 +283:2:3144 +284:2:3145 +285:2:3156 +286:2:3157 +287:2:3158 +288:2:3169 +289:2:3174 +290:2:3175 +291:2:3186 +292:2:3187 +293:2:3188 +294:2:3186 +295:2:3187 +296:2:3188 +297:2:3199 +298:2:3206 +299:0:4646 +300:2:2885 +301:0:4646 +302:2:3210 +303:2:3211 +304:2:3212 +305:2:3224 +306:2:3225 +307:2:3229 +308:2:3230 +309:2:3238 +310:2:3243 +311:2:3247 +312:2:3248 +313:2:3256 +314:2:3257 +315:2:3261 +316:2:3262 +317:2:3256 +318:2:3257 +319:2:3261 +320:2:3262 +321:2:3270 +322:2:3275 +323:2:3276 +324:2:3287 +325:2:3288 +326:2:3289 +327:2:3300 +328:2:3305 +329:2:3306 +330:2:3317 +331:2:3318 +332:2:3319 +333:2:3317 +334:2:3318 +335:2:3319 +336:2:3330 +337:2:3340 +338:2:3341 +339:0:4646 +340:2:2885 +341:0:4646 +342:2:3744 +343:0:4646 +344:2:4369 +345:2:4370 +346:2:4374 +347:2:4378 +348:2:4379 +349:2:4383 +350:2:4391 +351:2:4392 +352:2:4396 +353:2:4400 +354:2:4401 +355:2:4396 +356:2:4400 +357:2:4401 +358:2:4405 +359:2:4412 +360:2:4419 +361:2:4420 +362:2:4427 +363:2:4432 +364:2:4439 +365:2:4440 +366:2:4439 +367:2:4440 +368:2:4447 +369:2:4451 +370:0:4646 +371:2:4456 +372:0:4646 +373:2:4457 +374:0:4646 +375:2:4458 +376:0:4646 +377:2:4459 +378:0:4646 +379:1:118 +380:0:4646 +381:2:4460 +382:0:4646 +383:1:120 +384:0:4646 +385:2:4459 +386:0:4646 +387:1:19 +388:0:4646 +389:2:4460 +390:0:4646 +391:1:126 +392:1:127 +393:1:131 +394:1:132 +395:1:140 +396:1:141 +397:1:145 +398:1:146 +399:1:154 +400:1:159 +401:1:163 +402:1:164 +403:1:172 +404:1:173 +405:1:177 +406:1:178 +407:1:172 +408:1:173 +409:1:177 +410:1:178 +411:1:186 +412:1:198 +413:1:199 +414:1:203 +415:1:204 +416:1:205 +417:1:216 +418:1:221 +419:1:222 +420:1:233 +421:1:234 +422:1:235 +423:1:233 +424:1:234 +425:1:235 +426:1:246 +427:0:4646 +428:1:15 +429:0:4646 +430:1:16 +431:0:4646 +432:2:4459 +433:0:4646 +434:1:17 +435:0:4646 +436:2:4460 +437:0:4646 +438:1:118 +439:0:4646 +440:1:120 +441:0:4646 +442:2:4459 +443:0:4646 +444:1:19 +445:0:4646 +446:2:4460 +447:0:4646 +448:1:255 +449:1:256 +450:0:4646 +451:1:15 +452:0:4646 +453:1:16 +454:0:4646 +455:2:4459 +456:0:4646 +457:1:17 +458:0:4646 +459:2:4460 +460:0:4646 +461:1:118 +462:0:4646 +463:1:120 +464:0:4646 +465:2:4459 +466:0:4646 +467:1:19 +468:0:4646 +469:2:4460 +470:0:4646 +471:1:262 +472:1:263 +473:1:267 +474:1:268 +475:1:276 +476:1:277 +477:1:281 +478:1:282 +479:1:290 +480:1:295 +481:1:299 +482:1:300 +483:1:308 +484:1:309 +485:1:313 +486:1:314 +487:1:308 +488:1:309 +489:1:313 +490:1:314 +491:1:322 +492:1:334 +493:1:335 +494:1:339 +495:1:340 +496:1:341 +497:1:352 +498:1:357 +499:1:358 +500:1:369 +501:1:370 +502:1:371 +503:1:369 +504:1:370 +505:1:371 +506:1:382 +507:0:4646 +508:1:15 +509:0:4646 +510:1:16 +511:0:4646 +512:2:4459 +513:0:4646 +514:1:17 +515:0:4646 +516:2:4460 +517:0:4646 +518:1:26 +519:0:4646 +520:2:4459 +521:0:4646 +522:1:30 +523:1:31 +524:1:35 +525:1:39 +526:1:40 +527:1:44 +528:1:52 +529:1:53 +530:1:57 +531:1:61 +532:1:62 +533:1:57 +534:1:61 +535:1:62 +536:1:66 +537:1:73 +538:1:80 +539:1:81 +540:1:88 +541:1:93 +542:1:100 +543:1:101 +544:1:100 +545:1:101 +546:1:108 +547:1:112 +548:0:4646 +549:2:4460 +550:0:4646 +551:1:117 +552:0:4646 +553:2:4461 +554:0:4646 +555:2:4466 +556:0:4646 +557:2:4467 +558:0:4646 +559:2:4475 +560:2:4476 +561:2:4480 +562:2:4484 +563:2:4485 +564:2:4489 +565:2:4497 +566:2:4498 +567:2:4502 +568:2:4506 +569:2:4507 +570:2:4502 +571:2:4506 +572:2:4507 +573:2:4511 +574:2:4518 +575:2:4525 +576:2:4526 +577:2:4533 +578:2:4538 +579:2:4545 +580:2:4546 +581:2:4545 +582:2:4546 +583:2:4553 +584:2:4557 +585:0:4646 +586:2:3746 +587:2:3756 +588:0:4646 +589:2:2885 +590:0:4646 +591:2:3747 +592:2:3748 +593:0:4646 +594:2:2885 +595:0:4646 +596:2:3752 +597:0:4646 +598:2:3760 +599:0:4646 +600:2:2878 +601:0:4646 +602:2:2880 +603:0:4646 +604:2:2881 +605:0:4646 +606:2:2882 +607:0:4646 +608:2:2883 +609:0:4646 +610:2:2884 +611:0:4646 +612:2:2885 +613:0:4646 +614:2:2886 +615:2:2887 +616:2:2891 +617:2:2892 +618:2:2900 +619:2:2901 +620:2:2905 +621:2:2906 +622:2:2914 +623:2:2919 +624:2:2923 +625:2:2924 +626:2:2932 +627:2:2933 +628:2:2934 +629:2:2932 +630:2:2933 +631:2:2937 +632:2:2938 +633:2:2946 +634:2:2951 +635:2:2952 +636:2:2963 +637:2:2964 +638:2:2965 +639:2:2976 +640:2:2981 +641:2:2982 +642:2:2993 +643:2:2994 +644:2:2995 +645:2:2993 +646:2:2994 +647:2:2995 +648:2:3006 +649:2:3014 +650:0:4646 +651:2:2885 +652:0:4646 +653:2:3018 +654:2:3022 +655:2:3023 +656:2:3027 +657:2:3031 +658:2:3032 +659:2:3036 +660:2:3044 +661:2:3045 +662:2:3049 +663:2:3050 +664:2:3049 +665:2:3053 +666:2:3054 +667:2:3058 +668:0:4646 +669:2:2885 +670:0:4646 +671:2:3066 +672:2:3067 +673:2:3068 +674:0:4646 +675:2:2885 +676:0:4646 +677:2:3073 +678:0:4646 +679:2:3775 +680:2:3776 +681:2:3780 +682:2:3784 +683:2:3785 +684:2:3789 +685:2:3794 +686:2:3802 +687:2:3806 +688:2:3807 +689:2:3802 +690:2:3806 +691:2:3807 +692:2:3811 +693:2:3818 +694:2:3825 +695:2:3826 +696:2:3833 +697:2:3838 +698:2:3845 +699:2:3846 +700:2:3845 +701:2:3846 +702:2:3853 +703:2:3857 +704:0:4646 +705:2:3862 +706:0:4646 +707:2:3863 +708:0:4646 +709:2:3864 +710:0:4646 +711:2:3865 +712:0:4646 +713:1:118 +714:0:4646 +715:2:3866 +716:0:4646 +717:1:120 +718:0:4646 +719:2:3865 +720:0:4646 +721:1:19 +722:0:4646 +723:2:3866 +724:0:4646 +725:1:391 +726:1:392 +727:1:396 +728:1:397 +729:1:405 +730:1:406 +731:1:410 +732:1:411 +733:1:419 +734:1:424 +735:1:428 +736:1:429 +737:1:437 +738:1:438 +739:1:442 +740:1:443 +741:1:437 +742:1:438 +743:1:442 +744:1:443 +745:1:451 +746:1:456 +747:1:457 +748:1:468 +749:1:469 +750:1:470 +751:1:481 +752:1:493 +753:1:494 +754:1:498 +755:1:499 +756:1:500 +757:1:498 +758:1:499 +759:1:500 +760:1:511 +761:1:518 +762:0:4646 +763:1:15 +764:0:4646 +765:1:16 +766:0:4646 +767:2:3865 +768:0:4646 +769:1:17 +770:0:4646 +771:2:3866 +772:0:4646 +773:1:118 +774:0:4646 +775:1:120 +776:0:4646 +777:2:3865 +778:0:4646 +779:1:19 +780:0:4646 +781:2:3866 +782:0:4646 +783:1:656 +784:1:657 +785:1:661 +786:1:662 +787:1:670 +788:1:671 +789:1:672 +790:1:684 +791:1:689 +792:1:693 +793:1:694 +794:1:702 +795:1:703 +796:1:707 +797:1:708 +798:1:702 +799:1:703 +800:1:707 +801:1:708 +802:1:716 +803:1:721 +804:1:722 +805:1:733 +806:1:734 +807:1:735 +808:1:746 +809:1:758 +810:1:759 +811:1:763 +812:1:764 +813:1:765 +814:1:763 +815:1:764 +816:1:765 +817:1:776 +818:0:4646 +819:1:15 +820:0:4646 +821:1:16 +822:0:4646 +823:2:3865 +824:0:4646 +825:1:17 +826:0:4646 +827:2:3866 +828:0:4646 +829:1:118 +830:0:4646 +831:1:120 +832:0:4646 +833:2:3865 +834:0:4646 +835:1:19 +836:0:4646 +837:2:3866 +838:0:4646 +839:1:785 +840:1:788 +841:1:789 +842:0:4646 +843:1:15 +844:0:4646 +845:1:16 +846:0:4646 +847:2:3865 +848:0:4646 +849:1:17 +850:0:4646 +851:2:3866 +852:0:4646 +853:1:118 +854:0:4646 +855:1:120 +856:0:4646 +857:2:3865 +858:0:4646 +859:1:19 +860:0:4646 +861:2:3866 +862:0:4646 +863:1:1052 +864:1:1053 +865:1:1057 +866:1:1058 +867:1:1066 +868:1:1067 +869:1:1071 +870:1:1072 +871:1:1080 +872:1:1085 +873:1:1089 +874:1:1090 +875:1:1098 +876:1:1099 +877:1:1103 +878:1:1104 +879:1:1098 +880:1:1099 +881:1:1103 +882:1:1104 +883:1:1112 +884:1:1117 +885:1:1118 +886:1:1129 +887:1:1130 +888:1:1131 +889:1:1142 +890:1:1154 +891:1:1155 +892:1:1159 +893:1:1160 +894:1:1161 +895:1:1159 +896:1:1160 +897:1:1161 +898:1:1172 +899:1:1179 +900:1:1183 +901:0:4646 +902:1:15 +903:0:4646 +904:1:16 +905:0:4646 +906:2:3865 +907:0:4646 +908:1:17 +909:0:4646 +910:2:3866 +911:0:4646 +912:1:118 +913:0:4646 +914:1:120 +915:0:4646 +916:2:3865 +917:0:4646 +918:1:19 +919:0:4646 +920:2:3866 +921:0:4646 +922:1:1184 +923:1:1185 +924:1:1189 +925:1:1190 +926:1:1198 +927:1:1199 +928:1:1200 +929:1:1212 +930:1:1217 +931:1:1221 +932:1:1222 +933:1:1230 +934:1:1231 +935:1:1235 +936:1:1236 +937:1:1230 +938:1:1231 +939:1:1235 +940:1:1236 +941:1:1244 +942:1:1249 +943:1:1250 +944:1:1261 +945:1:1262 +946:1:1263 +947:1:1274 +948:1:1286 +949:1:1287 +950:1:1291 +951:1:1292 +952:1:1293 +953:1:1291 +954:1:1292 +955:1:1293 +956:1:1304 +957:0:4646 +958:1:15 +959:0:4646 +960:1:16 +961:0:4646 +962:2:3865 +963:0:4646 +964:1:17 +965:0:4646 +966:2:3866 +967:0:4646 +968:1:26 +969:0:4646 +970:2:3865 +971:0:4646 +972:1:30 +973:1:31 +974:1:35 +975:1:39 +976:1:40 +977:1:44 +978:1:52 +979:1:53 +980:1:57 +981:1:61 +982:1:62 +983:1:57 +984:1:61 +985:1:62 +986:1:66 +987:1:73 +988:1:80 +989:1:81 +990:1:88 +991:1:93 +992:1:100 +993:1:101 +994:1:100 +995:1:101 +996:1:108 +997:1:112 +998:0:4646 +999:2:3866 +1000:0:4646 +1001:1:117 +1002:0:4646 +1003:2:3867 +1004:0:4646 +1005:2:3872 +1006:0:4646 +1007:2:3873 +1008:0:4646 +1009:2:3881 +1010:2:3882 +1011:2:3886 +1012:2:3890 +1013:2:3891 +1014:2:3895 +1015:2:3903 +1016:2:3904 +1017:2:3908 +1018:2:3912 +1019:2:3913 +1020:2:3908 +1021:2:3912 +1022:2:3913 +1023:2:3917 +1024:2:3924 +1025:2:3931 +1026:2:3932 +1027:2:3939 +1028:2:3944 +1029:2:3951 +1030:2:3952 +1031:2:3951 +1032:2:3952 +1033:2:3959 +1034:2:3963 +1035:0:4646 +1036:2:3075 +1037:2:3756 +1038:0:4646 +1039:2:2885 +1040:0:4646 +1041:2:3076 +1042:0:4646 +1043:2:2885 +1044:0:4646 +1045:2:3079 +1046:2:3080 +1047:2:3084 +1048:2:3085 +1049:2:3093 +1050:2:3094 +1051:2:3098 +1052:2:3099 +1053:2:3107 +1054:2:3112 +1055:2:3116 +1056:2:3117 +1057:2:3125 +1058:2:3126 +1059:2:3130 +1060:2:3131 +1061:2:3125 +1062:2:3126 +1063:2:3130 +1064:2:3131 +1065:2:3139 +1066:2:3144 +1067:2:3145 +1068:2:3156 +1069:2:3157 +1070:2:3158 +1071:2:3169 +1072:2:3174 +1073:2:3175 +1074:2:3186 +1075:2:3187 +1076:2:3188 +1077:2:3186 +1078:2:3187 +1079:2:3188 +1080:2:3199 +1081:2:3206 +1082:0:4646 +1083:2:2885 +1084:0:4646 +1085:2:3210 +1086:2:3211 +1087:2:3212 +1088:2:3224 +1089:2:3225 +1090:2:3229 +1091:2:3230 +1092:2:3238 +1093:2:3243 +1094:2:3247 +1095:2:3248 +1096:2:3256 +1097:2:3257 +1098:2:3261 +1099:2:3262 +1100:2:3256 +1101:2:3257 +1102:2:3261 +1103:2:3262 +1104:2:3270 +1105:2:3275 +1106:2:3276 +1107:2:3287 +1108:2:3288 +1109:2:3289 +1110:2:3300 +1111:2:3305 +1112:2:3306 +1113:2:3317 +1114:2:3318 +1115:2:3319 +1116:2:3317 +1117:2:3318 +1118:2:3319 +1119:2:3330 +1120:2:3340 +1121:2:3341 +1122:0:4646 +1123:2:2885 +1124:0:4646 +1125:2:3744 +1126:0:4646 +1127:2:4369 +1128:2:4370 +1129:2:4374 +1130:2:4378 +1131:2:4379 +1132:2:4383 +1133:2:4391 +1134:2:4392 +1135:2:4396 +1136:2:4400 +1137:2:4401 +1138:2:4396 +1139:2:4400 +1140:2:4401 +1141:2:4405 +1142:2:4412 +1143:2:4419 +1144:2:4420 +1145:2:4427 +1146:2:4432 +1147:2:4439 +1148:2:4440 +1149:2:4439 +1150:2:4440 +1151:2:4447 +1152:2:4451 +1153:0:4646 +1154:2:4456 +1155:0:4646 +1156:2:4457 +1157:0:4646 +1158:2:4458 +1159:0:4646 +1160:2:4459 +1161:0:4646 +1162:1:26 +1163:0:4646 +1164:2:4460 +1165:0:4646 +1166:1:30 +1167:1:31 +1168:1:35 +1169:1:39 +1170:1:40 +1171:1:44 +1172:1:52 +1173:1:53 +1174:1:57 +1175:1:61 +1176:1:62 +1177:1:57 +1178:1:61 +1179:1:62 +1180:1:66 +1181:1:73 +1182:1:80 +1183:1:81 +1184:1:88 +1185:1:93 +1186:1:100 +1187:1:101 +1188:1:100 +1189:1:101 +1190:1:108 +1191:1:112 +1192:0:4646 +1193:2:4459 +1194:0:4646 +1195:1:117 +1196:0:4646 +1197:2:4460 +1198:0:4646 +1199:2:4461 +1200:0:4646 +1201:2:4466 +1202:0:4646 +1203:2:4467 +1204:0:4646 +1205:2:4475 +1206:2:4476 +1207:2:4480 +1208:2:4484 +1209:2:4485 +1210:2:4489 +1211:2:4497 +1212:2:4498 +1213:2:4502 +1214:2:4506 +1215:2:4507 +1216:2:4502 +1217:2:4506 +1218:2:4507 +1219:2:4511 +1220:2:4518 +1221:2:4525 +1222:2:4526 +1223:2:4533 +1224:2:4538 +1225:2:4545 +1226:2:4546 +1227:2:4545 +1228:2:4546 +1229:2:4553 +1230:2:4557 +1231:0:4646 +1232:2:3746 +1233:2:3756 +1234:0:4646 +1235:2:2885 +1236:0:4646 +1237:2:3747 +1238:2:3748 +1239:0:4646 +1240:2:2885 +1241:0:4646 +1242:2:3752 +1243:0:4646 +1244:2:3760 +1245:0:4646 +1246:2:2878 +1247:0:4646 +1248:2:2880 +1249:0:4646 +1250:2:2881 +1251:0:4646 +1252:2:2882 +1253:0:4646 +1254:2:2883 +1255:0:4646 +1256:2:2884 +1257:0:4646 +1258:2:2885 +1259:0:4646 +1260:2:2886 +1261:2:2887 +1262:2:2891 +1263:2:2892 +1264:2:2900 +1265:2:2901 +1266:2:2905 +1267:2:2906 +1268:2:2914 +1269:2:2919 +1270:2:2923 +1271:2:2924 +1272:2:2932 +1273:2:2933 +1274:2:2937 +1275:2:2938 +1276:2:2932 +1277:2:2933 +1278:2:2934 +1279:2:2946 +1280:2:2951 +1281:2:2952 +1282:2:2963 +1283:2:2964 +1284:2:2965 +1285:2:2976 +1286:2:2981 +1287:2:2982 +1288:2:2993 +1289:2:2994 +1290:2:2995 +1291:2:2993 +1292:2:2994 +1293:2:2995 +1294:2:3006 +1295:2:3014 +1296:0:4646 +1297:2:2885 +1298:0:4646 +1299:1:118 +1300:0:4646 +1301:1:120 +1302:0:4646 +1303:1:19 +1304:0:4646 +1305:1:1313 +1306:0:4646 +1307:1:2777 +1308:1:2784 +1309:1:2785 +1310:1:2792 +1311:1:2797 +1312:1:2804 +1313:1:2805 +1314:1:2804 +1315:1:2805 +1316:1:2812 +1317:1:2816 +1318:0:4646 +1319:2:3018 +1320:2:3022 +1321:2:3023 +1322:2:3027 +1323:2:3031 +1324:2:3032 +1325:2:3036 +1326:2:3044 +1327:2:3045 +1328:2:3049 +1329:2:3053 +1330:2:3054 +1331:2:3049 +1332:2:3050 +1333:2:3058 +1334:0:4646 +1335:2:2885 +1336:0:4646 +1337:2:3066 +1338:2:3067 +1339:2:3068 +1340:0:4646 +1341:2:2885 +1342:0:4646 +1343:2:3073 +1344:0:4646 +1345:2:3775 +1346:2:3776 +1347:2:3780 +1348:2:3784 +1349:2:3785 +1350:2:3789 +1351:2:3794 +1352:2:3802 +1353:2:3806 +1354:2:3807 +1355:2:3802 +1356:2:3806 +1357:2:3807 +1358:2:3811 +1359:2:3818 +1360:2:3825 +1361:2:3826 +1362:2:3833 +1363:2:3838 +1364:2:3845 +1365:2:3846 +1366:2:3845 +1367:2:3846 +1368:2:3853 +1369:2:3857 +1370:0:4646 +1371:2:3862 +1372:0:4646 +1373:2:3863 +1374:0:4646 +1375:2:3864 +1376:0:4646 +1377:2:3865 +1378:0:4646 +1379:1:1315 +1380:1:1316 +1381:0:4644 +1382:2:3866 +1383:0:4650 +1384:1:2431 diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_progress.ltl b/formal-model/results/urcu-controldataflow-ipi/urcu_progress.ltl new file mode 100644 index 0000000..8718641 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_progress.ltl @@ -0,0 +1 @@ +([] <> !np_) diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_progress_reader.define b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_reader.define new file mode 100644 index 0000000..ff3f783 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_reader.define @@ -0,0 +1 @@ +#define READER_PROGRESS diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_progress_reader.log b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_reader.log new file mode 100644 index 0000000..e493a0c --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_reader.log @@ -0,0 +1,597 @@ +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define > pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_progress.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_progress_reader.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -f -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1258) +depth 23: Claim reached state 9 (line 1263) +depth 137: Claim reached state 9 (line 1262) +Depth= 31896 States= 1e+06 Transitions= 1.91e+08 Memory= 519.963 t= 240 R= 4e+03 +Depth= 35611 States= 2e+06 Transitions= 3.82e+08 Memory= 572.111 t= 484 R= 4e+03 +Depth= 35611 States= 3e+06 Transitions= 6.15e+08 Memory= 623.869 t= 790 R= 4e+03 +pan: resizing hashtable to -w22.. done +Depth= 35611 States= 4e+06 Transitions= 8.15e+08 Memory= 707.236 t= 1.04e+03 R= 4e+03 +Depth= 35611 States= 5e+06 Transitions= 1e+09 Memory= 760.557 t= 1.28e+03 R= 4e+03 +Depth= 35611 States= 6e+06 Transitions= 1.33e+09 Memory= 808.408 t= 1.71e+03 R= 4e+03 +Depth= 35611 States= 7e+06 Transitions= 1.79e+09 Memory= 854.014 t= 2.32e+03 R= 3e+03 +Depth= 35611 States= 8e+06 Transitions= 2.33e+09 Memory= 898.740 t= 3.05e+03 R= 3e+03 +Depth= 35611 States= 9e+06 Transitions= 2.72e+09 Memory= 947.276 t= 3.57e+03 R= 3e+03 +pan: resizing hashtable to -w24.. done +Depth= 35611 States= 1e+07 Transitions= 3.17e+09 Memory= 1119.123 t= 4.17e+03 R= 2e+03 +Depth= 35611 States= 1.1e+07 Transitions= 3.43e+09 Memory= 1167.854 t= 4.5e+03 R= 2e+03 +Depth= 35611 States= 1.2e+07 Transitions= 3.67e+09 Memory= 1219.221 t= 4.81e+03 R= 2e+03 +Depth= 35611 States= 1.3e+07 Transitions= 4.19e+09 Memory= 1262.776 t= 5.49e+03 R= 2e+03 +Depth= 35611 States= 1.4e+07 Transitions= 5.17e+09 Memory= 1311.213 t= 6.83e+03 R= 2e+03 +Depth= 35611 States= 1.5e+07 Transitions= 6.13e+09 Memory= 1349.006 t= 8.12e+03 R= 2e+03 +Depth= 35611 States= 1.6e+07 Transitions= 6.65e+09 Memory= 1393.635 t= 8.82e+03 R= 2e+03 +Depth= 35611 States= 1.7e+07 Transitions= 7.12e+09 Memory= 1441.779 t= 9.45e+03 R= 2e+03 +Depth= 35611 States= 1.8e+07 Transitions= 7.52e+09 Memory= 1486.408 t= 9.98e+03 R= 2e+03 +Depth= 35611 States= 1.9e+07 Transitions= 8.03e+09 Memory= 1534.162 t= 1.07e+04 R= 2e+03 +Depth= 35611 States= 2e+07 Transitions= 8.6e+09 Memory= 1579.768 t= 1.14e+04 R= 2e+03 +Depth= 35611 States= 2.1e+07 Transitions= 9e+09 Memory= 1629.475 t= 1.2e+04 R= 2e+03 +Depth= 35611 States= 2.2e+07 Transitions= 9.32e+09 Memory= 1676.545 t= 1.24e+04 R= 2e+03 +Depth= 35611 States= 2.3e+07 Transitions= 9.66e+09 Memory= 1724.494 t= 1.29e+04 R= 2e+03 +Depth= 35611 States= 2.4e+07 Transitions= 1e+10 Memory= 1774.299 t= 1.34e+04 R= 2e+03 +Depth= 35611 States= 2.5e+07 Transitions= 1.03e+10 Memory= 1822.151 t= 1.37e+04 R= 2e+03 +Depth= 35611 States= 2.6e+07 Transitions= 1.07e+10 Memory= 1871.272 t= 1.42e+04 R= 2e+03 +Depth= 35611 States= 2.7e+07 Transitions= 1.09e+10 Memory= 1921.272 t= 1.45e+04 R= 2e+03 +Depth= 35611 States= 2.8e+07 Transitions= 1.13e+10 Memory= 1969.904 t= 1.51e+04 R= 2e+03 +Depth= 35611 States= 2.9e+07 Transitions= 1.15e+10 Memory= 2019.709 t= 1.54e+04 R= 2e+03 +Depth= 35611 States= 3e+07 Transitions= 1.2e+10 Memory= 2063.654 t= 1.6e+04 R= 2e+03 +Depth= 35611 States= 3.1e+07 Transitions= 1.23e+10 Memory= 2110.920 t= 1.65e+04 R= 2e+03 +Depth= 35611 States= 3.2e+07 Transitions= 1.29e+10 Memory= 2156.721 t= 1.73e+04 R= 2e+03 +Depth= 35611 States= 3.3e+07 Transitions= 1.35e+10 Memory= 2200.276 t= 1.8e+04 R= 2e+03 +Depth= 35611 States= 3.4e+07 Transitions= 1.4e+10 Memory= 2245.881 t= 1.87e+04 R= 2e+03 +pan: resizing hashtable to -w26.. done +Depth= 35611 States= 3.5e+07 Transitions= 1.43e+10 Memory= 2790.498 t= 1.91e+04 R= 2e+03 +Depth= 35611 States= 3.6e+07 Transitions= 1.45e+10 Memory= 2841.182 t= 1.94e+04 R= 2e+03 +Depth= 35611 States= 3.7e+07 Transitions= 1.49e+10 Memory= 2887.861 t= 1.99e+04 R= 2e+03 +Depth= 35611 States= 3.8e+07 Transitions= 1.57e+10 Memory= 2934.346 t= 2.1e+04 R= 2e+03 +Depth= 35611 States= 3.9e+07 Transitions= 1.67e+10 Memory= 2977.608 t= 2.23e+04 R= 2e+03 +Depth= 35611 States= 4e+07 Transitions= 1.74e+10 Memory= 3017.158 t= 2.33e+04 R= 2e+03 +Depth= 35611 States= 4.1e+07 Transitions= 1.81e+10 Memory= 3061.104 t= 2.42e+04 R= 2e+03 +Depth= 35611 States= 4.2e+07 Transitions= 1.83e+10 Memory= 3109.932 t= 2.45e+04 R= 2e+03 +Depth= 35611 States= 4.3e+07 Transitions= 1.88e+10 Memory= 3156.416 t= 2.51e+04 R= 2e+03 +Depth= 35611 States= 4.4e+07 Transitions= 1.93e+10 Memory= 3203.389 t= 2.58e+04 R= 2e+03 +Depth= 35611 States= 4.5e+07 Transitions= 1.98e+10 Memory= 3249.580 t= 2.65e+04 R= 2e+03 +Depth= 35611 States= 4.6e+07 Transitions= 2.02e+10 Memory= 3297.920 t= 2.69e+04 R= 2e+03 +Depth= 35611 States= 4.7e+07 Transitions= 2.06e+10 Memory= 3347.236 t= 2.75e+04 R= 2e+03 +Depth= 35611 States= 4.8e+07 Transitions= 2.09e+10 Memory= 3395.772 t= 2.79e+04 R= 2e+03 +Depth= 35611 States= 4.9e+07 Transitions= 2.12e+10 Memory= 3443.818 t= 2.83e+04 R= 2e+03 +Depth= 35611 States= 5e+07 Transitions= 2.15e+10 Memory= 3492.549 t= 2.87e+04 R= 2e+03 +Depth= 35611 States= 5.1e+07 Transitions= 2.18e+10 Memory= 3540.303 t= 2.91e+04 R= 2e+03 +Depth= 35611 States= 5.2e+07 Transitions= 2.21e+10 Memory= 3591.377 t= 2.95e+04 R= 2e+03 +Depth= 35611 States= 5.3e+07 Transitions= 2.24e+10 Memory= 3639.326 t= 3e+04 R= 2e+03 +Depth= 35611 States= 5.4e+07 Transitions= 2.27e+10 Memory= 3687.373 t= 3.04e+04 R= 2e+03 +Depth= 35611 States= 5.5e+07 Transitions= 2.31e+10 Memory= 3733.662 t= 3.09e+04 R= 2e+03 +Depth= 35611 States= 5.6e+07 Transitions= 2.37e+10 Memory= 3779.561 t= 3.16e+04 R= 2e+03 +Depth= 35611 States= 5.7e+07 Transitions= 2.42e+10 Memory= 3823.213 t= 3.24e+04 R= 2e+03 +Depth= 35611 States= 5.8e+07 Transitions= 2.47e+10 Memory= 3869.795 t= 3.3e+04 R= 2e+03 +Depth= 35611 States= 5.9e+07 Transitions= 2.52e+10 Memory= 3916.084 t= 3.37e+04 R= 2e+03 + +(Spin Version 5.1.7 -- 23 December 2008) + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness enabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 35611, errors: 0 + 33837266 states, stored (5.99297e+07 visited) +2.557894e+10 states, matched +2.563887e+10 transitions (= visited+matched) +1.4922421e+11 atomic steps +hash conflicts: 9.616061e+09 (resolved) + +Stats on memory usage (in Megabytes): + 3743.289 equivalent memory usage for states (stored*(State-vector + overhead)) + 2990.875 actual memory usage for states (compression: 79.90%) + state-vector as stored = 65 byte + 28 byte overhead + 512.000 memory used for hash table (-w26) + 457.764 memory used for DFS stack (-m10000000) + 1.683 memory lost to fragmentation + 3958.955 total actual memory usage + +unreached in proctype urcu_reader + line 250, "pan.___", state 30, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 52, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 61, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 77, "(1)" + line 231, "pan.___", state 85, "(1)" + line 235, "pan.___", state 97, "(1)" + line 239, "pan.___", state 105, "(1)" + line 395, "pan.___", state 131, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 163, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 177, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 196, "(1)" + line 421, "pan.___", state 226, "(1)" + line 425, "pan.___", state 239, "(1)" + line 670, "pan.___", state 260, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 395, "pan.___", state 267, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 299, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 313, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 332, "(1)" + line 421, "pan.___", state 362, "(1)" + line 425, "pan.___", state 375, "(1)" + line 395, "pan.___", state 396, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 428, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 442, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 461, "(1)" + line 421, "pan.___", state 491, "(1)" + line 425, "pan.___", state 504, "(1)" + line 395, "pan.___", state 527, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 529, "(1)" + line 395, "pan.___", state 530, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 530, "else" + line 395, "pan.___", state 533, "(1)" + line 399, "pan.___", state 541, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 543, "(1)" + line 399, "pan.___", state 544, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 544, "else" + line 399, "pan.___", state 547, "(1)" + line 399, "pan.___", state 548, "(1)" + line 399, "pan.___", state 548, "(1)" + line 397, "pan.___", state 553, "((i<1))" + line 397, "pan.___", state 553, "((i>=1))" + line 404, "pan.___", state 559, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 561, "(1)" + line 404, "pan.___", state 562, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 562, "else" + line 404, "pan.___", state 565, "(1)" + line 404, "pan.___", state 566, "(1)" + line 404, "pan.___", state 566, "(1)" + line 408, "pan.___", state 573, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 575, "(1)" + line 408, "pan.___", state 576, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 576, "else" + line 408, "pan.___", state 579, "(1)" + line 408, "pan.___", state 580, "(1)" + line 408, "pan.___", state 580, "(1)" + line 406, "pan.___", state 585, "((i<2))" + line 406, "pan.___", state 585, "((i>=2))" + line 412, "pan.___", state 592, "(1)" + line 412, "pan.___", state 593, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 593, "else" + line 412, "pan.___", state 596, "(1)" + line 412, "pan.___", state 597, "(1)" + line 412, "pan.___", state 597, "(1)" + line 416, "pan.___", state 605, "(1)" + line 416, "pan.___", state 606, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 606, "else" + line 416, "pan.___", state 609, "(1)" + line 416, "pan.___", state 610, "(1)" + line 416, "pan.___", state 610, "(1)" + line 414, "pan.___", state 615, "((i<1))" + line 414, "pan.___", state 615, "((i>=1))" + line 421, "pan.___", state 622, "(1)" + line 421, "pan.___", state 623, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 623, "else" + line 421, "pan.___", state 626, "(1)" + line 421, "pan.___", state 627, "(1)" + line 421, "pan.___", state 627, "(1)" + line 425, "pan.___", state 635, "(1)" + line 425, "pan.___", state 636, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 636, "else" + line 425, "pan.___", state 639, "(1)" + line 425, "pan.___", state 640, "(1)" + line 425, "pan.___", state 640, "(1)" + line 423, "pan.___", state 645, "((i<2))" + line 423, "pan.___", state 645, "((i>=2))" + line 430, "pan.___", state 649, "(1)" + line 430, "pan.___", state 649, "(1)" + line 670, "pan.___", state 652, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 670, "pan.___", state 653, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 670, "pan.___", state 654, "(1)" + line 395, "pan.___", state 661, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 693, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 707, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 726, "(1)" + line 421, "pan.___", state 756, "(1)" + line 425, "pan.___", state 769, "(1)" + line 395, "pan.___", state 797, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 799, "(1)" + line 395, "pan.___", state 800, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 800, "else" + line 395, "pan.___", state 803, "(1)" + line 399, "pan.___", state 811, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 813, "(1)" + line 399, "pan.___", state 814, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 814, "else" + line 399, "pan.___", state 817, "(1)" + line 399, "pan.___", state 818, "(1)" + line 399, "pan.___", state 818, "(1)" + line 397, "pan.___", state 823, "((i<1))" + line 397, "pan.___", state 823, "((i>=1))" + line 404, "pan.___", state 829, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 831, "(1)" + line 404, "pan.___", state 832, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 832, "else" + line 404, "pan.___", state 835, "(1)" + line 404, "pan.___", state 836, "(1)" + line 404, "pan.___", state 836, "(1)" + line 408, "pan.___", state 843, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 845, "(1)" + line 408, "pan.___", state 846, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 846, "else" + line 408, "pan.___", state 849, "(1)" + line 408, "pan.___", state 850, "(1)" + line 408, "pan.___", state 850, "(1)" + line 406, "pan.___", state 855, "((i<2))" + line 406, "pan.___", state 855, "((i>=2))" + line 412, "pan.___", state 862, "(1)" + line 412, "pan.___", state 863, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 863, "else" + line 412, "pan.___", state 866, "(1)" + line 412, "pan.___", state 867, "(1)" + line 412, "pan.___", state 867, "(1)" + line 416, "pan.___", state 875, "(1)" + line 416, "pan.___", state 876, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 876, "else" + line 416, "pan.___", state 879, "(1)" + line 416, "pan.___", state 880, "(1)" + line 416, "pan.___", state 880, "(1)" + line 414, "pan.___", state 885, "((i<1))" + line 414, "pan.___", state 885, "((i>=1))" + line 421, "pan.___", state 892, "(1)" + line 421, "pan.___", state 893, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 893, "else" + line 421, "pan.___", state 896, "(1)" + line 421, "pan.___", state 897, "(1)" + line 421, "pan.___", state 897, "(1)" + line 425, "pan.___", state 905, "(1)" + line 425, "pan.___", state 906, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 906, "else" + line 425, "pan.___", state 909, "(1)" + line 425, "pan.___", state 910, "(1)" + line 425, "pan.___", state 910, "(1)" + line 430, "pan.___", state 919, "(1)" + line 430, "pan.___", state 919, "(1)" + line 395, "pan.___", state 926, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 928, "(1)" + line 395, "pan.___", state 929, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 929, "else" + line 395, "pan.___", state 932, "(1)" + line 399, "pan.___", state 940, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 942, "(1)" + line 399, "pan.___", state 943, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 943, "else" + line 399, "pan.___", state 946, "(1)" + line 399, "pan.___", state 947, "(1)" + line 399, "pan.___", state 947, "(1)" + line 397, "pan.___", state 952, "((i<1))" + line 397, "pan.___", state 952, "((i>=1))" + line 404, "pan.___", state 958, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 960, "(1)" + line 404, "pan.___", state 961, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 961, "else" + line 404, "pan.___", state 964, "(1)" + line 404, "pan.___", state 965, "(1)" + line 404, "pan.___", state 965, "(1)" + line 408, "pan.___", state 972, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 974, "(1)" + line 408, "pan.___", state 975, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 975, "else" + line 408, "pan.___", state 978, "(1)" + line 408, "pan.___", state 979, "(1)" + line 408, "pan.___", state 979, "(1)" + line 406, "pan.___", state 984, "((i<2))" + line 406, "pan.___", state 984, "((i>=2))" + line 412, "pan.___", state 991, "(1)" + line 412, "pan.___", state 992, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 992, "else" + line 412, "pan.___", state 995, "(1)" + line 412, "pan.___", state 996, "(1)" + line 412, "pan.___", state 996, "(1)" + line 416, "pan.___", state 1004, "(1)" + line 416, "pan.___", state 1005, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 1005, "else" + line 416, "pan.___", state 1008, "(1)" + line 416, "pan.___", state 1009, "(1)" + line 416, "pan.___", state 1009, "(1)" + line 414, "pan.___", state 1014, "((i<1))" + line 414, "pan.___", state 1014, "((i>=1))" + line 421, "pan.___", state 1021, "(1)" + line 421, "pan.___", state 1022, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 1022, "else" + line 421, "pan.___", state 1025, "(1)" + line 421, "pan.___", state 1026, "(1)" + line 421, "pan.___", state 1026, "(1)" + line 425, "pan.___", state 1034, "(1)" + line 425, "pan.___", state 1035, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 1035, "else" + line 425, "pan.___", state 1038, "(1)" + line 425, "pan.___", state 1039, "(1)" + line 425, "pan.___", state 1039, "(1)" + line 423, "pan.___", state 1044, "((i<2))" + line 423, "pan.___", state 1044, "((i>=2))" + line 430, "pan.___", state 1048, "(1)" + line 430, "pan.___", state 1048, "(1)" + line 678, "pan.___", state 1052, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 395, "pan.___", state 1057, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1089, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1103, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1122, "(1)" + line 421, "pan.___", state 1152, "(1)" + line 425, "pan.___", state 1165, "(1)" + line 395, "pan.___", state 1189, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1221, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1235, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1254, "(1)" + line 421, "pan.___", state 1284, "(1)" + line 425, "pan.___", state 1297, "(1)" + line 395, "pan.___", state 1322, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1354, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1368, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1387, "(1)" + line 421, "pan.___", state 1417, "(1)" + line 425, "pan.___", state 1430, "(1)" + line 395, "pan.___", state 1451, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1483, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1497, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1516, "(1)" + line 421, "pan.___", state 1546, "(1)" + line 425, "pan.___", state 1559, "(1)" + line 395, "pan.___", state 1585, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1617, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1631, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1650, "(1)" + line 421, "pan.___", state 1680, "(1)" + line 425, "pan.___", state 1693, "(1)" + line 395, "pan.___", state 1714, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1746, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1760, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1779, "(1)" + line 421, "pan.___", state 1809, "(1)" + line 425, "pan.___", state 1822, "(1)" + line 395, "pan.___", state 1846, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1878, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1892, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1911, "(1)" + line 421, "pan.___", state 1941, "(1)" + line 425, "pan.___", state 1954, "(1)" + line 717, "pan.___", state 1975, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 395, "pan.___", state 1982, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2014, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2028, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2047, "(1)" + line 421, "pan.___", state 2077, "(1)" + line 425, "pan.___", state 2090, "(1)" + line 395, "pan.___", state 2111, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2143, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2157, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2176, "(1)" + line 421, "pan.___", state 2206, "(1)" + line 425, "pan.___", state 2219, "(1)" + line 395, "pan.___", state 2242, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 2244, "(1)" + line 395, "pan.___", state 2245, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 2245, "else" + line 395, "pan.___", state 2248, "(1)" + line 399, "pan.___", state 2256, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2258, "(1)" + line 399, "pan.___", state 2259, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 2259, "else" + line 399, "pan.___", state 2262, "(1)" + line 399, "pan.___", state 2263, "(1)" + line 399, "pan.___", state 2263, "(1)" + line 397, "pan.___", state 2268, "((i<1))" + line 397, "pan.___", state 2268, "((i>=1))" + line 404, "pan.___", state 2274, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2276, "(1)" + line 404, "pan.___", state 2277, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 2277, "else" + line 404, "pan.___", state 2280, "(1)" + line 404, "pan.___", state 2281, "(1)" + line 404, "pan.___", state 2281, "(1)" + line 408, "pan.___", state 2288, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2290, "(1)" + line 408, "pan.___", state 2291, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 2291, "else" + line 408, "pan.___", state 2294, "(1)" + line 408, "pan.___", state 2295, "(1)" + line 408, "pan.___", state 2295, "(1)" + line 406, "pan.___", state 2300, "((i<2))" + line 406, "pan.___", state 2300, "((i>=2))" + line 412, "pan.___", state 2307, "(1)" + line 412, "pan.___", state 2308, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 2308, "else" + line 412, "pan.___", state 2311, "(1)" + line 412, "pan.___", state 2312, "(1)" + line 412, "pan.___", state 2312, "(1)" + line 416, "pan.___", state 2320, "(1)" + line 416, "pan.___", state 2321, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 2321, "else" + line 416, "pan.___", state 2324, "(1)" + line 416, "pan.___", state 2325, "(1)" + line 416, "pan.___", state 2325, "(1)" + line 414, "pan.___", state 2330, "((i<1))" + line 414, "pan.___", state 2330, "((i>=1))" + line 421, "pan.___", state 2337, "(1)" + line 421, "pan.___", state 2338, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 2338, "else" + line 421, "pan.___", state 2341, "(1)" + line 421, "pan.___", state 2342, "(1)" + line 421, "pan.___", state 2342, "(1)" + line 425, "pan.___", state 2350, "(1)" + line 425, "pan.___", state 2351, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 2351, "else" + line 425, "pan.___", state 2354, "(1)" + line 425, "pan.___", state 2355, "(1)" + line 425, "pan.___", state 2355, "(1)" + line 423, "pan.___", state 2360, "((i<2))" + line 423, "pan.___", state 2360, "((i>=2))" + line 430, "pan.___", state 2364, "(1)" + line 430, "pan.___", state 2364, "(1)" + line 717, "pan.___", state 2367, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 717, "pan.___", state 2368, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 717, "pan.___", state 2369, "(1)" + line 395, "pan.___", state 2376, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2408, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2422, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2441, "(1)" + line 421, "pan.___", state 2471, "(1)" + line 425, "pan.___", state 2484, "(1)" + line 395, "pan.___", state 2511, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2543, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2557, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2576, "(1)" + line 421, "pan.___", state 2606, "(1)" + line 425, "pan.___", state 2619, "(1)" + line 395, "pan.___", state 2640, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2672, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2686, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2705, "(1)" + line 421, "pan.___", state 2735, "(1)" + line 425, "pan.___", state 2748, "(1)" + line 227, "pan.___", state 2781, "(1)" + line 235, "pan.___", state 2801, "(1)" + line 239, "pan.___", state 2809, "(1)" + line 227, "pan.___", state 2824, "(1)" + line 235, "pan.___", state 2844, "(1)" + line 239, "pan.___", state 2852, "(1)" + line 877, "pan.___", state 2869, "-end-" + (278 of 2869 states) +unreached in proctype urcu_writer + line 395, "pan.___", state 18, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 32, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 50, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 412, "pan.___", state 83, "(1)" + line 416, "pan.___", state 96, "(1)" + line 421, "pan.___", state 113, "(1)" + line 250, "pan.___", state 149, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 158, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 171, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 211, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 225, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 243, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 257, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 276, "(1)" + line 416, "pan.___", state 289, "(1)" + line 421, "pan.___", state 306, "(1)" + line 425, "pan.___", state 319, "(1)" + line 399, "pan.___", state 356, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 374, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 388, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 420, "(1)" + line 421, "pan.___", state 437, "(1)" + line 425, "pan.___", state 450, "(1)" + line 399, "pan.___", state 494, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 512, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 526, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 558, "(1)" + line 421, "pan.___", state 575, "(1)" + line 425, "pan.___", state 588, "(1)" + line 399, "pan.___", state 623, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 641, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 655, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 687, "(1)" + line 421, "pan.___", state 704, "(1)" + line 425, "pan.___", state 717, "(1)" + line 399, "pan.___", state 754, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 772, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 786, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 818, "(1)" + line 421, "pan.___", state 835, "(1)" + line 425, "pan.___", state 848, "(1)" + line 250, "pan.___", state 898, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 907, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 920, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 227, "pan.___", state 945, "(1)" + line 231, "pan.___", state 953, "(1)" + line 235, "pan.___", state 965, "(1)" + line 239, "pan.___", state 973, "(1)" + line 250, "pan.___", state 1004, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1013, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1026, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1035, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1051, "(1)" + line 231, "pan.___", state 1059, "(1)" + line 235, "pan.___", state 1071, "(1)" + line 239, "pan.___", state 1079, "(1)" + line 250, "pan.___", state 1100, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1109, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1124, "(1)" + line 262, "pan.___", state 1131, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1147, "(1)" + line 231, "pan.___", state 1155, "(1)" + line 235, "pan.___", state 1167, "(1)" + line 239, "pan.___", state 1175, "(1)" + line 250, "pan.___", state 1206, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1215, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1228, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1237, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1253, "(1)" + line 231, "pan.___", state 1261, "(1)" + line 235, "pan.___", state 1273, "(1)" + line 239, "pan.___", state 1281, "(1)" + line 254, "pan.___", state 1307, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1320, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1329, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1345, "(1)" + line 231, "pan.___", state 1353, "(1)" + line 235, "pan.___", state 1365, "(1)" + line 239, "pan.___", state 1373, "(1)" + line 250, "pan.___", state 1404, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1413, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1426, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1435, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1451, "(1)" + line 231, "pan.___", state 1459, "(1)" + line 235, "pan.___", state 1471, "(1)" + line 239, "pan.___", state 1479, "(1)" + line 254, "pan.___", state 1505, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1518, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1527, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1543, "(1)" + line 231, "pan.___", state 1551, "(1)" + line 235, "pan.___", state 1563, "(1)" + line 239, "pan.___", state 1571, "(1)" + line 250, "pan.___", state 1602, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1611, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1624, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1633, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1649, "(1)" + line 231, "pan.___", state 1657, "(1)" + line 235, "pan.___", state 1669, "(1)" + line 239, "pan.___", state 1677, "(1)" + line 254, "pan.___", state 1703, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1716, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1725, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1741, "(1)" + line 231, "pan.___", state 1749, "(1)" + line 235, "pan.___", state 1761, "(1)" + line 239, "pan.___", state 1769, "(1)" + line 250, "pan.___", state 1800, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1809, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1822, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1831, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1847, "(1)" + line 231, "pan.___", state 1855, "(1)" + line 235, "pan.___", state 1867, "(1)" + line 239, "pan.___", state 1875, "(1)" + line 1204, "pan.___", state 1891, "-end-" + (118 of 1891 states) +unreached in proctype :init: + (0 of 78 states) +unreached in proctype :never: + line 1265, "pan.___", state 11, "-end-" + (1 of 11 states) + +pan: elapsed time 3.42e+04 seconds +pan: rate 1751.5295 states/second +pan: avg transition delay 1.3345e-06 usec +cp .input.spin urcu_progress_reader.spin.input +cp .input.spin.trail urcu_progress_reader.spin.input.trail diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_progress_reader.spin.input b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_reader.spin.input new file mode 100644 index 0000000..fc0b3ae --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_reader.spin.input @@ -0,0 +1,1240 @@ +#define READER_PROGRESS + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_progress_reader.spin.input.trail b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_reader.spin.input.trail new file mode 100644 index 0000000..a0cf98c --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_reader.spin.input.trail @@ -0,0 +1,1767 @@ +-2:3:-2 +-4:-4:-4 +1:0:4840 +2:3:4760 +3:3:4763 +4:3:4763 +5:3:4766 +6:3:4774 +7:3:4774 +8:3:4777 +9:3:4783 +10:3:4787 +11:3:4787 +12:3:4790 +13:3:4800 +14:3:4808 +15:3:4808 +16:3:4811 +17:3:4817 +18:3:4821 +19:3:4821 +20:3:4824 +21:3:4830 +22:3:4834 +23:3:4835 +24:0:4840 +25:3:4837 +26:0:4840 +27:2:2871 +28:0:4840 +29:2:2877 +30:0:4840 +31:2:2878 +32:0:4840 +33:2:2880 +34:0:4840 +35:2:2881 +36:0:4840 +37:2:2882 +38:2:2883 +39:2:2887 +40:2:2888 +41:2:2896 +42:2:2897 +43:2:2901 +44:2:2902 +45:2:2910 +46:2:2915 +47:2:2919 +48:2:2920 +49:2:2928 +50:2:2929 +51:2:2933 +52:2:2934 +53:2:2928 +54:2:2929 +55:2:2933 +56:2:2934 +57:2:2942 +58:2:2947 +59:2:2948 +60:2:2959 +61:2:2960 +62:2:2961 +63:2:2972 +64:2:2977 +65:2:2978 +66:2:2989 +67:2:2990 +68:2:2991 +69:2:2989 +70:2:2990 +71:2:2991 +72:2:3002 +73:2:3010 +74:0:4840 +75:2:2881 +76:0:4840 +77:2:3014 +78:2:3018 +79:2:3019 +80:2:3023 +81:2:3027 +82:2:3028 +83:2:3032 +84:2:3040 +85:2:3041 +86:2:3045 +87:2:3049 +88:2:3050 +89:2:3045 +90:2:3046 +91:2:3054 +92:0:4840 +93:2:2881 +94:0:4840 +95:2:3062 +96:2:3063 +97:2:3064 +98:0:4840 +99:2:2881 +100:0:4840 +101:2:3069 +102:0:4840 +103:2:3969 +104:2:3970 +105:2:3974 +106:2:3978 +107:2:3979 +108:2:3983 +109:2:3988 +110:2:3996 +111:2:4000 +112:2:4001 +113:2:3996 +114:2:4000 +115:2:4001 +116:2:4005 +117:2:4012 +118:2:4019 +119:2:4020 +120:2:4027 +121:2:4032 +122:2:4039 +123:2:4040 +124:2:4039 +125:2:4040 +126:2:4047 +127:2:4051 +128:0:4840 +129:2:4056 +130:0:4840 +131:2:4057 +132:0:4840 +133:2:4058 +134:0:4840 +135:2:4059 +136:0:4840 +137:1:2 +138:0:4840 +139:1:8 +140:0:4840 +141:2:4060 +142:0:4840 +143:1:9 +144:0:4840 +145:2:4059 +146:0:4840 +147:1:10 +148:0:4840 +149:2:4060 +150:0:4838 +151:1:11 +152:0:4844 +153:1:12 +154:0:4844 +155:1:13 +156:0:4844 +157:1:14 +158:0:4844 +159:1:15 +160:0:4844 +161:1:16 +162:0:4844 +163:1:17 +164:0:4844 +165:1:26 +166:0:4844 +167:1:30 +168:1:31 +169:1:35 +170:1:39 +171:1:40 +172:1:44 +173:1:52 +174:1:53 +175:1:57 +176:1:61 +177:1:62 +178:1:57 +179:1:61 +180:1:62 +181:1:66 +182:1:73 +183:1:80 +184:1:81 +185:1:88 +186:1:93 +187:1:100 +188:1:101 +189:1:100 +190:1:101 +191:1:108 +192:1:112 +193:0:4844 +194:1:117 +195:0:4844 +196:2:4061 +197:0:4844 +198:2:4066 +199:0:4844 +200:2:4067 +201:0:4844 +202:2:4075 +203:2:4076 +204:2:4080 +205:2:4084 +206:2:4085 +207:2:4089 +208:2:4097 +209:2:4098 +210:2:4102 +211:2:4106 +212:2:4107 +213:2:4102 +214:2:4106 +215:2:4107 +216:2:4111 +217:2:4118 +218:2:4125 +219:2:4126 +220:2:4133 +221:2:4138 +222:2:4145 +223:2:4146 +224:2:4145 +225:2:4146 +226:2:4153 +227:2:4157 +228:0:4844 +229:2:3071 +230:2:3753 +231:0:4844 +232:2:2881 +233:0:4844 +234:2:3072 +235:0:4844 +236:2:2881 +237:0:4844 +238:2:3075 +239:2:3076 +240:2:3080 +241:2:3081 +242:2:3089 +243:2:3090 +244:2:3094 +245:2:3095 +246:2:3103 +247:2:3108 +248:2:3112 +249:2:3113 +250:2:3121 +251:2:3122 +252:2:3126 +253:2:3127 +254:2:3121 +255:2:3122 +256:2:3126 +257:2:3127 +258:2:3135 +259:2:3140 +260:2:3141 +261:2:3152 +262:2:3153 +263:2:3154 +264:2:3165 +265:2:3170 +266:2:3171 +267:2:3182 +268:2:3183 +269:2:3184 +270:2:3182 +271:2:3183 +272:2:3184 +273:2:3195 +274:2:3202 +275:0:4844 +276:2:2881 +277:0:4844 +278:2:3206 +279:2:3207 +280:2:3208 +281:2:3220 +282:2:3221 +283:2:3225 +284:2:3226 +285:2:3234 +286:2:3239 +287:2:3243 +288:2:3244 +289:2:3252 +290:2:3253 +291:2:3257 +292:2:3258 +293:2:3252 +294:2:3253 +295:2:3257 +296:2:3258 +297:2:3266 +298:2:3271 +299:2:3272 +300:2:3283 +301:2:3284 +302:2:3285 +303:2:3296 +304:2:3301 +305:2:3302 +306:2:3313 +307:2:3314 +308:2:3315 +309:2:3313 +310:2:3314 +311:2:3315 +312:2:3326 +313:2:3337 +314:2:3338 +315:0:4844 +316:2:2881 +317:0:4844 +318:2:3344 +319:2:3345 +320:2:3349 +321:2:3350 +322:2:3358 +323:2:3359 +324:2:3363 +325:2:3364 +326:2:3372 +327:2:3377 +328:2:3381 +329:2:3382 +330:2:3390 +331:2:3391 +332:2:3395 +333:2:3396 +334:2:3390 +335:2:3391 +336:2:3395 +337:2:3396 +338:2:3404 +339:2:3409 +340:2:3410 +341:2:3421 +342:2:3422 +343:2:3423 +344:2:3434 +345:2:3439 +346:2:3440 +347:2:3451 +348:2:3452 +349:2:3453 +350:2:3451 +351:2:3452 +352:2:3453 +353:2:3464 +354:0:4844 +355:2:2881 +356:0:4844 +357:2:3473 +358:2:3474 +359:2:3478 +360:2:3479 +361:2:3487 +362:2:3488 +363:2:3492 +364:2:3493 +365:2:3501 +366:2:3506 +367:2:3510 +368:2:3511 +369:2:3519 +370:2:3520 +371:2:3524 +372:2:3525 +373:2:3519 +374:2:3520 +375:2:3524 +376:2:3525 +377:2:3533 +378:2:3538 +379:2:3539 +380:2:3550 +381:2:3551 +382:2:3552 +383:2:3563 +384:2:3568 +385:2:3569 +386:2:3580 +387:2:3581 +388:2:3582 +389:2:3580 +390:2:3581 +391:2:3582 +392:2:3593 +393:2:3600 +394:0:4844 +395:2:2881 +396:0:4844 +397:2:3604 +398:2:3605 +399:2:3606 +400:2:3618 +401:2:3619 +402:2:3623 +403:2:3624 +404:2:3632 +405:2:3637 +406:2:3641 +407:2:3642 +408:2:3650 +409:2:3651 +410:2:3655 +411:2:3656 +412:2:3650 +413:2:3651 +414:2:3655 +415:2:3656 +416:2:3664 +417:2:3669 +418:2:3670 +419:2:3681 +420:2:3682 +421:2:3683 +422:2:3694 +423:2:3699 +424:2:3700 +425:2:3711 +426:2:3712 +427:2:3713 +428:2:3711 +429:2:3712 +430:2:3713 +431:2:3724 +432:2:3734 +433:2:3735 +434:0:4844 +435:2:2881 +436:0:4844 +437:2:3741 +438:0:4844 +439:2:4563 +440:2:4564 +441:2:4568 +442:2:4572 +443:2:4573 +444:2:4577 +445:2:4585 +446:2:4586 +447:2:4590 +448:2:4594 +449:2:4595 +450:2:4590 +451:2:4594 +452:2:4595 +453:2:4599 +454:2:4606 +455:2:4613 +456:2:4614 +457:2:4621 +458:2:4626 +459:2:4633 +460:2:4634 +461:2:4633 +462:2:4634 +463:2:4641 +464:2:4645 +465:0:4844 +466:2:4650 +467:0:4844 +468:2:4651 +469:0:4844 +470:2:4652 +471:0:4844 +472:1:26 +473:0:4844 +474:1:30 +475:1:31 +476:1:35 +477:1:39 +478:1:40 +479:1:44 +480:1:52 +481:1:53 +482:1:57 +483:1:61 +484:1:62 +485:1:57 +486:1:61 +487:1:62 +488:1:66 +489:1:73 +490:1:80 +491:1:81 +492:1:88 +493:1:93 +494:1:100 +495:1:101 +496:1:100 +497:1:101 +498:1:108 +499:1:112 +500:0:4844 +501:1:117 +502:0:4844 +503:2:4655 +504:0:4844 +505:2:4660 +506:0:4844 +507:2:4661 +508:0:4844 +509:2:4669 +510:2:4670 +511:2:4674 +512:2:4678 +513:2:4679 +514:2:4683 +515:2:4691 +516:2:4692 +517:2:4696 +518:2:4700 +519:2:4701 +520:2:4696 +521:2:4700 +522:2:4701 +523:2:4705 +524:2:4712 +525:2:4719 +526:2:4720 +527:2:4727 +528:2:4732 +529:2:4739 +530:2:4740 +531:2:4739 +532:2:4740 +533:2:4747 +534:2:4751 +535:0:4844 +536:2:3743 +537:2:3753 +538:0:4844 +539:2:2881 +540:0:4844 +541:2:3744 +542:2:3745 +543:0:4844 +544:2:2881 +545:0:4844 +546:2:3749 +547:0:4844 +548:2:3757 +549:0:4844 +550:2:2878 +551:0:4844 +552:2:2880 +553:0:4844 +554:2:2881 +555:0:4844 +556:2:2882 +557:2:2883 +558:2:2887 +559:2:2888 +560:2:2896 +561:2:2897 +562:2:2901 +563:2:2902 +564:2:2910 +565:2:2915 +566:2:2919 +567:2:2920 +568:2:2928 +569:2:2929 +570:2:2930 +571:2:2928 +572:2:2929 +573:2:2933 +574:2:2934 +575:2:2942 +576:2:2947 +577:2:2948 +578:2:2959 +579:2:2960 +580:2:2961 +581:2:2972 +582:2:2977 +583:2:2978 +584:2:2989 +585:2:2990 +586:2:2991 +587:2:2989 +588:2:2990 +589:2:2991 +590:2:3002 +591:2:3010 +592:0:4844 +593:2:2881 +594:0:4844 +595:2:3014 +596:2:3018 +597:2:3019 +598:2:3023 +599:2:3027 +600:2:3028 +601:2:3032 +602:2:3040 +603:2:3041 +604:2:3045 +605:2:3046 +606:2:3045 +607:2:3049 +608:2:3050 +609:2:3054 +610:0:4844 +611:2:2881 +612:0:4844 +613:2:3062 +614:2:3063 +615:2:3064 +616:0:4844 +617:2:2881 +618:0:4844 +619:2:3069 +620:0:4844 +621:2:3969 +622:2:3970 +623:2:3974 +624:2:3978 +625:2:3979 +626:2:3983 +627:2:3988 +628:2:3996 +629:2:4000 +630:2:4001 +631:2:3996 +632:2:4000 +633:2:4001 +634:2:4005 +635:2:4012 +636:2:4019 +637:2:4020 +638:2:4027 +639:2:4032 +640:2:4039 +641:2:4040 +642:2:4039 +643:2:4040 +644:2:4047 +645:2:4051 +646:0:4844 +647:2:4056 +648:0:4844 +649:2:4057 +650:0:4844 +651:2:4058 +652:0:4844 +653:1:26 +654:0:4844 +655:1:30 +656:1:31 +657:1:35 +658:1:39 +659:1:40 +660:1:44 +661:1:52 +662:1:53 +663:1:57 +664:1:61 +665:1:62 +666:1:57 +667:1:61 +668:1:62 +669:1:66 +670:1:73 +671:1:80 +672:1:81 +673:1:88 +674:1:93 +675:1:100 +676:1:101 +677:1:100 +678:1:101 +679:1:108 +680:1:112 +681:0:4844 +682:1:117 +683:0:4844 +684:2:4061 +685:0:4844 +686:2:4066 +687:0:4844 +688:2:4067 +689:0:4844 +690:2:4075 +691:2:4076 +692:2:4080 +693:2:4084 +694:2:4085 +695:2:4089 +696:2:4097 +697:2:4098 +698:2:4102 +699:2:4106 +700:2:4107 +701:2:4102 +702:2:4106 +703:2:4107 +704:2:4111 +705:2:4118 +706:2:4125 +707:2:4126 +708:2:4133 +709:2:4138 +710:2:4145 +711:2:4146 +712:2:4145 +713:2:4146 +714:2:4153 +715:2:4157 +716:0:4844 +717:2:3071 +718:2:3753 +719:0:4844 +720:2:2881 +721:0:4844 +722:2:3072 +723:0:4844 +724:2:2881 +725:0:4844 +726:2:3075 +727:2:3076 +728:2:3080 +729:2:3081 +730:2:3089 +731:2:3090 +732:2:3094 +733:2:3095 +734:2:3103 +735:2:3108 +736:2:3112 +737:2:3113 +738:2:3121 +739:2:3122 +740:2:3126 +741:2:3127 +742:2:3121 +743:2:3122 +744:2:3126 +745:2:3127 +746:2:3135 +747:2:3140 +748:2:3141 +749:2:3152 +750:2:3153 +751:2:3154 +752:2:3165 +753:2:3170 +754:2:3171 +755:2:3182 +756:2:3183 +757:2:3184 +758:2:3182 +759:2:3183 +760:2:3184 +761:2:3195 +762:2:3202 +763:0:4844 +764:2:2881 +765:0:4844 +766:2:3206 +767:2:3207 +768:2:3208 +769:2:3220 +770:2:3221 +771:2:3225 +772:2:3226 +773:2:3234 +774:2:3239 +775:2:3243 +776:2:3244 +777:2:3252 +778:2:3253 +779:2:3257 +780:2:3258 +781:2:3252 +782:2:3253 +783:2:3257 +784:2:3258 +785:2:3266 +786:2:3271 +787:2:3272 +788:2:3283 +789:2:3284 +790:2:3285 +791:2:3296 +792:2:3301 +793:2:3302 +794:2:3313 +795:2:3314 +796:2:3315 +797:2:3313 +798:2:3314 +799:2:3315 +800:2:3326 +801:2:3337 +802:2:3338 +803:0:4844 +804:2:2881 +805:0:4844 +806:2:3344 +807:2:3345 +808:2:3349 +809:2:3350 +810:2:3358 +811:2:3359 +812:2:3363 +813:2:3364 +814:2:3372 +815:2:3377 +816:2:3381 +817:2:3382 +818:2:3390 +819:2:3391 +820:2:3395 +821:2:3396 +822:2:3390 +823:2:3391 +824:2:3395 +825:2:3396 +826:2:3404 +827:2:3409 +828:2:3410 +829:2:3421 +830:2:3422 +831:2:3423 +832:2:3434 +833:2:3439 +834:2:3440 +835:2:3451 +836:2:3452 +837:2:3453 +838:2:3451 +839:2:3452 +840:2:3453 +841:2:3464 +842:0:4844 +843:2:2881 +844:0:4844 +845:2:3473 +846:2:3474 +847:2:3478 +848:2:3479 +849:2:3487 +850:2:3488 +851:2:3492 +852:2:3493 +853:2:3501 +854:2:3506 +855:2:3510 +856:2:3511 +857:2:3519 +858:2:3520 +859:2:3524 +860:2:3525 +861:2:3519 +862:2:3520 +863:2:3524 +864:2:3525 +865:2:3533 +866:2:3538 +867:2:3539 +868:2:3550 +869:2:3551 +870:2:3552 +871:2:3563 +872:2:3568 +873:2:3569 +874:2:3580 +875:2:3581 +876:2:3582 +877:2:3580 +878:2:3581 +879:2:3582 +880:2:3593 +881:2:3600 +882:0:4844 +883:2:2881 +884:0:4844 +885:2:3604 +886:2:3605 +887:2:3606 +888:2:3618 +889:2:3619 +890:2:3623 +891:2:3624 +892:2:3632 +893:2:3637 +894:2:3641 +895:2:3642 +896:2:3650 +897:2:3651 +898:2:3655 +899:2:3656 +900:2:3650 +901:2:3651 +902:2:3655 +903:2:3656 +904:2:3664 +905:2:3669 +906:2:3670 +907:2:3681 +908:2:3682 +909:2:3683 +910:2:3694 +911:2:3699 +912:2:3700 +913:2:3711 +914:2:3712 +915:2:3713 +916:2:3711 +917:2:3712 +918:2:3713 +919:2:3724 +920:2:3734 +921:2:3735 +922:0:4844 +923:2:2881 +924:0:4844 +925:2:3741 +926:0:4844 +927:2:4563 +928:2:4564 +929:2:4568 +930:2:4572 +931:2:4573 +932:2:4577 +933:2:4585 +934:2:4586 +935:2:4590 +936:2:4594 +937:2:4595 +938:2:4590 +939:2:4594 +940:2:4595 +941:2:4599 +942:2:4606 +943:2:4613 +944:2:4614 +945:2:4621 +946:2:4626 +947:2:4633 +948:2:4634 +949:2:4633 +950:2:4634 +951:2:4641 +952:2:4645 +953:0:4844 +954:2:4650 +955:0:4844 +956:2:4651 +957:0:4844 +958:2:4652 +959:0:4844 +960:1:26 +961:0:4844 +962:1:30 +963:1:31 +964:1:35 +965:1:39 +966:1:40 +967:1:44 +968:1:52 +969:1:53 +970:1:57 +971:1:61 +972:1:62 +973:1:57 +974:1:61 +975:1:62 +976:1:66 +977:1:73 +978:1:80 +979:1:81 +980:1:88 +981:1:93 +982:1:100 +983:1:101 +984:1:100 +985:1:101 +986:1:108 +987:1:112 +988:0:4844 +989:1:117 +990:0:4844 +991:2:4655 +992:0:4844 +993:2:4660 +994:0:4844 +995:2:4661 +996:0:4844 +997:2:4669 +998:2:4670 +999:2:4674 +1000:2:4678 +1001:2:4679 +1002:2:4683 +1003:2:4691 +1004:2:4692 +1005:2:4696 +1006:2:4700 +1007:2:4701 +1008:2:4696 +1009:2:4700 +1010:2:4701 +1011:2:4705 +1012:2:4712 +1013:2:4719 +1014:2:4720 +1015:2:4727 +1016:2:4732 +1017:2:4739 +1018:2:4740 +1019:2:4739 +1020:2:4740 +1021:2:4747 +1022:2:4751 +1023:0:4844 +1024:2:3743 +1025:2:3753 +1026:0:4844 +1027:2:2881 +1028:0:4844 +1029:2:3744 +1030:2:3745 +1031:0:4844 +1032:2:2881 +1033:0:4844 +1034:2:3749 +1035:0:4844 +1036:2:3757 +1037:0:4844 +1038:2:2878 +1039:0:4844 +1040:2:2880 +1041:0:4844 +1042:2:2881 +1043:0:4844 +1044:2:2882 +1045:2:2883 +1046:2:2887 +1047:2:2888 +1048:2:2896 +1049:2:2897 +1050:2:2901 +1051:2:2902 +1052:2:2910 +1053:2:2915 +1054:2:2919 +1055:2:2920 +1056:2:2928 +1057:2:2929 +1058:2:2933 +1059:2:2934 +1060:2:2928 +1061:2:2929 +1062:2:2930 +1063:2:2942 +1064:2:2947 +1065:2:2948 +1066:2:2959 +1067:2:2960 +1068:2:2961 +1069:2:2972 +1070:2:2977 +1071:2:2978 +1072:2:2989 +1073:2:2990 +1074:2:2991 +1075:2:2989 +1076:2:2990 +1077:2:2991 +1078:2:3002 +1079:2:3010 +1080:0:4844 +1081:2:2881 +1082:0:4844 +1083:2:3014 +1084:2:3018 +1085:2:3019 +1086:2:3023 +1087:2:3027 +1088:2:3028 +1089:2:3032 +1090:2:3040 +1091:2:3041 +1092:2:3045 +1093:2:3049 +1094:2:3050 +1095:2:3045 +1096:2:3046 +1097:2:3054 +1098:0:4844 +1099:2:2881 +1100:0:4844 +1101:2:3062 +1102:2:3063 +1103:2:3064 +1104:0:4844 +1105:2:2881 +1106:0:4844 +1107:2:3069 +1108:0:4844 +1109:2:3969 +1110:2:3970 +1111:2:3974 +1112:2:3978 +1113:2:3979 +1114:2:3983 +1115:2:3988 +1116:2:3996 +1117:2:4000 +1118:2:4001 +1119:2:3996 +1120:2:4000 +1121:2:4001 +1122:2:4005 +1123:2:4012 +1124:2:4019 +1125:2:4020 +1126:2:4027 +1127:2:4032 +1128:2:4039 +1129:2:4040 +1130:2:4039 +1131:2:4040 +1132:2:4047 +1133:2:4051 +1134:0:4844 +1135:2:4056 +1136:0:4844 +1137:2:4057 +1138:0:4844 +1139:2:4058 +1140:0:4844 +1141:1:26 +1142:0:4844 +1143:1:30 +1144:1:31 +1145:1:35 +1146:1:39 +1147:1:40 +1148:1:44 +1149:1:52 +1150:1:53 +1151:1:57 +1152:1:61 +1153:1:62 +1154:1:57 +1155:1:61 +1156:1:62 +1157:1:66 +1158:1:73 +1159:1:80 +1160:1:81 +1161:1:88 +1162:1:93 +1163:1:100 +1164:1:101 +1165:1:100 +1166:1:101 +1167:1:108 +1168:1:112 +1169:0:4844 +1170:1:117 +1171:0:4844 +1172:2:4061 +1173:0:4844 +1174:2:4066 +1175:0:4844 +1176:2:4067 +1177:0:4844 +1178:2:4075 +1179:2:4076 +1180:2:4080 +1181:2:4084 +1182:2:4085 +1183:2:4089 +1184:2:4097 +1185:2:4098 +1186:2:4102 +1187:2:4106 +1188:2:4107 +1189:2:4102 +1190:2:4106 +1191:2:4107 +1192:2:4111 +1193:2:4118 +1194:2:4125 +1195:2:4126 +1196:2:4133 +1197:2:4138 +1198:2:4145 +1199:2:4146 +1200:2:4145 +1201:2:4146 +1202:2:4153 +1203:2:4157 +1204:0:4844 +1205:2:3071 +1206:2:3753 +1207:0:4844 +1208:2:2881 +1209:0:4844 +1210:2:3072 +1211:0:4844 +1212:2:2881 +1213:0:4844 +1214:2:3075 +1215:2:3076 +1216:2:3080 +1217:2:3081 +1218:2:3089 +1219:2:3090 +1220:2:3094 +1221:2:3095 +1222:2:3103 +1223:2:3108 +1224:2:3112 +1225:2:3113 +1226:2:3121 +1227:2:3122 +1228:2:3126 +1229:2:3127 +1230:2:3121 +1231:2:3122 +1232:2:3126 +1233:2:3127 +1234:2:3135 +1235:2:3140 +1236:2:3141 +1237:2:3152 +1238:2:3153 +1239:2:3154 +1240:2:3165 +1241:2:3170 +1242:2:3171 +1243:2:3182 +1244:2:3183 +1245:2:3184 +1246:2:3182 +1247:2:3183 +1248:2:3184 +1249:2:3195 +1250:2:3202 +1251:0:4844 +1252:2:2881 +1253:0:4844 +1254:2:3206 +1255:2:3207 +1256:2:3208 +1257:2:3220 +1258:2:3221 +1259:2:3225 +1260:2:3226 +1261:2:3234 +1262:2:3239 +1263:2:3243 +1264:2:3244 +1265:2:3252 +1266:2:3253 +1267:2:3257 +1268:2:3258 +1269:2:3252 +1270:2:3253 +1271:2:3257 +1272:2:3258 +1273:2:3266 +1274:2:3271 +1275:2:3272 +1276:2:3283 +1277:2:3284 +1278:2:3285 +1279:2:3296 +1280:2:3301 +1281:2:3302 +1282:2:3313 +1283:2:3314 +1284:2:3315 +1285:2:3313 +1286:2:3314 +1287:2:3315 +1288:2:3326 +1289:2:3337 +1290:2:3338 +1291:0:4844 +1292:2:2881 +1293:0:4844 +1294:2:3344 +1295:2:3345 +1296:2:3349 +1297:2:3350 +1298:2:3358 +1299:2:3359 +1300:2:3363 +1301:2:3364 +1302:2:3372 +1303:2:3377 +1304:2:3381 +1305:2:3382 +1306:2:3390 +1307:2:3391 +1308:2:3395 +1309:2:3396 +1310:2:3390 +1311:2:3391 +1312:2:3395 +1313:2:3396 +1314:2:3404 +1315:2:3409 +1316:2:3410 +1317:2:3421 +1318:2:3422 +1319:2:3423 +1320:2:3434 +1321:2:3439 +1322:2:3440 +1323:2:3451 +1324:2:3452 +1325:2:3453 +1326:2:3451 +1327:2:3452 +1328:2:3453 +1329:2:3464 +1330:0:4844 +1331:2:2881 +1332:0:4844 +1333:2:3473 +1334:2:3474 +1335:2:3478 +1336:2:3479 +1337:2:3487 +1338:2:3488 +1339:2:3492 +1340:2:3493 +1341:2:3501 +1342:2:3506 +1343:2:3510 +1344:2:3511 +1345:2:3519 +1346:2:3520 +1347:2:3524 +1348:2:3525 +1349:2:3519 +1350:2:3520 +1351:2:3524 +1352:2:3525 +1353:2:3533 +1354:2:3538 +1355:2:3539 +1356:2:3550 +1357:2:3551 +1358:2:3552 +1359:2:3563 +1360:2:3568 +1361:2:3569 +1362:2:3580 +1363:2:3581 +1364:2:3582 +1365:2:3580 +1366:2:3581 +1367:2:3582 +1368:2:3593 +1369:2:3600 +1370:0:4844 +1371:2:2881 +1372:0:4844 +1373:2:3604 +1374:2:3605 +1375:2:3606 +1376:2:3618 +1377:2:3619 +1378:2:3623 +1379:2:3624 +1380:2:3632 +1381:2:3637 +1382:2:3641 +1383:2:3642 +1384:2:3650 +1385:2:3651 +1386:2:3655 +1387:2:3656 +1388:2:3650 +1389:2:3651 +1390:2:3655 +1391:2:3656 +1392:2:3664 +1393:2:3669 +1394:2:3670 +1395:2:3681 +1396:2:3682 +1397:2:3683 +1398:2:3694 +1399:2:3699 +1400:2:3700 +1401:2:3711 +1402:2:3712 +1403:2:3713 +1404:2:3711 +1405:2:3712 +1406:2:3713 +1407:2:3724 +1408:2:3734 +1409:2:3735 +1410:0:4844 +1411:2:2881 +1412:0:4844 +1413:2:3741 +1414:0:4844 +1415:2:4563 +1416:2:4564 +1417:2:4568 +1418:2:4572 +1419:2:4573 +1420:2:4577 +1421:2:4585 +1422:2:4586 +1423:2:4590 +1424:2:4594 +1425:2:4595 +1426:2:4590 +1427:2:4594 +1428:2:4595 +1429:2:4599 +1430:2:4606 +1431:2:4613 +1432:2:4614 +1433:2:4621 +1434:2:4626 +1435:2:4633 +1436:2:4634 +1437:2:4633 +1438:2:4634 +1439:2:4641 +1440:2:4645 +1441:0:4844 +1442:2:4650 +1443:0:4844 +1444:2:4651 +1445:0:4844 +1446:2:4652 +1447:0:4844 +1448:1:26 +1449:0:4844 +1450:1:30 +1451:1:31 +1452:1:35 +1453:1:39 +1454:1:40 +1455:1:44 +1456:1:52 +1457:1:53 +1458:1:57 +1459:1:61 +1460:1:62 +1461:1:57 +1462:1:61 +1463:1:62 +1464:1:66 +1465:1:73 +1466:1:80 +1467:1:81 +1468:1:88 +1469:1:93 +1470:1:100 +1471:1:101 +1472:1:100 +1473:1:101 +1474:1:108 +1475:1:112 +1476:0:4844 +1477:1:117 +1478:0:4844 +1479:2:4655 +1480:0:4844 +1481:2:4660 +1482:0:4844 +1483:2:4661 +1484:0:4844 +1485:2:4669 +1486:2:4670 +1487:2:4674 +1488:2:4678 +1489:2:4679 +1490:2:4683 +1491:2:4691 +1492:2:4692 +1493:2:4696 +1494:2:4700 +1495:2:4701 +1496:2:4696 +1497:2:4700 +1498:2:4701 +1499:2:4705 +1500:2:4712 +1501:2:4719 +1502:2:4720 +1503:2:4727 +1504:2:4732 +1505:2:4739 +1506:2:4740 +1507:2:4739 +1508:2:4740 +1509:2:4747 +1510:2:4751 +1511:0:4844 +1512:2:3743 +1513:2:3753 +1514:0:4844 +1515:2:2881 +1516:0:4844 +1517:2:3744 +1518:2:3745 +1519:0:4844 +1520:2:2881 +1521:0:4844 +1522:2:3749 +1523:0:4844 +1524:2:3757 +1525:0:4844 +1526:2:3758 +1527:0:4844 +1528:2:3763 +1529:0:4844 +1530:2:3767 +1531:2:3768 +1532:2:3772 +1533:2:3776 +1534:2:3777 +1535:2:3781 +1536:2:3789 +1537:2:3790 +1538:2:3794 +1539:2:3795 +1540:2:3794 +1541:2:3798 +1542:2:3799 +1543:2:3803 +1544:2:3810 +1545:2:3817 +1546:2:3818 +1547:2:3825 +1548:2:3830 +1549:2:3837 +1550:2:3838 +1551:2:3837 +1552:2:3838 +1553:2:3845 +1554:2:3849 +1555:0:4844 +1556:2:3854 +1557:0:4844 +1558:2:3855 +1559:0:4844 +1560:2:3856 +1561:0:4844 +1562:1:26 +1563:0:4844 +1564:1:30 +1565:1:31 +1566:1:35 +1567:1:39 +1568:1:40 +1569:1:44 +1570:1:52 +1571:1:53 +1572:1:57 +1573:1:61 +1574:1:62 +1575:1:57 +1576:1:61 +1577:1:62 +1578:1:66 +1579:1:73 +1580:1:80 +1581:1:81 +1582:1:88 +1583:1:93 +1584:1:100 +1585:1:101 +1586:1:100 +1587:1:101 +1588:1:108 +1589:1:112 +1590:0:4844 +1591:1:117 +1592:0:4844 +1593:2:3859 +1594:0:4844 +1595:2:3864 +1596:0:4844 +1597:2:3865 +1598:0:4844 +1599:2:3873 +1600:2:3874 +1601:2:3878 +1602:2:3882 +1603:2:3883 +1604:2:3887 +1605:2:3895 +1606:2:3896 +1607:2:3900 +1608:2:3904 +1609:2:3905 +1610:2:3900 +1611:2:3904 +1612:2:3905 +1613:2:3909 +1614:2:3916 +1615:2:3923 +1616:2:3924 +1617:2:3931 +1618:2:3936 +1619:2:3943 +1620:2:3944 +1621:2:3943 +1622:2:3944 +1623:2:3951 +1624:2:3955 +1625:0:4844 +1626:2:3961 +1627:0:4844 +1628:2:3763 +1629:0:4844 +1630:2:3767 +1631:2:3768 +1632:2:3772 +1633:2:3776 +1634:2:3777 +1635:2:3781 +1636:2:3789 +1637:2:3790 +1638:2:3794 +1639:2:3798 +1640:2:3799 +1641:2:3794 +1642:2:3798 +1643:2:3799 +1644:2:3803 +1645:2:3810 +1646:2:3817 +1647:2:3818 +1648:2:3825 +1649:2:3830 +1650:2:3837 +1651:2:3838 +1652:2:3837 +1653:2:3838 +1654:2:3845 +1655:2:3849 +1656:0:4844 +1657:2:3854 +1658:0:4844 +1659:2:3855 +1660:0:4844 +1661:2:3856 +1662:0:4844 +1663:1:26 +-1:-1:-1 +1664:0:4844 +1665:1:30 +1666:1:31 +1667:1:35 +1668:1:39 +1669:1:40 +1670:1:44 +1671:1:52 +1672:1:53 +1673:1:57 +1674:1:61 +1675:1:62 +1676:1:57 +1677:1:61 +1678:1:62 +1679:1:66 +1680:1:73 +1681:1:80 +1682:1:81 +1683:1:88 +1684:1:93 +1685:1:100 +1686:1:101 +1687:1:100 +1688:1:101 +1689:1:108 +1690:1:112 +1691:0:4844 +1692:1:117 +1693:0:4844 +1694:2:3859 +1695:0:4844 +1696:2:3864 +1697:0:4844 +1698:2:3865 +1699:0:4844 +1700:2:3873 +1701:2:3874 +1702:2:3878 +1703:2:3882 +1704:2:3883 +1705:2:3887 +1706:2:3895 +1707:2:3896 +1708:2:3900 +1709:2:3904 +1710:2:3905 +1711:2:3900 +1712:2:3904 +1713:2:3905 +1714:2:3909 +1715:2:3916 +1716:2:3923 +1717:2:3924 +1718:2:3931 +1719:2:3936 +1720:2:3943 +1721:2:3944 +1722:2:3943 +1723:2:3944 +1724:2:3951 +1725:2:3955 +1726:0:4844 +1727:2:3961 +1728:0:4844 +1729:2:3763 +1730:0:4844 +1731:2:3767 +1732:2:3768 +1733:2:3772 +1734:2:3776 +1735:2:3777 +1736:2:3781 +1737:2:3789 +1738:2:3790 +1739:2:3794 +1740:2:3798 +1741:2:3799 +1742:2:3794 +1743:2:3798 +1744:2:3799 +1745:2:3803 +1746:2:3810 +1747:2:3817 +1748:2:3818 +1749:2:3825 +1750:2:3830 +1751:2:3837 +1752:2:3838 +1753:2:3837 +1754:2:3838 +1755:2:3845 +1756:2:3849 +1757:0:4844 +1758:2:3854 +1759:0:4844 +1760:2:3855 +1761:0:4844 +1762:2:3856 +1763:0:4844 +1764:1:26 diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer.define b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer.define new file mode 100644 index 0000000..1e4417f --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer.define @@ -0,0 +1 @@ +#define WRITER_PROGRESS diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer.log b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer.log new file mode 100644 index 0000000..7a8b4c1 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer.log @@ -0,0 +1,581 @@ +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define > pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_progress.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_progress_writer.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -f -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1258) +depth 23: Claim reached state 9 (line 1263) +depth 51: Claim reached state 9 (line 1262) +Depth= 6084 States= 1e+06 Transitions= 2e+08 Memory= 516.838 t= 264 R= 4e+03 +Depth= 7018 States= 2e+06 Transitions= 4.38e+08 Memory= 566.154 t= 585 R= 3e+03 +Depth= 7018 States= 3e+06 Transitions= 6.49e+08 Memory= 616.545 t= 870 R= 3e+03 +pan: resizing hashtable to -w22.. done +Depth= 7018 States= 4e+06 Transitions= 8.46e+08 Memory= 698.447 t= 1.13e+03 R= 4e+03 +Depth= 7018 States= 5e+06 Transitions= 1.29e+09 Memory= 742.979 t= 1.73e+03 R= 3e+03 +Depth= 7018 States= 6e+06 Transitions= 1.8e+09 Memory= 789.170 t= 2.44e+03 R= 2e+03 +Depth= 7018 States= 7e+06 Transitions= 2.27e+09 Memory= 833.506 t= 3.09e+03 R= 2e+03 +Depth= 7018 States= 8e+06 Transitions= 2.76e+09 Memory= 880.283 t= 3.76e+03 R= 2e+03 +Depth= 7018 States= 9e+06 Transitions= 3.05e+09 Memory= 928.135 t= 4.16e+03 R= 2e+03 +pan: resizing hashtable to -w24.. done +Depth= 7018 States= 1e+07 Transitions= 3.3e+09 Memory= 1102.815 t= 4.5e+03 R= 2e+03 +Depth= 7018 States= 1.1e+07 Transitions= 3.74e+09 Memory= 1148.322 t= 5.08e+03 R= 2e+03 +Depth= 7018 States= 1.2e+07 Transitions= 4.65e+09 Memory= 1195.783 t= 6.37e+03 R= 2e+03 +Depth= 7018 States= 1.3e+07 Transitions= 5.63e+09 Memory= 1235.334 t= 7.72e+03 R= 2e+03 +Depth= 7018 States= 1.4e+07 Transitions= 6.21e+09 Memory= 1277.912 t= 8.53e+03 R= 2e+03 +Depth= 7018 States= 1.5e+07 Transitions= 6.77e+09 Memory= 1325.276 t= 9.3e+03 R= 2e+03 +Depth= 7018 States= 1.6e+07 Transitions= 7.05e+09 Memory= 1372.248 t= 9.68e+03 R= 2e+03 +Depth= 7018 States= 1.7e+07 Transitions= 7.66e+09 Memory= 1417.463 t= 1.05e+04 R= 2e+03 +Depth= 7018 States= 1.8e+07 Transitions= 8.25e+09 Memory= 1463.264 t= 1.13e+04 R= 2e+03 +Depth= 7018 States= 1.9e+07 Transitions= 8.65e+09 Memory= 1513.068 t= 1.19e+04 R= 2e+03 +Depth= 7018 States= 2e+07 Transitions= 8.97e+09 Memory= 1561.408 t= 1.23e+04 R= 2e+03 +Depth= 7018 States= 2.1e+07 Transitions= 9.29e+09 Memory= 1609.651 t= 1.28e+04 R= 2e+03 +Depth= 7018 States= 2.2e+07 Transitions= 9.65e+09 Memory= 1659.065 t= 1.33e+04 R= 2e+03 +Depth= 7018 States= 2.3e+07 Transitions= 9.91e+09 Memory= 1708.186 t= 1.36e+04 R= 2e+03 +Depth= 7018 States= 2.4e+07 Transitions= 1.03e+10 Memory= 1757.307 t= 1.41e+04 R= 2e+03 +Depth= 7018 States= 2.5e+07 Transitions= 1.05e+10 Memory= 1807.014 t= 1.45e+04 R= 2e+03 +Depth= 7018 States= 2.6e+07 Transitions= 1.09e+10 Memory= 1856.623 t= 1.49e+04 R= 2e+03 +Depth= 7018 States= 2.7e+07 Transitions= 1.12e+10 Memory= 1906.428 t= 1.54e+04 R= 2e+03 +Depth= 7018 States= 2.8e+07 Transitions= 1.16e+10 Memory= 1951.838 t= 1.59e+04 R= 2e+03 +Depth= 7018 States= 2.9e+07 Transitions= 1.2e+10 Memory= 1998.615 t= 1.65e+04 R= 2e+03 +Depth= 7018 States= 3e+07 Transitions= 1.25e+10 Memory= 2044.026 t= 1.73e+04 R= 2e+03 +Depth= 7018 States= 3.1e+07 Transitions= 1.31e+10 Memory= 2087.971 t= 1.8e+04 R= 2e+03 +Depth= 7018 States= 3.2e+07 Transitions= 1.36e+10 Memory= 2134.455 t= 1.87e+04 R= 2e+03 +Depth= 7018 States= 3.3e+07 Transitions= 1.39e+10 Memory= 2181.818 t= 1.92e+04 R= 2e+03 +Depth= 7018 States= 3.4e+07 Transitions= 1.42e+10 Memory= 2232.795 t= 1.95e+04 R= 2e+03 +pan: resizing hashtable to -w26.. done +Depth= 7018 States= 3.5e+07 Transitions= 1.45e+10 Memory= 2776.338 t= 1.99e+04 R= 2e+03 +Depth= 7018 States= 3.6e+07 Transitions= 1.52e+10 Memory= 2822.041 t= 2.09e+04 R= 2e+03 +Depth= 7018 States= 3.7e+07 Transitions= 1.62e+10 Memory= 2866.182 t= 2.23e+04 R= 2e+03 +Depth= 7018 States= 3.8e+07 Transitions= 1.7e+10 Memory= 2904.365 t= 2.35e+04 R= 2e+03 +Depth= 7018 States= 3.9e+07 Transitions= 1.76e+10 Memory= 2950.361 t= 2.43e+04 R= 2e+03 +Depth= 7018 States= 4e+07 Transitions= 1.79e+10 Memory= 2998.701 t= 2.47e+04 R= 2e+03 +Depth= 7018 States= 4.1e+07 Transitions= 1.84e+10 Memory= 3044.600 t= 2.53e+04 R= 2e+03 +Depth= 7018 States= 4.2e+07 Transitions= 1.89e+10 Memory= 3090.498 t= 2.61e+04 R= 2e+03 +Depth= 7018 States= 4.3e+07 Transitions= 1.95e+10 Memory= 3136.885 t= 2.68e+04 R= 2e+03 +Depth= 7018 States= 4.4e+07 Transitions= 1.98e+10 Memory= 3186.299 t= 2.73e+04 R= 2e+03 +Depth= 7018 States= 4.5e+07 Transitions= 2.01e+10 Memory= 3235.225 t= 2.77e+04 R= 2e+03 +Depth= 7018 States= 4.6e+07 Transitions= 2.04e+10 Memory= 3284.541 t= 2.82e+04 R= 2e+03 +Depth= 7018 States= 4.7e+07 Transitions= 2.08e+10 Memory= 3334.541 t= 2.87e+04 R= 2e+03 +Depth= 7018 States= 4.8e+07 Transitions= 2.11e+10 Memory= 3383.565 t= 2.91e+04 R= 2e+03 +Depth= 7018 States= 4.9e+07 Transitions= 2.14e+10 Memory= 3432.588 t= 2.95e+04 R= 2e+03 +Depth= 7018 States= 5e+07 Transitions= 2.17e+10 Memory= 3483.369 t= 2.99e+04 R= 2e+03 +Depth= 7018 States= 5.1e+07 Transitions= 2.21e+10 Memory= 3532.490 t= 3.04e+04 R= 2e+03 +Depth= 7018 States= 5.2e+07 Transitions= 2.23e+10 Memory= 3580.147 t= 3.07e+04 R= 2e+03 +Depth= 7018 States= 5.3e+07 Transitions= 2.27e+10 Memory= 3625.752 t= 3.13e+04 R= 2e+03 +Depth= 7018 States= 5.4e+07 Transitions= 2.32e+10 Memory= 3671.943 t= 3.2e+04 R= 2e+03 +Depth= 7018 States= 5.5e+07 Transitions= 2.38e+10 Memory= 3715.693 t= 3.27e+04 R= 2e+03 +Depth= 7018 States= 5.6e+07 Transitions= 2.42e+10 Memory= 3762.276 t= 3.33e+04 R= 2e+03 +Depth= 7018 States= 5.7e+07 Transitions= 2.48e+10 Memory= 3808.565 t= 3.41e+04 R= 2e+03 +Depth= 7018 States= 5.8e+07 Transitions= 2.53e+10 Memory= 3855.440 t= 3.48e+04 R= 2e+03 + +(Spin Version 5.1.7 -- 23 December 2008) + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness enabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 7018, errors: 0 + 32735820 states, stored (5.82355e+07 visited) +2.5283515e+10 states, matched +2.534175e+10 transitions (= visited+matched) +1.4761827e+11 atomic steps +hash conflicts: 8.6523014e+09 (resolved) + +Stats on memory usage (in Megabytes): + 3621.440 equivalent memory usage for states (stored*(State-vector + overhead)) + 2898.114 actual memory usage for states (compression: 80.03%) + state-vector as stored = 65 byte + 28 byte overhead + 512.000 memory used for hash table (-w26) + 457.764 memory used for DFS stack (-m10000000) + 1.598 memory lost to fragmentation + 3866.279 total actual memory usage + +unreached in proctype urcu_reader + line 250, "pan.___", state 30, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 52, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 61, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 77, "(1)" + line 231, "pan.___", state 85, "(1)" + line 235, "pan.___", state 97, "(1)" + line 239, "pan.___", state 105, "(1)" + line 395, "pan.___", state 131, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 163, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 177, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 196, "(1)" + line 421, "pan.___", state 226, "(1)" + line 425, "pan.___", state 239, "(1)" + line 670, "pan.___", state 260, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 395, "pan.___", state 267, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 299, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 313, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 332, "(1)" + line 421, "pan.___", state 362, "(1)" + line 425, "pan.___", state 375, "(1)" + line 395, "pan.___", state 396, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 428, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 442, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 461, "(1)" + line 421, "pan.___", state 491, "(1)" + line 425, "pan.___", state 504, "(1)" + line 395, "pan.___", state 527, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 529, "(1)" + line 395, "pan.___", state 530, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 530, "else" + line 395, "pan.___", state 533, "(1)" + line 399, "pan.___", state 541, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 543, "(1)" + line 399, "pan.___", state 544, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 544, "else" + line 399, "pan.___", state 547, "(1)" + line 399, "pan.___", state 548, "(1)" + line 399, "pan.___", state 548, "(1)" + line 397, "pan.___", state 553, "((i<1))" + line 397, "pan.___", state 553, "((i>=1))" + line 404, "pan.___", state 559, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 561, "(1)" + line 404, "pan.___", state 562, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 562, "else" + line 404, "pan.___", state 565, "(1)" + line 404, "pan.___", state 566, "(1)" + line 404, "pan.___", state 566, "(1)" + line 408, "pan.___", state 573, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 575, "(1)" + line 408, "pan.___", state 576, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 576, "else" + line 408, "pan.___", state 579, "(1)" + line 408, "pan.___", state 580, "(1)" + line 408, "pan.___", state 580, "(1)" + line 406, "pan.___", state 585, "((i<2))" + line 406, "pan.___", state 585, "((i>=2))" + line 412, "pan.___", state 592, "(1)" + line 412, "pan.___", state 593, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 593, "else" + line 412, "pan.___", state 596, "(1)" + line 412, "pan.___", state 597, "(1)" + line 412, "pan.___", state 597, "(1)" + line 416, "pan.___", state 605, "(1)" + line 416, "pan.___", state 606, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 606, "else" + line 416, "pan.___", state 609, "(1)" + line 416, "pan.___", state 610, "(1)" + line 416, "pan.___", state 610, "(1)" + line 414, "pan.___", state 615, "((i<1))" + line 414, "pan.___", state 615, "((i>=1))" + line 421, "pan.___", state 622, "(1)" + line 421, "pan.___", state 623, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 623, "else" + line 421, "pan.___", state 626, "(1)" + line 421, "pan.___", state 627, "(1)" + line 421, "pan.___", state 627, "(1)" + line 425, "pan.___", state 635, "(1)" + line 425, "pan.___", state 636, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 636, "else" + line 425, "pan.___", state 639, "(1)" + line 425, "pan.___", state 640, "(1)" + line 425, "pan.___", state 640, "(1)" + line 423, "pan.___", state 645, "((i<2))" + line 423, "pan.___", state 645, "((i>=2))" + line 430, "pan.___", state 649, "(1)" + line 430, "pan.___", state 649, "(1)" + line 670, "pan.___", state 652, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 670, "pan.___", state 653, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 670, "pan.___", state 654, "(1)" + line 395, "pan.___", state 661, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 693, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 707, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 726, "(1)" + line 421, "pan.___", state 756, "(1)" + line 425, "pan.___", state 769, "(1)" + line 395, "pan.___", state 797, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 799, "(1)" + line 395, "pan.___", state 800, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 800, "else" + line 395, "pan.___", state 803, "(1)" + line 399, "pan.___", state 811, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 813, "(1)" + line 399, "pan.___", state 814, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 814, "else" + line 399, "pan.___", state 817, "(1)" + line 399, "pan.___", state 818, "(1)" + line 399, "pan.___", state 818, "(1)" + line 397, "pan.___", state 823, "((i<1))" + line 397, "pan.___", state 823, "((i>=1))" + line 404, "pan.___", state 829, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 831, "(1)" + line 404, "pan.___", state 832, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 832, "else" + line 404, "pan.___", state 835, "(1)" + line 404, "pan.___", state 836, "(1)" + line 404, "pan.___", state 836, "(1)" + line 408, "pan.___", state 843, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 845, "(1)" + line 408, "pan.___", state 846, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 846, "else" + line 408, "pan.___", state 849, "(1)" + line 408, "pan.___", state 850, "(1)" + line 408, "pan.___", state 850, "(1)" + line 406, "pan.___", state 855, "((i<2))" + line 406, "pan.___", state 855, "((i>=2))" + line 412, "pan.___", state 862, "(1)" + line 412, "pan.___", state 863, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 863, "else" + line 412, "pan.___", state 866, "(1)" + line 412, "pan.___", state 867, "(1)" + line 412, "pan.___", state 867, "(1)" + line 416, "pan.___", state 875, "(1)" + line 416, "pan.___", state 876, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 876, "else" + line 416, "pan.___", state 879, "(1)" + line 416, "pan.___", state 880, "(1)" + line 416, "pan.___", state 880, "(1)" + line 414, "pan.___", state 885, "((i<1))" + line 414, "pan.___", state 885, "((i>=1))" + line 421, "pan.___", state 892, "(1)" + line 421, "pan.___", state 893, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 893, "else" + line 421, "pan.___", state 896, "(1)" + line 421, "pan.___", state 897, "(1)" + line 421, "pan.___", state 897, "(1)" + line 425, "pan.___", state 905, "(1)" + line 425, "pan.___", state 906, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 906, "else" + line 425, "pan.___", state 909, "(1)" + line 425, "pan.___", state 910, "(1)" + line 425, "pan.___", state 910, "(1)" + line 430, "pan.___", state 919, "(1)" + line 430, "pan.___", state 919, "(1)" + line 395, "pan.___", state 926, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 928, "(1)" + line 395, "pan.___", state 929, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 929, "else" + line 395, "pan.___", state 932, "(1)" + line 399, "pan.___", state 940, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 942, "(1)" + line 399, "pan.___", state 943, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 943, "else" + line 399, "pan.___", state 946, "(1)" + line 399, "pan.___", state 947, "(1)" + line 399, "pan.___", state 947, "(1)" + line 397, "pan.___", state 952, "((i<1))" + line 397, "pan.___", state 952, "((i>=1))" + line 404, "pan.___", state 958, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 960, "(1)" + line 404, "pan.___", state 961, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 961, "else" + line 404, "pan.___", state 964, "(1)" + line 404, "pan.___", state 965, "(1)" + line 404, "pan.___", state 965, "(1)" + line 408, "pan.___", state 972, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 974, "(1)" + line 408, "pan.___", state 975, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 975, "else" + line 408, "pan.___", state 978, "(1)" + line 408, "pan.___", state 979, "(1)" + line 408, "pan.___", state 979, "(1)" + line 406, "pan.___", state 984, "((i<2))" + line 406, "pan.___", state 984, "((i>=2))" + line 412, "pan.___", state 991, "(1)" + line 412, "pan.___", state 992, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 992, "else" + line 412, "pan.___", state 995, "(1)" + line 412, "pan.___", state 996, "(1)" + line 412, "pan.___", state 996, "(1)" + line 416, "pan.___", state 1004, "(1)" + line 416, "pan.___", state 1005, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 1005, "else" + line 416, "pan.___", state 1008, "(1)" + line 416, "pan.___", state 1009, "(1)" + line 416, "pan.___", state 1009, "(1)" + line 414, "pan.___", state 1014, "((i<1))" + line 414, "pan.___", state 1014, "((i>=1))" + line 421, "pan.___", state 1021, "(1)" + line 421, "pan.___", state 1022, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 1022, "else" + line 421, "pan.___", state 1025, "(1)" + line 421, "pan.___", state 1026, "(1)" + line 421, "pan.___", state 1026, "(1)" + line 425, "pan.___", state 1034, "(1)" + line 425, "pan.___", state 1035, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 1035, "else" + line 425, "pan.___", state 1038, "(1)" + line 425, "pan.___", state 1039, "(1)" + line 425, "pan.___", state 1039, "(1)" + line 423, "pan.___", state 1044, "((i<2))" + line 423, "pan.___", state 1044, "((i>=2))" + line 430, "pan.___", state 1048, "(1)" + line 430, "pan.___", state 1048, "(1)" + line 678, "pan.___", state 1052, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 395, "pan.___", state 1057, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1089, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1103, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1122, "(1)" + line 421, "pan.___", state 1152, "(1)" + line 425, "pan.___", state 1165, "(1)" + line 395, "pan.___", state 1189, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1221, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1235, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1254, "(1)" + line 421, "pan.___", state 1284, "(1)" + line 425, "pan.___", state 1297, "(1)" + line 395, "pan.___", state 1322, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1354, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1368, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1387, "(1)" + line 421, "pan.___", state 1417, "(1)" + line 425, "pan.___", state 1430, "(1)" + line 395, "pan.___", state 1451, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1483, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1497, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1516, "(1)" + line 421, "pan.___", state 1546, "(1)" + line 425, "pan.___", state 1559, "(1)" + line 395, "pan.___", state 1585, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1617, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1631, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1650, "(1)" + line 421, "pan.___", state 1680, "(1)" + line 425, "pan.___", state 1693, "(1)" + line 395, "pan.___", state 1714, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1746, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1760, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1779, "(1)" + line 421, "pan.___", state 1809, "(1)" + line 425, "pan.___", state 1822, "(1)" + line 395, "pan.___", state 1846, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1878, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1892, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1911, "(1)" + line 421, "pan.___", state 1941, "(1)" + line 425, "pan.___", state 1954, "(1)" + line 717, "pan.___", state 1975, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 395, "pan.___", state 1982, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2014, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2028, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2047, "(1)" + line 421, "pan.___", state 2077, "(1)" + line 425, "pan.___", state 2090, "(1)" + line 395, "pan.___", state 2111, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2143, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2157, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2176, "(1)" + line 421, "pan.___", state 2206, "(1)" + line 425, "pan.___", state 2219, "(1)" + line 395, "pan.___", state 2242, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 2244, "(1)" + line 395, "pan.___", state 2245, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 2245, "else" + line 395, "pan.___", state 2248, "(1)" + line 399, "pan.___", state 2256, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2258, "(1)" + line 399, "pan.___", state 2259, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 2259, "else" + line 399, "pan.___", state 2262, "(1)" + line 399, "pan.___", state 2263, "(1)" + line 399, "pan.___", state 2263, "(1)" + line 397, "pan.___", state 2268, "((i<1))" + line 397, "pan.___", state 2268, "((i>=1))" + line 404, "pan.___", state 2274, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2276, "(1)" + line 404, "pan.___", state 2277, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 2277, "else" + line 404, "pan.___", state 2280, "(1)" + line 404, "pan.___", state 2281, "(1)" + line 404, "pan.___", state 2281, "(1)" + line 408, "pan.___", state 2288, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2290, "(1)" + line 408, "pan.___", state 2291, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 2291, "else" + line 408, "pan.___", state 2294, "(1)" + line 408, "pan.___", state 2295, "(1)" + line 408, "pan.___", state 2295, "(1)" + line 406, "pan.___", state 2300, "((i<2))" + line 406, "pan.___", state 2300, "((i>=2))" + line 412, "pan.___", state 2307, "(1)" + line 412, "pan.___", state 2308, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 2308, "else" + line 412, "pan.___", state 2311, "(1)" + line 412, "pan.___", state 2312, "(1)" + line 412, "pan.___", state 2312, "(1)" + line 416, "pan.___", state 2320, "(1)" + line 416, "pan.___", state 2321, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 2321, "else" + line 416, "pan.___", state 2324, "(1)" + line 416, "pan.___", state 2325, "(1)" + line 416, "pan.___", state 2325, "(1)" + line 414, "pan.___", state 2330, "((i<1))" + line 414, "pan.___", state 2330, "((i>=1))" + line 421, "pan.___", state 2337, "(1)" + line 421, "pan.___", state 2338, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 2338, "else" + line 421, "pan.___", state 2341, "(1)" + line 421, "pan.___", state 2342, "(1)" + line 421, "pan.___", state 2342, "(1)" + line 425, "pan.___", state 2350, "(1)" + line 425, "pan.___", state 2351, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 2351, "else" + line 425, "pan.___", state 2354, "(1)" + line 425, "pan.___", state 2355, "(1)" + line 425, "pan.___", state 2355, "(1)" + line 423, "pan.___", state 2360, "((i<2))" + line 423, "pan.___", state 2360, "((i>=2))" + line 430, "pan.___", state 2364, "(1)" + line 430, "pan.___", state 2364, "(1)" + line 717, "pan.___", state 2367, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 717, "pan.___", state 2368, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 717, "pan.___", state 2369, "(1)" + line 395, "pan.___", state 2376, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2408, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2422, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2441, "(1)" + line 421, "pan.___", state 2471, "(1)" + line 425, "pan.___", state 2484, "(1)" + line 395, "pan.___", state 2511, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2543, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2557, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2576, "(1)" + line 421, "pan.___", state 2606, "(1)" + line 425, "pan.___", state 2619, "(1)" + line 395, "pan.___", state 2640, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2672, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2686, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2705, "(1)" + line 421, "pan.___", state 2735, "(1)" + line 425, "pan.___", state 2748, "(1)" + line 227, "pan.___", state 2781, "(1)" + line 235, "pan.___", state 2801, "(1)" + line 239, "pan.___", state 2809, "(1)" + line 227, "pan.___", state 2824, "(1)" + line 235, "pan.___", state 2844, "(1)" + line 239, "pan.___", state 2852, "(1)" + line 877, "pan.___", state 2869, "-end-" + (278 of 2869 states) +unreached in proctype urcu_writer + line 395, "pan.___", state 18, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 32, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 50, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 412, "pan.___", state 83, "(1)" + line 416, "pan.___", state 96, "(1)" + line 421, "pan.___", state 113, "(1)" + line 250, "pan.___", state 149, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 158, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 171, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 211, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 225, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 243, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 257, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 276, "(1)" + line 416, "pan.___", state 289, "(1)" + line 421, "pan.___", state 306, "(1)" + line 425, "pan.___", state 319, "(1)" + line 399, "pan.___", state 356, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 374, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 388, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 420, "(1)" + line 421, "pan.___", state 437, "(1)" + line 425, "pan.___", state 450, "(1)" + line 399, "pan.___", state 494, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 512, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 526, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 558, "(1)" + line 421, "pan.___", state 575, "(1)" + line 425, "pan.___", state 588, "(1)" + line 399, "pan.___", state 623, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 641, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 655, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 687, "(1)" + line 421, "pan.___", state 704, "(1)" + line 425, "pan.___", state 717, "(1)" + line 399, "pan.___", state 754, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 772, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 786, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 818, "(1)" + line 421, "pan.___", state 835, "(1)" + line 425, "pan.___", state 848, "(1)" + line 250, "pan.___", state 903, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 912, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 927, "(1)" + line 262, "pan.___", state 934, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 950, "(1)" + line 231, "pan.___", state 958, "(1)" + line 235, "pan.___", state 970, "(1)" + line 239, "pan.___", state 978, "(1)" + line 250, "pan.___", state 1009, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1018, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1031, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1040, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1056, "(1)" + line 231, "pan.___", state 1064, "(1)" + line 235, "pan.___", state 1076, "(1)" + line 239, "pan.___", state 1084, "(1)" + line 254, "pan.___", state 1110, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1123, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1132, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1148, "(1)" + line 231, "pan.___", state 1156, "(1)" + line 235, "pan.___", state 1168, "(1)" + line 239, "pan.___", state 1176, "(1)" + line 250, "pan.___", state 1207, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1216, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1229, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1238, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1254, "(1)" + line 231, "pan.___", state 1262, "(1)" + line 235, "pan.___", state 1274, "(1)" + line 239, "pan.___", state 1282, "(1)" + line 254, "pan.___", state 1308, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1321, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1330, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1346, "(1)" + line 231, "pan.___", state 1354, "(1)" + line 235, "pan.___", state 1366, "(1)" + line 239, "pan.___", state 1374, "(1)" + line 250, "pan.___", state 1405, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1414, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1427, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1436, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1452, "(1)" + line 231, "pan.___", state 1460, "(1)" + line 235, "pan.___", state 1472, "(1)" + line 239, "pan.___", state 1480, "(1)" + line 254, "pan.___", state 1506, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1519, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1528, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1544, "(1)" + line 231, "pan.___", state 1552, "(1)" + line 235, "pan.___", state 1564, "(1)" + line 239, "pan.___", state 1572, "(1)" + line 250, "pan.___", state 1603, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1612, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1625, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1634, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1650, "(1)" + line 231, "pan.___", state 1658, "(1)" + line 235, "pan.___", state 1670, "(1)" + line 239, "pan.___", state 1678, "(1)" + line 1204, "pan.___", state 1694, "-end-" + (103 of 1694 states) +unreached in proctype :init: + (0 of 78 states) +unreached in proctype :never: + line 1265, "pan.___", state 11, "-end-" + (1 of 11 states) + +pan: elapsed time 3.48e+04 seconds +pan: rate 1671.9756 states/second +pan: avg transition delay 1.3744e-06 usec +cp .input.spin urcu_progress_writer.spin.input +cp .input.spin.trail urcu_progress_writer.spin.input.trail diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer.spin.input b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer.spin.input new file mode 100644 index 0000000..05d09b7 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer.spin.input @@ -0,0 +1,1240 @@ +#define WRITER_PROGRESS + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer.spin.input.trail b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer.spin.input.trail new file mode 100644 index 0000000..e8b02f0 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer.spin.input.trail @@ -0,0 +1,884 @@ +-2:3:-2 +-4:-4:-4 +1:0:4645 +2:3:4565 +3:3:4568 +4:3:4568 +5:3:4571 +6:3:4579 +7:3:4579 +8:3:4582 +9:3:4588 +10:3:4592 +11:3:4592 +12:3:4595 +13:3:4605 +14:3:4613 +15:3:4613 +16:3:4616 +17:3:4622 +18:3:4626 +19:3:4626 +20:3:4629 +21:3:4635 +22:3:4639 +23:3:4640 +24:0:4645 +25:3:4642 +26:0:4645 +27:2:2873 +28:0:4645 +29:2:2879 +30:0:4645 +31:2:2880 +32:0:4645 +33:2:2881 +34:0:4643 +35:2:2882 +36:0:4649 +37:2:2883 +38:0:4649 +39:2:2884 +40:2:2885 +41:2:2889 +42:2:2890 +43:2:2898 +44:2:2899 +45:2:2903 +46:2:2904 +47:2:2912 +48:2:2917 +49:2:2921 +50:2:2922 +51:2:2930 +52:2:2931 +53:2:2935 +54:2:2936 +55:2:2930 +56:2:2931 +57:2:2935 +58:2:2936 +59:2:2944 +60:2:2949 +61:2:2950 +62:2:2961 +63:2:2962 +64:2:2963 +65:2:2974 +66:2:2979 +67:2:2980 +68:2:2991 +69:2:2992 +70:2:2993 +71:2:2991 +72:2:2992 +73:2:2993 +74:2:3004 +75:2:3012 +76:0:4649 +77:2:2883 +78:0:4649 +79:2:3016 +80:2:3020 +81:2:3021 +82:2:3025 +83:2:3029 +84:2:3030 +85:2:3034 +86:2:3042 +87:2:3043 +88:2:3047 +89:2:3051 +90:2:3052 +91:2:3047 +92:2:3048 +93:2:3056 +94:0:4649 +95:2:2883 +96:0:4649 +97:2:3064 +98:2:3065 +99:2:3066 +100:0:4649 +101:2:2883 +102:0:4649 +103:2:3071 +104:0:4649 +105:2:3774 +106:2:3775 +107:2:3779 +108:2:3783 +109:2:3784 +110:2:3788 +111:2:3793 +112:2:3801 +113:2:3805 +114:2:3806 +115:2:3801 +116:2:3805 +117:2:3806 +118:2:3810 +119:2:3817 +120:2:3824 +121:2:3825 +122:2:3832 +123:2:3837 +124:2:3844 +125:2:3845 +126:2:3844 +127:2:3845 +128:2:3852 +129:2:3856 +130:0:4649 +131:2:3861 +132:0:4649 +133:2:3862 +134:0:4649 +135:2:3863 +136:0:4649 +137:2:3864 +138:0:4649 +139:1:2 +140:0:4649 +141:2:3865 +142:0:4649 +143:1:8 +144:0:4649 +145:1:9 +146:0:4649 +147:2:3864 +148:0:4649 +149:2:3865 +150:0:4649 +151:1:10 +152:0:4649 +153:2:3864 +154:0:4649 +155:2:3865 +156:0:4649 +157:1:11 +158:0:4649 +159:2:3864 +160:0:4649 +161:2:3865 +162:0:4649 +163:1:12 +164:0:4649 +165:2:3864 +166:0:4649 +167:2:3865 +168:0:4649 +169:1:13 +170:0:4649 +171:2:3864 +172:0:4649 +173:2:3865 +174:0:4649 +175:1:14 +176:0:4649 +177:1:15 +178:0:4649 +179:1:23 +180:0:4649 +181:1:24 +182:0:4649 +183:2:3864 +184:0:4649 +185:2:3865 +186:0:4649 +187:1:128 +188:1:129 +189:1:133 +190:1:134 +191:1:142 +192:1:143 +193:1:147 +194:1:148 +195:1:156 +196:1:161 +197:1:165 +198:1:166 +199:1:174 +200:1:175 +201:1:179 +202:1:180 +203:1:174 +204:1:175 +205:1:179 +206:1:180 +207:1:188 +208:1:193 +209:1:194 +210:1:205 +211:1:206 +212:1:207 +213:1:218 +214:1:223 +215:1:224 +216:1:235 +217:1:236 +218:1:237 +219:1:235 +220:1:236 +221:1:237 +222:1:248 +223:0:4649 +224:1:15 +225:0:4649 +226:1:23 +227:0:4649 +228:1:24 +229:0:4649 +230:2:3864 +231:0:4649 +232:2:3865 +233:0:4649 +234:1:257 +235:1:258 +236:0:4649 +237:1:15 +238:0:4649 +239:1:23 +240:0:4649 +241:1:24 +242:0:4649 +243:2:3864 +244:0:4649 +245:2:3865 +246:0:4649 +247:1:264 +248:1:265 +249:1:269 +250:1:270 +251:1:278 +252:1:279 +253:1:283 +254:1:284 +255:1:292 +256:1:297 +257:1:301 +258:1:302 +259:1:310 +260:1:311 +261:1:315 +262:1:316 +263:1:310 +264:1:311 +265:1:315 +266:1:316 +267:1:324 +268:1:329 +269:1:330 +270:1:341 +271:1:342 +272:1:343 +273:1:354 +274:1:359 +275:1:360 +276:1:371 +277:1:372 +278:1:373 +279:1:371 +280:1:372 +281:1:373 +282:1:384 +283:0:4649 +284:1:15 +285:0:4649 +286:1:23 +287:0:4649 +288:1:24 +289:0:4649 +290:2:3864 +291:0:4649 +292:2:3865 +293:0:4649 +294:1:393 +295:1:394 +296:1:398 +297:1:399 +298:1:407 +299:1:408 +300:1:412 +301:1:413 +302:1:421 +303:1:426 +304:1:430 +305:1:431 +306:1:439 +307:1:440 +308:1:444 +309:1:445 +310:1:439 +311:1:440 +312:1:444 +313:1:445 +314:1:453 +315:1:458 +316:1:459 +317:1:470 +318:1:471 +319:1:472 +320:1:483 +321:1:488 +322:1:489 +323:1:500 +324:1:501 +325:1:502 +326:1:500 +327:1:501 +328:1:502 +329:1:513 +330:1:520 +331:0:4649 +332:1:15 +333:0:4649 +334:1:16 +335:0:4649 +336:2:3864 +337:0:4649 +338:2:3865 +339:0:4649 +340:1:17 +341:0:4649 +342:2:3864 +343:0:4649 +344:2:3865 +345:0:4649 +346:1:28 +347:0:4649 +348:2:3864 +349:0:4649 +350:2:3865 +351:0:4649 +352:1:32 +353:1:33 +354:1:37 +355:1:38 +356:1:46 +357:1:54 +358:1:55 +359:1:59 +360:1:63 +361:1:64 +362:1:59 +363:1:63 +364:1:64 +365:1:68 +366:1:75 +367:1:82 +368:1:83 +369:1:90 +370:1:95 +371:1:102 +372:1:103 +373:1:102 +374:1:103 +375:1:110 +376:1:114 +377:0:4649 +378:2:3864 +379:0:4649 +380:2:3865 +381:0:4649 +382:1:119 +383:0:4649 +384:2:3866 +385:0:4649 +386:2:3871 +387:0:4649 +388:2:3872 +389:0:4649 +390:2:3880 +391:2:3881 +392:2:3885 +393:2:3889 +394:2:3890 +395:2:3894 +396:2:3902 +397:2:3903 +398:2:3907 +399:2:3911 +400:2:3912 +401:2:3907 +402:2:3911 +403:2:3912 +404:2:3916 +405:2:3923 +406:2:3930 +407:2:3931 +408:2:3938 +409:2:3943 +410:2:3950 +411:2:3951 +412:2:3950 +413:2:3951 +414:2:3958 +415:2:3962 +416:0:4649 +417:2:3073 +418:2:3755 +419:0:4649 +420:2:2883 +421:0:4649 +422:2:3074 +423:0:4649 +424:2:2883 +425:0:4649 +426:2:3077 +427:2:3078 +428:2:3082 +429:2:3083 +430:2:3091 +431:2:3092 +432:2:3096 +433:2:3097 +434:2:3105 +435:2:3110 +436:2:3114 +437:2:3115 +438:2:3123 +439:2:3124 +440:2:3128 +441:2:3129 +442:2:3123 +443:2:3124 +444:2:3128 +445:2:3129 +446:2:3137 +447:2:3142 +448:2:3143 +449:2:3154 +450:2:3155 +451:2:3156 +452:2:3167 +453:2:3172 +454:2:3173 +455:2:3184 +456:2:3185 +457:2:3186 +458:2:3184 +459:2:3185 +460:2:3186 +461:2:3197 +462:2:3204 +463:0:4649 +464:2:2883 +465:0:4649 +466:2:3208 +467:2:3209 +468:2:3210 +469:2:3222 +470:2:3223 +471:2:3227 +472:2:3228 +473:2:3236 +474:2:3241 +475:2:3245 +476:2:3246 +477:2:3254 +478:2:3255 +479:2:3259 +480:2:3260 +481:2:3254 +482:2:3255 +483:2:3259 +484:2:3260 +485:2:3268 +486:2:3273 +487:2:3274 +488:2:3285 +489:2:3286 +490:2:3287 +491:2:3298 +492:2:3303 +493:2:3304 +494:2:3315 +495:2:3316 +496:2:3317 +497:2:3315 +498:2:3316 +499:2:3317 +500:2:3328 +501:2:3337 +502:0:4649 +503:2:2883 +504:0:4649 +505:2:3343 +506:0:4649 +507:2:3972 +508:2:3973 +509:2:3977 +510:2:3981 +511:2:3982 +512:2:3986 +513:2:3994 +514:2:3995 +515:2:3999 +516:2:4003 +517:2:4004 +518:2:3999 +519:2:4003 +520:2:4004 +521:2:4008 +522:2:4015 +523:2:4022 +524:2:4023 +525:2:4030 +526:2:4035 +527:2:4042 +528:2:4043 +529:2:4042 +530:2:4043 +531:2:4050 +532:2:4054 +533:0:4649 +534:2:4059 +535:0:4649 +536:2:4060 +537:0:4649 +538:2:4061 +539:0:4649 +540:2:4062 +541:0:4649 +542:1:28 +543:0:4649 +544:2:4063 +545:0:4649 +546:2:4062 +547:0:4649 +548:1:32 +549:1:33 +550:1:37 +551:1:41 +552:1:42 +553:1:46 +554:1:54 +555:1:55 +556:1:59 +557:1:63 +558:1:64 +559:1:59 +560:1:63 +561:1:64 +562:1:68 +563:1:75 +564:1:82 +565:1:83 +566:1:90 +567:1:95 +568:1:102 +569:1:103 +570:1:102 +571:1:103 +572:1:110 +573:1:114 +-1:-1:-1 +574:0:4649 +575:2:4063 +576:0:4649 +577:2:4062 +578:0:4649 +579:1:119 +580:0:4649 +581:2:4063 +582:0:4649 +583:2:4064 +584:0:4649 +585:2:4069 +586:0:4649 +587:2:4070 +588:0:4649 +589:2:4078 +590:2:4079 +591:2:4083 +592:2:4087 +593:2:4088 +594:2:4092 +595:2:4100 +596:2:4101 +597:2:4105 +598:2:4109 +599:2:4110 +600:2:4105 +601:2:4109 +602:2:4110 +603:2:4114 +604:2:4121 +605:2:4128 +606:2:4129 +607:2:4136 +608:2:4141 +609:2:4148 +610:2:4149 +611:2:4148 +612:2:4149 +613:2:4156 +614:2:4160 +615:0:4649 +616:2:3345 +617:2:3755 +618:0:4649 +619:2:2883 +620:0:4649 +621:2:3208 +622:2:3209 +623:2:3213 +624:2:3214 +625:2:3222 +626:2:3223 +627:2:3227 +628:2:3228 +629:2:3236 +630:2:3241 +631:2:3245 +632:2:3246 +633:2:3254 +634:2:3255 +635:2:3259 +636:2:3260 +637:2:3254 +638:2:3255 +639:2:3259 +640:2:3260 +641:2:3268 +642:2:3273 +643:2:3274 +644:2:3285 +645:2:3286 +646:2:3287 +647:2:3298 +648:2:3303 +649:2:3304 +650:2:3315 +651:2:3316 +652:2:3317 +653:2:3315 +654:2:3316 +655:2:3317 +656:2:3328 +657:2:3337 +658:0:4649 +659:2:2883 +660:0:4649 +661:2:3343 +662:0:4649 +663:2:3972 +664:2:3973 +665:2:3977 +666:2:3981 +667:2:3982 +668:2:3986 +669:2:3994 +670:2:3995 +671:2:3999 +672:2:4003 +673:2:4004 +674:2:3999 +675:2:4003 +676:2:4004 +677:2:4008 +678:2:4015 +679:2:4022 +680:2:4023 +681:2:4030 +682:2:4035 +683:2:4042 +684:2:4043 +685:2:4042 +686:2:4043 +687:2:4050 +688:2:4054 +689:0:4649 +690:2:4059 +691:0:4649 +692:2:4060 +693:0:4649 +694:2:4061 +695:0:4649 +696:2:4062 +697:0:4649 +698:1:28 +699:0:4649 +700:2:4063 +701:0:4649 +702:1:32 +703:1:33 +704:1:37 +705:1:41 +706:1:42 +707:1:46 +708:1:54 +709:1:55 +710:1:59 +711:1:63 +712:1:64 +713:1:59 +714:1:63 +715:1:64 +716:1:68 +717:1:75 +718:1:82 +719:1:83 +720:1:90 +721:1:95 +722:1:102 +723:1:103 +724:1:102 +725:1:103 +726:1:110 +727:1:114 +728:0:4649 +729:2:4062 +730:0:4649 +731:2:4063 +732:0:4649 +733:1:119 +734:0:4649 +735:2:4064 +736:0:4649 +737:2:4069 +738:0:4649 +739:2:4070 +740:0:4649 +741:2:4078 +742:2:4079 +743:2:4083 +744:2:4087 +745:2:4088 +746:2:4092 +747:2:4100 +748:2:4101 +749:2:4105 +750:2:4109 +751:2:4110 +752:2:4105 +753:2:4109 +754:2:4110 +755:2:4114 +756:2:4121 +757:2:4128 +758:2:4129 +759:2:4136 +760:2:4141 +761:2:4148 +762:2:4149 +763:2:4148 +764:2:4149 +765:2:4156 +766:2:4160 +767:0:4649 +768:2:3345 +769:2:3755 +770:0:4649 +771:2:2883 +772:0:4649 +773:2:3208 +774:2:3209 +775:2:3213 +776:2:3214 +777:2:3222 +778:2:3223 +779:2:3227 +780:2:3228 +781:2:3236 +782:2:3241 +783:2:3245 +784:2:3246 +785:2:3254 +786:2:3255 +787:2:3259 +788:2:3260 +789:2:3254 +790:2:3255 +791:2:3259 +792:2:3260 +793:2:3268 +794:2:3273 +795:2:3274 +796:2:3285 +797:2:3286 +798:2:3287 +799:2:3298 +800:2:3303 +801:2:3304 +802:2:3315 +803:2:3316 +804:2:3317 +805:2:3315 +806:2:3316 +807:2:3317 +808:2:3328 +809:2:3337 +810:0:4649 +811:2:2883 +812:0:4649 +813:2:3343 +814:0:4649 +815:2:3972 +816:2:3973 +817:2:3977 +818:2:3981 +819:2:3982 +820:2:3986 +821:2:3994 +822:2:3995 +823:2:3999 +824:2:4003 +825:2:4004 +826:2:3999 +827:2:4003 +828:2:4004 +829:2:4008 +830:2:4015 +831:2:4022 +832:2:4023 +833:2:4030 +834:2:4035 +835:2:4042 +836:2:4043 +837:2:4042 +838:2:4043 +839:2:4050 +840:2:4054 +841:0:4649 +842:2:4059 +843:0:4649 +844:2:4060 +845:0:4649 +846:2:4061 +847:0:4649 +848:2:4062 +849:0:4649 +850:1:28 +851:0:4649 +852:2:4063 +853:0:4649 +854:2:4062 +855:0:4649 +856:1:32 +857:1:33 +858:1:37 +859:1:41 +860:1:42 +861:1:46 +862:1:54 +863:1:55 +864:1:59 +865:1:63 +866:1:64 +867:1:59 +868:1:63 +869:1:64 +870:1:68 +871:1:75 +872:1:82 +873:1:83 +874:1:90 +875:1:95 +876:1:102 +877:1:103 +878:1:102 +879:1:103 +880:1:110 +881:1:114 diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer_error.define b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer_error.define new file mode 100644 index 0000000..8d304f5 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer_error.define @@ -0,0 +1,2 @@ +#define WRITER_PROGRESS +#define GEN_ERROR_WRITER_PROGRESS diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer_error.log b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer_error.log new file mode 100644 index 0000000..499062a --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer_error.log @@ -0,0 +1,556 @@ +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define > pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_progress.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_progress_writer_error.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -f -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1259) +depth 23: Claim reached state 9 (line 1264) +depth 51: Claim reached state 9 (line 1263) +pan: acceptance cycle (at depth 1669) +pan: wrote .input.spin.trail + +(Spin Version 5.1.7 -- 23 December 2008) +Warning: Search not completed + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness enabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 4939, errors: 1 + 565131 states, stored (936882 visited) +1.8676179e+08 states, matched +1.8769867e+08 transitions (= visited+matched) +1.0114449e+09 atomic steps +hash conflicts: 18464180 (resolved) + +Stats on memory usage (in Megabytes): + 62.518 equivalent memory usage for states (stored*(State-vector + overhead)) + 48.226 actual memory usage for states (compression: 77.14%) + state-vector as stored = 61 byte + 28 byte overhead + 8.000 memory used for hash table (-w20) + 457.764 memory used for DFS stack (-m10000000) + 513.908 total actual memory usage + +unreached in proctype urcu_reader + line 251, "pan.___", state 30, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 259, "pan.___", state 52, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 263, "pan.___", state 61, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 228, "pan.___", state 77, "(1)" + line 232, "pan.___", state 85, "(1)" + line 236, "pan.___", state 97, "(1)" + line 240, "pan.___", state 105, "(1)" + line 396, "pan.___", state 131, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 163, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 177, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 196, "(1)" + line 422, "pan.___", state 226, "(1)" + line 426, "pan.___", state 239, "(1)" + line 671, "pan.___", state 260, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 396, "pan.___", state 267, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 299, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 313, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 332, "(1)" + line 422, "pan.___", state 362, "(1)" + line 426, "pan.___", state 375, "(1)" + line 396, "pan.___", state 396, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 428, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 442, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 461, "(1)" + line 422, "pan.___", state 491, "(1)" + line 426, "pan.___", state 504, "(1)" + line 396, "pan.___", state 527, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 529, "(1)" + line 396, "pan.___", state 530, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 530, "else" + line 396, "pan.___", state 533, "(1)" + line 400, "pan.___", state 541, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 543, "(1)" + line 400, "pan.___", state 544, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 400, "pan.___", state 544, "else" + line 400, "pan.___", state 547, "(1)" + line 400, "pan.___", state 548, "(1)" + line 400, "pan.___", state 548, "(1)" + line 398, "pan.___", state 553, "((i<1))" + line 398, "pan.___", state 553, "((i>=1))" + line 405, "pan.___", state 559, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 561, "(1)" + line 405, "pan.___", state 562, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 405, "pan.___", state 562, "else" + line 405, "pan.___", state 565, "(1)" + line 405, "pan.___", state 566, "(1)" + line 405, "pan.___", state 566, "(1)" + line 409, "pan.___", state 573, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 575, "(1)" + line 409, "pan.___", state 576, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 409, "pan.___", state 576, "else" + line 409, "pan.___", state 579, "(1)" + line 409, "pan.___", state 580, "(1)" + line 409, "pan.___", state 580, "(1)" + line 407, "pan.___", state 585, "((i<2))" + line 407, "pan.___", state 585, "((i>=2))" + line 413, "pan.___", state 592, "(1)" + line 413, "pan.___", state 593, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 593, "else" + line 413, "pan.___", state 596, "(1)" + line 413, "pan.___", state 597, "(1)" + line 413, "pan.___", state 597, "(1)" + line 417, "pan.___", state 605, "(1)" + line 417, "pan.___", state 606, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 417, "pan.___", state 606, "else" + line 417, "pan.___", state 609, "(1)" + line 417, "pan.___", state 610, "(1)" + line 417, "pan.___", state 610, "(1)" + line 415, "pan.___", state 615, "((i<1))" + line 415, "pan.___", state 615, "((i>=1))" + line 422, "pan.___", state 622, "(1)" + line 422, "pan.___", state 623, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 422, "pan.___", state 623, "else" + line 422, "pan.___", state 626, "(1)" + line 422, "pan.___", state 627, "(1)" + line 422, "pan.___", state 627, "(1)" + line 426, "pan.___", state 635, "(1)" + line 426, "pan.___", state 636, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 426, "pan.___", state 636, "else" + line 426, "pan.___", state 639, "(1)" + line 426, "pan.___", state 640, "(1)" + line 426, "pan.___", state 640, "(1)" + line 424, "pan.___", state 645, "((i<2))" + line 424, "pan.___", state 645, "((i>=2))" + line 431, "pan.___", state 649, "(1)" + line 431, "pan.___", state 649, "(1)" + line 671, "pan.___", state 652, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 671, "pan.___", state 653, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 671, "pan.___", state 654, "(1)" + line 396, "pan.___", state 661, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 693, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 707, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 726, "(1)" + line 422, "pan.___", state 756, "(1)" + line 426, "pan.___", state 769, "(1)" + line 396, "pan.___", state 797, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 799, "(1)" + line 396, "pan.___", state 800, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 800, "else" + line 396, "pan.___", state 803, "(1)" + line 400, "pan.___", state 811, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 813, "(1)" + line 400, "pan.___", state 814, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 400, "pan.___", state 814, "else" + line 400, "pan.___", state 817, "(1)" + line 400, "pan.___", state 818, "(1)" + line 400, "pan.___", state 818, "(1)" + line 398, "pan.___", state 823, "((i<1))" + line 398, "pan.___", state 823, "((i>=1))" + line 405, "pan.___", state 829, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 831, "(1)" + line 405, "pan.___", state 832, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 405, "pan.___", state 832, "else" + line 405, "pan.___", state 835, "(1)" + line 405, "pan.___", state 836, "(1)" + line 405, "pan.___", state 836, "(1)" + line 409, "pan.___", state 843, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 845, "(1)" + line 409, "pan.___", state 846, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 409, "pan.___", state 846, "else" + line 409, "pan.___", state 849, "(1)" + line 409, "pan.___", state 850, "(1)" + line 409, "pan.___", state 850, "(1)" + line 407, "pan.___", state 855, "((i<2))" + line 407, "pan.___", state 855, "((i>=2))" + line 413, "pan.___", state 862, "(1)" + line 413, "pan.___", state 863, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 863, "else" + line 413, "pan.___", state 866, "(1)" + line 413, "pan.___", state 867, "(1)" + line 413, "pan.___", state 867, "(1)" + line 417, "pan.___", state 875, "(1)" + line 417, "pan.___", state 876, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 417, "pan.___", state 876, "else" + line 417, "pan.___", state 879, "(1)" + line 417, "pan.___", state 880, "(1)" + line 417, "pan.___", state 880, "(1)" + line 415, "pan.___", state 885, "((i<1))" + line 415, "pan.___", state 885, "((i>=1))" + line 422, "pan.___", state 892, "(1)" + line 422, "pan.___", state 893, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 422, "pan.___", state 893, "else" + line 422, "pan.___", state 896, "(1)" + line 422, "pan.___", state 897, "(1)" + line 422, "pan.___", state 897, "(1)" + line 426, "pan.___", state 905, "(1)" + line 426, "pan.___", state 906, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 426, "pan.___", state 906, "else" + line 426, "pan.___", state 909, "(1)" + line 426, "pan.___", state 910, "(1)" + line 426, "pan.___", state 910, "(1)" + line 431, "pan.___", state 919, "(1)" + line 431, "pan.___", state 919, "(1)" + line 396, "pan.___", state 926, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 928, "(1)" + line 396, "pan.___", state 929, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 929, "else" + line 396, "pan.___", state 932, "(1)" + line 400, "pan.___", state 940, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 942, "(1)" + line 400, "pan.___", state 943, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 400, "pan.___", state 943, "else" + line 400, "pan.___", state 946, "(1)" + line 400, "pan.___", state 947, "(1)" + line 400, "pan.___", state 947, "(1)" + line 398, "pan.___", state 952, "((i<1))" + line 398, "pan.___", state 952, "((i>=1))" + line 405, "pan.___", state 958, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 960, "(1)" + line 405, "pan.___", state 961, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 405, "pan.___", state 961, "else" + line 405, "pan.___", state 964, "(1)" + line 405, "pan.___", state 965, "(1)" + line 405, "pan.___", state 965, "(1)" + line 409, "pan.___", state 972, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 974, "(1)" + line 409, "pan.___", state 975, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 409, "pan.___", state 975, "else" + line 409, "pan.___", state 978, "(1)" + line 409, "pan.___", state 979, "(1)" + line 409, "pan.___", state 979, "(1)" + line 407, "pan.___", state 984, "((i<2))" + line 407, "pan.___", state 984, "((i>=2))" + line 413, "pan.___", state 991, "(1)" + line 413, "pan.___", state 992, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 992, "else" + line 413, "pan.___", state 995, "(1)" + line 413, "pan.___", state 996, "(1)" + line 413, "pan.___", state 996, "(1)" + line 417, "pan.___", state 1004, "(1)" + line 417, "pan.___", state 1005, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 417, "pan.___", state 1005, "else" + line 417, "pan.___", state 1008, "(1)" + line 417, "pan.___", state 1009, "(1)" + line 417, "pan.___", state 1009, "(1)" + line 415, "pan.___", state 1014, "((i<1))" + line 415, "pan.___", state 1014, "((i>=1))" + line 422, "pan.___", state 1021, "(1)" + line 422, "pan.___", state 1022, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 422, "pan.___", state 1022, "else" + line 422, "pan.___", state 1025, "(1)" + line 422, "pan.___", state 1026, "(1)" + line 422, "pan.___", state 1026, "(1)" + line 426, "pan.___", state 1034, "(1)" + line 426, "pan.___", state 1035, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 426, "pan.___", state 1035, "else" + line 426, "pan.___", state 1038, "(1)" + line 426, "pan.___", state 1039, "(1)" + line 426, "pan.___", state 1039, "(1)" + line 424, "pan.___", state 1044, "((i<2))" + line 424, "pan.___", state 1044, "((i>=2))" + line 431, "pan.___", state 1048, "(1)" + line 431, "pan.___", state 1048, "(1)" + line 679, "pan.___", state 1052, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 396, "pan.___", state 1057, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1089, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 1103, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 1122, "(1)" + line 422, "pan.___", state 1152, "(1)" + line 426, "pan.___", state 1165, "(1)" + line 396, "pan.___", state 1189, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1221, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 1235, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 1254, "(1)" + line 422, "pan.___", state 1284, "(1)" + line 426, "pan.___", state 1297, "(1)" + line 396, "pan.___", state 1322, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1354, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 1368, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 1387, "(1)" + line 422, "pan.___", state 1417, "(1)" + line 426, "pan.___", state 1430, "(1)" + line 396, "pan.___", state 1451, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1483, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 1497, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 1516, "(1)" + line 422, "pan.___", state 1546, "(1)" + line 426, "pan.___", state 1559, "(1)" + line 396, "pan.___", state 1585, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1617, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 1631, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 1650, "(1)" + line 422, "pan.___", state 1680, "(1)" + line 426, "pan.___", state 1693, "(1)" + line 396, "pan.___", state 1714, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1746, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 1760, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 1779, "(1)" + line 422, "pan.___", state 1809, "(1)" + line 426, "pan.___", state 1822, "(1)" + line 396, "pan.___", state 1846, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1878, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 1892, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 1911, "(1)" + line 422, "pan.___", state 1941, "(1)" + line 426, "pan.___", state 1954, "(1)" + line 718, "pan.___", state 1975, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 396, "pan.___", state 1982, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 2014, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 2028, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 2047, "(1)" + line 422, "pan.___", state 2077, "(1)" + line 426, "pan.___", state 2090, "(1)" + line 396, "pan.___", state 2111, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 2143, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 2157, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 2176, "(1)" + line 422, "pan.___", state 2206, "(1)" + line 426, "pan.___", state 2219, "(1)" + line 396, "pan.___", state 2242, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2244, "(1)" + line 396, "pan.___", state 2245, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 2245, "else" + line 396, "pan.___", state 2248, "(1)" + line 400, "pan.___", state 2256, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2258, "(1)" + line 400, "pan.___", state 2259, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 400, "pan.___", state 2259, "else" + line 400, "pan.___", state 2262, "(1)" + line 400, "pan.___", state 2263, "(1)" + line 400, "pan.___", state 2263, "(1)" + line 398, "pan.___", state 2268, "((i<1))" + line 398, "pan.___", state 2268, "((i>=1))" + line 405, "pan.___", state 2274, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 2276, "(1)" + line 405, "pan.___", state 2277, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 405, "pan.___", state 2277, "else" + line 405, "pan.___", state 2280, "(1)" + line 405, "pan.___", state 2281, "(1)" + line 405, "pan.___", state 2281, "(1)" + line 409, "pan.___", state 2288, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 2290, "(1)" + line 409, "pan.___", state 2291, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 409, "pan.___", state 2291, "else" + line 409, "pan.___", state 2294, "(1)" + line 409, "pan.___", state 2295, "(1)" + line 409, "pan.___", state 2295, "(1)" + line 407, "pan.___", state 2300, "((i<2))" + line 407, "pan.___", state 2300, "((i>=2))" + line 413, "pan.___", state 2307, "(1)" + line 413, "pan.___", state 2308, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 2308, "else" + line 413, "pan.___", state 2311, "(1)" + line 413, "pan.___", state 2312, "(1)" + line 413, "pan.___", state 2312, "(1)" + line 417, "pan.___", state 2320, "(1)" + line 417, "pan.___", state 2321, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 417, "pan.___", state 2321, "else" + line 417, "pan.___", state 2324, "(1)" + line 417, "pan.___", state 2325, "(1)" + line 417, "pan.___", state 2325, "(1)" + line 415, "pan.___", state 2330, "((i<1))" + line 415, "pan.___", state 2330, "((i>=1))" + line 422, "pan.___", state 2337, "(1)" + line 422, "pan.___", state 2338, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 422, "pan.___", state 2338, "else" + line 422, "pan.___", state 2341, "(1)" + line 422, "pan.___", state 2342, "(1)" + line 422, "pan.___", state 2342, "(1)" + line 426, "pan.___", state 2350, "(1)" + line 426, "pan.___", state 2351, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 426, "pan.___", state 2351, "else" + line 426, "pan.___", state 2354, "(1)" + line 426, "pan.___", state 2355, "(1)" + line 426, "pan.___", state 2355, "(1)" + line 424, "pan.___", state 2360, "((i<2))" + line 424, "pan.___", state 2360, "((i>=2))" + line 431, "pan.___", state 2364, "(1)" + line 431, "pan.___", state 2364, "(1)" + line 718, "pan.___", state 2367, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 718, "pan.___", state 2368, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 718, "pan.___", state 2369, "(1)" + line 396, "pan.___", state 2376, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 2408, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 2422, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 2441, "(1)" + line 422, "pan.___", state 2471, "(1)" + line 426, "pan.___", state 2484, "(1)" + line 396, "pan.___", state 2511, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 2543, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 2557, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 2576, "(1)" + line 422, "pan.___", state 2606, "(1)" + line 426, "pan.___", state 2619, "(1)" + line 396, "pan.___", state 2640, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 2672, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 2686, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 2705, "(1)" + line 422, "pan.___", state 2735, "(1)" + line 426, "pan.___", state 2748, "(1)" + line 228, "pan.___", state 2781, "(1)" + line 236, "pan.___", state 2801, "(1)" + line 240, "pan.___", state 2809, "(1)" + line 228, "pan.___", state 2824, "(1)" + line 236, "pan.___", state 2844, "(1)" + line 240, "pan.___", state 2852, "(1)" + line 878, "pan.___", state 2869, "-end-" + (278 of 2869 states) +unreached in proctype urcu_writer + line 396, "pan.___", state 18, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 32, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 50, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 413, "pan.___", state 83, "(1)" + line 417, "pan.___", state 96, "(1)" + line 422, "pan.___", state 113, "(1)" + line 251, "pan.___", state 149, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 255, "pan.___", state 158, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 259, "pan.___", state 171, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 211, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 225, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 243, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 257, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 276, "(1)" + line 417, "pan.___", state 289, "(1)" + line 422, "pan.___", state 306, "(1)" + line 426, "pan.___", state 319, "(1)" + line 400, "pan.___", state 356, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 374, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 388, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 417, "pan.___", state 420, "(1)" + line 422, "pan.___", state 437, "(1)" + line 426, "pan.___", state 450, "(1)" + line 396, "pan.___", state 477, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 479, "(1)" + line 396, "pan.___", state 480, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 480, "else" + line 396, "pan.___", state 483, "(1)" + line 400, "pan.___", state 491, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 493, "(1)" + line 400, "pan.___", state 494, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 400, "pan.___", state 494, "else" + line 400, "pan.___", state 497, "(1)" + line 400, "pan.___", state 498, "(1)" + line 400, "pan.___", state 498, "(1)" + line 398, "pan.___", state 503, "((i<1))" + line 398, "pan.___", state 503, "((i>=1))" + line 405, "pan.___", state 509, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 511, "(1)" + line 405, "pan.___", state 512, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 405, "pan.___", state 512, "else" + line 405, "pan.___", state 515, "(1)" + line 405, "pan.___", state 516, "(1)" + line 405, "pan.___", state 516, "(1)" + line 409, "pan.___", state 523, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 525, "(1)" + line 409, "pan.___", state 526, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 409, "pan.___", state 526, "else" + line 409, "pan.___", state 529, "(1)" + line 409, "pan.___", state 530, "(1)" + line 409, "pan.___", state 530, "(1)" + line 407, "pan.___", state 535, "((i<2))" + line 407, "pan.___", state 535, "((i>=2))" + line 413, "pan.___", state 542, "(1)" + line 413, "pan.___", state 543, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 543, "else" + line 413, "pan.___", state 546, "(1)" + line 413, "pan.___", state 547, "(1)" + line 413, "pan.___", state 547, "(1)" + line 417, "pan.___", state 555, "(1)" + line 417, "pan.___", state 556, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 417, "pan.___", state 556, "else" + line 417, "pan.___", state 559, "(1)" + line 417, "pan.___", state 560, "(1)" + line 417, "pan.___", state 560, "(1)" + line 415, "pan.___", state 565, "((i<1))" + line 415, "pan.___", state 565, "((i>=1))" + line 422, "pan.___", state 572, "(1)" + line 422, "pan.___", state 573, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 422, "pan.___", state 573, "else" + line 422, "pan.___", state 576, "(1)" + line 422, "pan.___", state 577, "(1)" + line 422, "pan.___", state 577, "(1)" + line 426, "pan.___", state 585, "(1)" + line 426, "pan.___", state 586, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 426, "pan.___", state 586, "else" + line 426, "pan.___", state 589, "(1)" + line 426, "pan.___", state 590, "(1)" + line 426, "pan.___", state 590, "(1)" + line 431, "pan.___", state 599, "(1)" + line 431, "pan.___", state 599, "(1)" + line 400, "pan.___", state 619, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 637, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 651, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 417, "pan.___", state 683, "(1)" + line 422, "pan.___", state 700, "(1)" + line 426, "pan.___", state 713, "(1)" + line 400, "pan.___", state 748, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 766, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 780, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 417, "pan.___", state 812, "(1)" + line 422, "pan.___", state 829, "(1)" + line 426, "pan.___", state 842, "(1)" + line 400, "pan.___", state 879, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 897, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 911, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 417, "pan.___", state 943, "(1)" + line 422, "pan.___", state 960, "(1)" + line 426, "pan.___", state 973, "(1)" + line 400, "pan.___", state 1013, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1031, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 1045, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 417, "pan.___", state 1077, "(1)" + line 422, "pan.___", state 1094, "(1)" + line 426, "pan.___", state 1107, "(1)" + line 251, "pan.___", state 1153, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 255, "pan.___", state 1162, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 259, "pan.___", state 1177, "(1)" + line 263, "pan.___", state 1184, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 228, "pan.___", state 1200, "(1)" + line 232, "pan.___", state 1208, "(1)" + line 236, "pan.___", state 1220, "(1)" + line 240, "pan.___", state 1228, "(1)" + line 251, "pan.___", state 1259, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 255, "pan.___", state 1268, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 259, "pan.___", state 1281, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 263, "pan.___", state 1290, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 228, "pan.___", state 1306, "(1)" + line 232, "pan.___", state 1314, "(1)" + line 236, "pan.___", state 1326, "(1)" + line 240, "pan.___", state 1334, "(1)" + line 255, "pan.___", state 1360, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 259, "pan.___", state 1373, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 263, "pan.___", state 1382, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 228, "pan.___", state 1398, "(1)" + line 232, "pan.___", state 1406, "(1)" + line 236, "pan.___", state 1418, "(1)" + line 240, "pan.___", state 1426, "(1)" + line 251, "pan.___", state 1457, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 255, "pan.___", state 1466, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 259, "pan.___", state 1479, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 263, "pan.___", state 1488, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 228, "pan.___", state 1504, "(1)" + line 232, "pan.___", state 1512, "(1)" + line 236, "pan.___", state 1524, "(1)" + line 240, "pan.___", state 1532, "(1)" + line 1205, "pan.___", state 1548, "-end-" + (118 of 1548 states) +unreached in proctype :init: + (0 of 78 states) +unreached in proctype :never: + line 1266, "pan.___", state 11, "-end-" + (1 of 11 states) + +pan: elapsed time 237 seconds +pan: rate 3946.2617 states/second +pan: avg transition delay 1.2648e-06 usec +cp .input.spin urcu_progress_writer_error.spin.input +cp .input.spin.trail urcu_progress_writer_error.spin.input.trail diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer_error.spin.input b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer_error.spin.input new file mode 100644 index 0000000..d01c814 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer_error.spin.input @@ -0,0 +1,1241 @@ +#define WRITER_PROGRESS +#define GEN_ERROR_WRITER_PROGRESS + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer_error.spin.input.trail b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer_error.spin.input.trail new file mode 100644 index 0000000..64285b2 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-ipi/urcu_progress_writer_error.spin.input.trail @@ -0,0 +1,1830 @@ +-2:3:-2 +-4:-4:-4 +1:0:4497 +2:3:4417 +3:3:4420 +4:3:4420 +5:3:4423 +6:3:4431 +7:3:4431 +8:3:4434 +9:3:4440 +10:3:4444 +11:3:4444 +12:3:4447 +13:3:4457 +14:3:4465 +15:3:4465 +16:3:4468 +17:3:4474 +18:3:4478 +19:3:4478 +20:3:4481 +21:3:4487 +22:3:4491 +23:3:4492 +24:0:4497 +25:3:4494 +26:0:4497 +27:2:2871 +28:0:4497 +29:2:2877 +30:0:4497 +31:2:2878 +32:0:4497 +33:2:2879 +34:0:4497 +35:2:2880 +36:0:4497 +37:2:2881 +38:0:4497 +39:2:2882 +40:2:2883 +41:2:2887 +42:2:2888 +43:2:2896 +44:2:2897 +45:2:2901 +46:2:2902 +47:2:2910 +48:2:2915 +49:2:2919 +50:2:2920 +51:2:2928 +52:2:2929 +53:2:2933 +54:2:2934 +55:2:2928 +56:2:2929 +57:2:2933 +58:2:2934 +59:2:2942 +60:2:2947 +61:2:2948 +62:2:2959 +63:2:2960 +64:2:2961 +65:2:2972 +66:2:2977 +67:2:2978 +68:2:2989 +69:2:2990 +70:2:2991 +71:2:2989 +72:2:2990 +73:2:2991 +74:2:3002 +75:2:3010 +76:0:4497 +77:2:2881 +78:0:4497 +79:2:3014 +80:2:3018 +81:2:3019 +82:2:3023 +83:2:3027 +84:2:3028 +85:2:3032 +86:2:3040 +87:2:3041 +88:2:3045 +89:2:3049 +90:2:3050 +91:2:3045 +92:2:3046 +93:2:3054 +94:0:4497 +95:2:2881 +96:0:4497 +97:2:3062 +98:2:3063 +99:2:3064 +100:0:4497 +101:2:2881 +102:0:4497 +103:2:3069 +104:0:4497 +105:2:4022 +106:2:4023 +107:2:4027 +108:2:4031 +109:2:4032 +110:2:4036 +111:2:4041 +112:2:4049 +113:2:4053 +114:2:4054 +115:2:4049 +116:2:4053 +117:2:4054 +118:2:4058 +119:2:4065 +120:2:4072 +121:2:4073 +122:2:4080 +123:2:4085 +124:2:4092 +125:2:4093 +126:2:4092 +127:2:4093 +128:2:4100 +129:2:4104 +130:0:4497 +131:2:4109 +132:0:4497 +133:2:4110 +134:0:4497 +135:2:4111 +136:0:4497 +137:2:4112 +138:0:4497 +139:1:2 +140:0:4497 +141:1:8 +142:0:4497 +143:1:9 +144:0:4497 +145:2:4113 +146:0:4497 +147:1:10 +148:0:4497 +149:2:4112 +150:0:4497 +151:1:11 +152:0:4497 +153:2:4113 +154:0:4497 +155:1:12 +156:0:4497 +157:2:4112 +158:0:4497 +159:1:13 +160:0:4497 +161:2:4113 +162:0:4497 +163:1:14 +164:0:4497 +165:1:15 +166:0:4497 +167:1:16 +168:0:4497 +169:2:4112 +170:0:4497 +171:1:17 +172:0:4497 +173:2:4113 +174:0:4497 +175:1:26 +176:0:4497 +177:2:4112 +178:0:4497 +179:1:30 +180:1:31 +181:1:35 +182:1:39 +183:1:40 +184:1:44 +185:1:52 +186:1:53 +187:1:57 +188:1:61 +189:1:62 +190:1:57 +191:1:61 +192:1:62 +193:1:66 +194:1:73 +195:1:80 +196:1:81 +197:1:88 +198:1:93 +199:1:100 +200:1:101 +201:1:100 +202:1:101 +203:1:108 +204:1:112 +205:0:4497 +206:2:4113 +207:0:4497 +208:1:117 +209:0:4497 +210:2:4114 +211:0:4497 +212:2:4119 +213:0:4497 +214:2:4120 +215:0:4497 +216:2:4128 +217:2:4129 +218:2:4133 +219:2:4137 +220:2:4138 +221:2:4142 +222:2:4150 +223:2:4151 +224:2:4155 +225:2:4159 +226:2:4160 +227:2:4155 +228:2:4159 +229:2:4160 +230:2:4164 +231:2:4171 +232:2:4178 +233:2:4179 +234:2:4186 +235:2:4191 +236:2:4198 +237:2:4199 +238:2:4198 +239:2:4199 +240:2:4206 +241:2:4210 +242:0:4497 +243:2:3071 +244:2:4003 +245:0:4497 +246:2:2881 +247:0:4497 +248:2:3072 +249:0:4497 +250:2:2881 +251:0:4497 +252:2:3075 +253:2:3076 +254:2:3080 +255:2:3081 +256:2:3089 +257:2:3090 +258:2:3094 +259:2:3095 +260:2:3103 +261:2:3108 +262:2:3112 +263:2:3113 +264:2:3121 +265:2:3122 +266:2:3126 +267:2:3127 +268:2:3121 +269:2:3122 +270:2:3126 +271:2:3127 +272:2:3135 +273:2:3140 +274:2:3141 +275:2:3152 +276:2:3153 +277:2:3154 +278:2:3165 +279:2:3170 +280:2:3171 +281:2:3182 +282:2:3183 +283:2:3184 +284:2:3182 +285:2:3183 +286:2:3184 +287:2:3195 +288:2:3202 +289:0:4497 +290:2:2881 +291:0:4497 +292:2:3206 +293:2:3207 +294:2:3208 +295:2:3220 +296:2:3221 +297:2:3225 +298:2:3226 +299:2:3234 +300:2:3239 +301:2:3243 +302:2:3244 +303:2:3252 +304:2:3253 +305:2:3257 +306:2:3258 +307:2:3252 +308:2:3253 +309:2:3257 +310:2:3258 +311:2:3266 +312:2:3271 +313:2:3272 +314:2:3283 +315:2:3284 +316:2:3285 +317:2:3296 +318:2:3301 +319:2:3302 +320:2:3313 +321:2:3314 +322:2:3315 +323:2:3313 +324:2:3314 +325:2:3315 +326:2:3326 +327:2:3337 +328:2:3338 +329:0:4497 +330:2:2881 +331:0:4497 +332:2:3469 +333:2:3470 +334:2:3474 +335:2:3475 +336:2:3483 +337:2:3484 +338:2:3488 +339:2:3489 +340:2:3497 +341:2:3502 +342:2:3506 +343:2:3507 +344:2:3515 +345:2:3516 +346:2:3520 +347:2:3521 +348:2:3515 +349:2:3516 +350:2:3520 +351:2:3521 +352:2:3529 +353:2:3534 +354:2:3535 +355:2:3546 +356:2:3547 +357:2:3548 +358:2:3559 +359:2:3564 +360:2:3565 +361:2:3576 +362:2:3577 +363:2:3578 +364:2:3576 +365:2:3577 +366:2:3578 +367:2:3589 +368:0:4497 +369:2:2881 +370:0:4497 +371:2:3598 +372:2:3599 +373:2:3603 +374:2:3604 +375:2:3612 +376:2:3613 +377:2:3617 +378:2:3618 +379:2:3626 +380:2:3631 +381:2:3635 +382:2:3636 +383:2:3644 +384:2:3645 +385:2:3649 +386:2:3650 +387:2:3644 +388:2:3645 +389:2:3649 +390:2:3650 +391:2:3658 +392:2:3663 +393:2:3664 +394:2:3675 +395:2:3676 +396:2:3677 +397:2:3688 +398:2:3693 +399:2:3694 +400:2:3705 +401:2:3706 +402:2:3707 +403:2:3705 +404:2:3706 +405:2:3707 +406:2:3718 +407:2:3725 +408:0:4497 +409:2:2881 +410:0:4497 +411:2:3729 +412:2:3730 +413:2:3731 +414:2:3743 +415:2:3744 +416:2:3748 +417:2:3749 +418:2:3757 +419:2:3762 +420:2:3766 +421:2:3767 +422:2:3775 +423:2:3776 +424:2:3780 +425:2:3781 +426:2:3775 +427:2:3776 +428:2:3780 +429:2:3781 +430:2:3789 +431:2:3794 +432:2:3795 +433:2:3806 +434:2:3807 +435:2:3808 +436:2:3819 +437:2:3824 +438:2:3825 +439:2:3836 +440:2:3837 +441:2:3838 +442:2:3836 +443:2:3837 +444:2:3838 +445:2:3849 +446:2:3859 +447:2:3860 +448:0:4497 +449:2:2881 +450:0:4497 +451:2:3991 +452:0:4497 +453:2:4220 +454:2:4221 +455:2:4225 +456:2:4229 +457:2:4230 +458:2:4234 +459:2:4242 +460:2:4243 +461:2:4247 +462:2:4251 +463:2:4252 +464:2:4247 +465:2:4251 +466:2:4252 +467:2:4256 +468:2:4263 +469:2:4270 +470:2:4271 +471:2:4278 +472:2:4283 +473:2:4290 +474:2:4291 +475:2:4290 +476:2:4291 +477:2:4298 +478:2:4302 +479:0:4497 +480:2:4307 +481:0:4497 +482:2:4308 +483:0:4497 +484:2:4309 +485:0:4497 +486:2:4310 +487:0:4497 +488:1:26 +489:0:4497 +490:2:4311 +491:0:4497 +492:1:30 +493:1:31 +494:1:35 +495:1:39 +496:1:40 +497:1:44 +498:1:52 +499:1:53 +500:1:57 +501:1:61 +502:1:62 +503:1:57 +504:1:61 +505:1:62 +506:1:66 +507:1:73 +508:1:80 +509:1:81 +510:1:88 +511:1:93 +512:1:100 +513:1:101 +514:1:100 +515:1:101 +516:1:108 +517:1:112 +518:0:4497 +519:2:4310 +520:0:4497 +521:1:117 +522:0:4497 +523:2:4311 +524:0:4497 +525:2:4312 +526:0:4497 +527:2:4317 +528:0:4497 +529:2:4318 +530:0:4497 +531:2:4326 +532:2:4327 +533:2:4331 +534:2:4335 +535:2:4336 +536:2:4340 +537:2:4348 +538:2:4349 +539:2:4353 +540:2:4357 +541:2:4358 +542:2:4353 +543:2:4357 +544:2:4358 +545:2:4362 +546:2:4369 +547:2:4376 +548:2:4377 +549:2:4384 +550:2:4389 +551:2:4396 +552:2:4397 +553:2:4396 +554:2:4397 +555:2:4404 +556:2:4408 +557:0:4497 +558:2:3993 +559:2:4003 +560:0:4497 +561:2:2881 +562:0:4497 +563:2:3994 +564:2:3995 +565:0:4497 +566:2:2881 +567:0:4497 +568:2:3999 +569:0:4497 +570:2:4007 +571:0:4497 +572:2:2878 +573:0:4497 +574:2:2879 +575:0:4497 +576:2:2880 +577:0:4497 +578:2:2881 +579:0:4497 +580:2:2882 +581:2:2883 +582:2:2887 +583:2:2888 +584:2:2896 +585:2:2897 +586:2:2901 +587:2:2902 +588:2:2910 +589:2:2915 +590:2:2919 +591:2:2920 +592:2:2928 +593:2:2929 +594:2:2930 +595:2:2928 +596:2:2929 +597:2:2933 +598:2:2934 +599:2:2942 +600:2:2947 +601:2:2948 +602:2:2959 +603:2:2960 +604:2:2961 +605:2:2972 +606:2:2977 +607:2:2978 +608:2:2989 +609:2:2990 +610:2:2991 +611:2:2989 +612:2:2990 +613:2:2991 +614:2:3002 +615:2:3010 +616:0:4497 +617:2:2881 +618:0:4497 +619:2:3014 +620:2:3018 +621:2:3019 +622:2:3023 +623:2:3027 +624:2:3028 +625:2:3032 +626:2:3040 +627:2:3041 +628:2:3045 +629:2:3046 +630:2:3045 +631:2:3049 +632:2:3050 +633:2:3054 +634:0:4497 +635:2:2881 +636:0:4497 +637:2:3062 +638:2:3063 +639:2:3064 +640:0:4497 +641:2:2881 +642:0:4497 +643:2:3069 +644:0:4497 +645:2:4022 +646:2:4023 +647:2:4027 +648:2:4031 +649:2:4032 +650:2:4036 +651:2:4041 +652:2:4049 +653:2:4053 +654:2:4054 +655:2:4049 +656:2:4053 +657:2:4054 +658:2:4058 +659:2:4065 +660:2:4072 +661:2:4073 +662:2:4080 +663:2:4085 +664:2:4092 +665:2:4093 +666:2:4092 +667:2:4093 +668:2:4100 +669:2:4104 +670:0:4497 +671:2:4109 +672:0:4497 +673:2:4110 +674:0:4497 +675:2:4111 +676:0:4497 +677:2:4112 +678:0:4497 +679:1:26 +680:0:4497 +681:2:4113 +682:0:4497 +683:1:30 +684:1:31 +685:1:35 +686:1:39 +687:1:40 +688:1:44 +689:1:52 +690:1:53 +691:1:57 +692:1:61 +693:1:62 +694:1:57 +695:1:61 +696:1:62 +697:1:66 +698:1:73 +699:1:80 +700:1:81 +701:1:88 +702:1:93 +703:1:100 +704:1:101 +705:1:100 +706:1:101 +707:1:108 +708:1:112 +709:0:4497 +710:2:4112 +711:0:4497 +712:1:117 +713:0:4497 +714:2:4113 +715:0:4497 +716:2:4114 +717:0:4497 +718:2:4119 +719:0:4497 +720:2:4120 +721:0:4497 +722:2:4128 +723:2:4129 +724:2:4133 +725:2:4137 +726:2:4138 +727:2:4142 +728:2:4150 +729:2:4151 +730:2:4155 +731:2:4159 +732:2:4160 +733:2:4155 +734:2:4159 +735:2:4160 +736:2:4164 +737:2:4171 +738:2:4178 +739:2:4179 +740:2:4186 +741:2:4191 +742:2:4198 +743:2:4199 +744:2:4198 +745:2:4199 +746:2:4206 +747:2:4210 +748:0:4497 +749:2:3071 +750:2:4003 +751:0:4497 +752:2:2881 +753:0:4497 +754:2:3072 +755:0:4497 +756:2:2881 +757:0:4497 +758:2:3075 +759:2:3076 +760:2:3080 +761:2:3081 +762:2:3089 +763:2:3090 +764:2:3094 +765:2:3095 +766:2:3103 +767:2:3108 +768:2:3112 +769:2:3113 +770:2:3121 +771:2:3122 +772:2:3126 +773:2:3127 +774:2:3121 +775:2:3122 +776:2:3126 +777:2:3127 +778:2:3135 +779:2:3140 +780:2:3141 +781:2:3152 +782:2:3153 +783:2:3154 +784:2:3165 +785:2:3170 +786:2:3171 +787:2:3182 +788:2:3183 +789:2:3184 +790:2:3182 +791:2:3183 +792:2:3184 +793:2:3195 +794:2:3202 +795:0:4497 +796:2:2881 +797:0:4497 +798:2:3206 +799:2:3207 +800:2:3208 +801:2:3220 +802:2:3221 +803:2:3225 +804:2:3226 +805:2:3234 +806:2:3239 +807:2:3243 +808:2:3244 +809:2:3252 +810:2:3253 +811:2:3257 +812:2:3258 +813:2:3252 +814:2:3253 +815:2:3257 +816:2:3258 +817:2:3266 +818:2:3271 +819:2:3272 +820:2:3283 +821:2:3284 +822:2:3285 +823:2:3296 +824:2:3301 +825:2:3302 +826:2:3313 +827:2:3314 +828:2:3315 +829:2:3313 +830:2:3314 +831:2:3315 +832:2:3326 +833:2:3337 +834:2:3338 +835:0:4497 +836:2:2881 +837:0:4497 +838:2:3469 +839:2:3470 +840:2:3474 +841:2:3475 +842:2:3483 +843:2:3484 +844:2:3488 +845:2:3489 +846:2:3497 +847:2:3502 +848:2:3506 +849:2:3507 +850:2:3515 +851:2:3516 +852:2:3520 +853:2:3521 +854:2:3515 +855:2:3516 +856:2:3520 +857:2:3521 +858:2:3529 +859:2:3534 +860:2:3535 +861:2:3546 +862:2:3547 +863:2:3548 +864:2:3559 +865:2:3564 +866:2:3565 +867:2:3576 +868:2:3577 +869:2:3578 +870:2:3576 +871:2:3577 +872:2:3578 +873:2:3589 +874:0:4497 +875:2:2881 +876:0:4497 +877:2:3598 +878:2:3599 +879:2:3603 +880:2:3604 +881:2:3612 +882:2:3613 +883:2:3617 +884:2:3618 +885:2:3626 +886:2:3631 +887:2:3635 +888:2:3636 +889:2:3644 +890:2:3645 +891:2:3649 +892:2:3650 +893:2:3644 +894:2:3645 +895:2:3649 +896:2:3650 +897:2:3658 +898:2:3663 +899:2:3664 +900:2:3675 +901:2:3676 +902:2:3677 +903:2:3688 +904:2:3693 +905:2:3694 +906:2:3705 +907:2:3706 +908:2:3707 +909:2:3705 +910:2:3706 +911:2:3707 +912:2:3718 +913:2:3725 +914:0:4497 +915:2:2881 +916:0:4497 +917:2:3729 +918:2:3730 +919:2:3731 +920:2:3743 +921:2:3744 +922:2:3748 +923:2:3749 +924:2:3757 +925:2:3762 +926:2:3766 +927:2:3767 +928:2:3775 +929:2:3776 +930:2:3780 +931:2:3781 +932:2:3775 +933:2:3776 +934:2:3780 +935:2:3781 +936:2:3789 +937:2:3794 +938:2:3795 +939:2:3806 +940:2:3807 +941:2:3808 +942:2:3819 +943:2:3824 +944:2:3825 +945:2:3836 +946:2:3837 +947:2:3838 +948:2:3836 +949:2:3837 +950:2:3838 +951:2:3849 +952:2:3859 +953:2:3860 +954:0:4497 +955:2:2881 +956:0:4497 +957:2:3991 +958:0:4497 +959:2:4220 +960:2:4221 +961:2:4225 +962:2:4229 +963:2:4230 +964:2:4234 +965:2:4242 +966:2:4243 +967:2:4247 +968:2:4251 +969:2:4252 +970:2:4247 +971:2:4251 +972:2:4252 +973:2:4256 +974:2:4263 +975:2:4270 +976:2:4271 +977:2:4278 +978:2:4283 +979:2:4290 +980:2:4291 +981:2:4290 +982:2:4291 +983:2:4298 +984:2:4302 +985:0:4497 +986:2:4307 +987:0:4497 +988:2:4308 +989:0:4497 +990:2:4309 +991:0:4497 +992:2:4310 +993:0:4497 +994:1:26 +995:0:4497 +996:2:4311 +997:0:4497 +998:1:30 +999:1:31 +1000:1:35 +1001:1:39 +1002:1:40 +1003:1:44 +1004:1:52 +1005:1:53 +1006:1:57 +1007:1:61 +1008:1:62 +1009:1:57 +1010:1:61 +1011:1:62 +1012:1:66 +1013:1:73 +1014:1:80 +1015:1:81 +1016:1:88 +1017:1:93 +1018:1:100 +1019:1:101 +1020:1:100 +1021:1:101 +1022:1:108 +1023:1:112 +1024:0:4497 +1025:2:4310 +1026:0:4497 +1027:1:117 +1028:0:4497 +1029:2:4311 +1030:0:4497 +1031:2:4312 +1032:0:4497 +1033:2:4317 +1034:0:4497 +1035:2:4318 +1036:0:4497 +1037:2:4326 +1038:2:4327 +1039:2:4331 +1040:2:4335 +1041:2:4336 +1042:2:4340 +1043:2:4348 +1044:2:4349 +1045:2:4353 +1046:2:4357 +1047:2:4358 +1048:2:4353 +1049:2:4357 +1050:2:4358 +1051:2:4362 +1052:2:4369 +1053:2:4376 +1054:2:4377 +1055:2:4384 +1056:2:4389 +1057:2:4396 +1058:2:4397 +1059:2:4396 +1060:2:4397 +1061:2:4404 +1062:2:4408 +1063:0:4497 +1064:2:3993 +1065:2:4003 +1066:0:4497 +1067:2:2881 +1068:0:4497 +1069:2:3994 +1070:2:3995 +1071:0:4497 +1072:2:2881 +1073:0:4497 +1074:2:3999 +1075:0:4497 +1076:2:4007 +1077:0:4497 +1078:2:2878 +1079:0:4497 +1080:2:2879 +1081:0:4497 +1082:2:2880 +1083:0:4497 +1084:2:2881 +1085:0:4497 +1086:2:2882 +1087:2:2883 +1088:2:2887 +1089:2:2888 +1090:2:2896 +1091:2:2897 +1092:2:2901 +1093:2:2902 +1094:2:2910 +1095:2:2915 +1096:2:2919 +1097:2:2920 +1098:2:2928 +1099:2:2929 +1100:2:2933 +1101:2:2934 +1102:2:2928 +1103:2:2929 +1104:2:2930 +1105:2:2942 +1106:2:2947 +1107:2:2948 +1108:2:2959 +1109:2:2960 +1110:2:2961 +1111:2:2972 +1112:2:2977 +1113:2:2978 +1114:2:2989 +1115:2:2990 +1116:2:2991 +1117:2:2989 +1118:2:2990 +1119:2:2991 +1120:2:3002 +1121:2:3010 +1122:0:4497 +1123:2:2881 +1124:0:4497 +1125:2:3014 +1126:2:3018 +1127:2:3019 +1128:2:3023 +1129:2:3027 +1130:2:3028 +1131:2:3032 +1132:2:3040 +1133:2:3041 +1134:2:3045 +1135:2:3049 +1136:2:3050 +1137:2:3045 +1138:2:3046 +1139:2:3054 +1140:0:4497 +1141:2:2881 +1142:0:4497 +1143:2:3062 +1144:2:3063 +1145:2:3064 +1146:0:4497 +1147:2:2881 +1148:0:4497 +1149:2:3069 +1150:0:4497 +1151:2:4022 +1152:2:4023 +1153:2:4027 +1154:2:4031 +1155:2:4032 +1156:2:4036 +1157:2:4041 +1158:2:4049 +1159:2:4053 +1160:2:4054 +1161:2:4049 +1162:2:4053 +1163:2:4054 +1164:2:4058 +1165:2:4065 +1166:2:4072 +1167:2:4073 +1168:2:4080 +1169:2:4085 +1170:2:4092 +1171:2:4093 +1172:2:4092 +1173:2:4093 +1174:2:4100 +1175:2:4104 +1176:0:4497 +1177:2:4109 +1178:0:4497 +1179:2:4110 +1180:0:4497 +1181:2:4111 +1182:0:4497 +1183:2:4112 +1184:0:4497 +1185:1:26 +1186:0:4497 +1187:2:4113 +1188:0:4497 +1189:1:30 +1190:1:31 +1191:1:35 +1192:1:39 +1193:1:40 +1194:1:44 +1195:1:52 +1196:1:53 +1197:1:57 +1198:1:61 +1199:1:62 +1200:1:57 +1201:1:61 +1202:1:62 +1203:1:66 +1204:1:73 +1205:1:80 +1206:1:81 +1207:1:88 +1208:1:93 +1209:1:100 +1210:1:101 +1211:1:100 +1212:1:101 +1213:1:108 +1214:1:112 +1215:0:4497 +1216:2:4112 +1217:0:4497 +1218:1:117 +1219:0:4497 +1220:2:4113 +1221:0:4497 +1222:2:4114 +1223:0:4497 +1224:2:4119 +1225:0:4497 +1226:2:4120 +1227:0:4497 +1228:2:4128 +1229:2:4129 +1230:2:4133 +1231:2:4137 +1232:2:4138 +1233:2:4142 +1234:2:4150 +1235:2:4151 +1236:2:4155 +1237:2:4159 +1238:2:4160 +1239:2:4155 +1240:2:4159 +1241:2:4160 +1242:2:4164 +1243:2:4171 +1244:2:4178 +1245:2:4179 +1246:2:4186 +1247:2:4191 +1248:2:4198 +1249:2:4199 +1250:2:4198 +1251:2:4199 +1252:2:4206 +1253:2:4210 +1254:0:4497 +1255:2:3071 +1256:2:4003 +1257:0:4497 +1258:2:2881 +1259:0:4497 +1260:2:3072 +1261:0:4497 +1262:2:2881 +1263:0:4497 +1264:2:3075 +1265:2:3076 +1266:2:3080 +1267:2:3081 +1268:2:3089 +1269:2:3090 +1270:2:3094 +1271:2:3095 +1272:2:3103 +1273:2:3108 +1274:2:3112 +1275:2:3113 +1276:2:3121 +1277:2:3122 +1278:2:3126 +1279:2:3127 +1280:2:3121 +1281:2:3122 +1282:2:3126 +1283:2:3127 +1284:2:3135 +1285:2:3140 +1286:2:3141 +1287:2:3152 +1288:2:3153 +1289:2:3154 +1290:2:3165 +1291:2:3170 +1292:2:3171 +1293:2:3182 +1294:2:3183 +1295:2:3184 +1296:2:3182 +1297:2:3183 +1298:2:3184 +1299:2:3195 +1300:2:3202 +1301:0:4497 +1302:2:2881 +1303:0:4497 +1304:2:3206 +1305:2:3207 +1306:2:3208 +1307:2:3220 +1308:2:3221 +1309:2:3225 +1310:2:3226 +1311:2:3234 +1312:2:3239 +1313:2:3243 +1314:2:3244 +1315:2:3252 +1316:2:3253 +1317:2:3257 +1318:2:3258 +1319:2:3252 +1320:2:3253 +1321:2:3257 +1322:2:3258 +1323:2:3266 +1324:2:3271 +1325:2:3272 +1326:2:3283 +1327:2:3284 +1328:2:3285 +1329:2:3296 +1330:2:3301 +1331:2:3302 +1332:2:3313 +1333:2:3314 +1334:2:3315 +1335:2:3313 +1336:2:3314 +1337:2:3315 +1338:2:3326 +1339:2:3337 +1340:2:3338 +1341:0:4497 +1342:2:2881 +1343:0:4497 +1344:2:3469 +1345:2:3470 +1346:2:3474 +1347:2:3475 +1348:2:3483 +1349:2:3484 +1350:2:3488 +1351:2:3489 +1352:2:3497 +1353:2:3502 +1354:2:3506 +1355:2:3507 +1356:2:3515 +1357:2:3516 +1358:2:3520 +1359:2:3521 +1360:2:3515 +1361:2:3516 +1362:2:3520 +1363:2:3521 +1364:2:3529 +1365:2:3534 +1366:2:3535 +1367:2:3546 +1368:2:3547 +1369:2:3548 +1370:2:3559 +1371:2:3564 +1372:2:3565 +1373:2:3576 +1374:2:3577 +1375:2:3578 +1376:2:3576 +1377:2:3577 +1378:2:3578 +1379:2:3589 +1380:0:4497 +1381:2:2881 +1382:0:4497 +1383:2:3598 +1384:2:3599 +1385:2:3603 +1386:2:3604 +1387:2:3612 +1388:2:3613 +1389:2:3617 +1390:2:3618 +1391:2:3626 +1392:2:3631 +1393:2:3635 +1394:2:3636 +1395:2:3644 +1396:2:3645 +1397:2:3649 +1398:2:3650 +1399:2:3644 +1400:2:3645 +1401:2:3649 +1402:2:3650 +1403:2:3658 +1404:2:3663 +1405:2:3664 +1406:2:3675 +1407:2:3676 +1408:2:3677 +1409:2:3688 +1410:2:3693 +1411:2:3694 +1412:2:3705 +1413:2:3706 +1414:2:3707 +1415:2:3705 +1416:2:3706 +1417:2:3707 +1418:2:3718 +1419:2:3725 +1420:0:4497 +1421:2:2881 +1422:0:4497 +1423:1:118 +1424:0:4497 +1425:1:120 +1426:0:4497 +1427:1:19 +1428:0:4497 +1429:1:126 +1430:1:127 +1431:1:131 +1432:1:132 +1433:1:140 +1434:1:141 +1435:1:145 +1436:1:146 +1437:1:154 +1438:1:159 +1439:1:163 +1440:1:164 +1441:1:172 +1442:1:173 +1443:1:177 +1444:1:178 +1445:1:172 +1446:1:173 +1447:1:177 +1448:1:178 +1449:1:186 +1450:1:191 +1451:1:192 +1452:1:203 +1453:1:204 +1454:1:205 +1455:1:216 +1456:1:221 +1457:1:222 +1458:1:233 +1459:1:234 +1460:1:235 +1461:1:233 +1462:1:234 +1463:1:235 +1464:1:246 +1465:0:4497 +1466:1:15 +1467:0:4497 +1468:1:16 +1469:0:4497 +1470:1:17 +1471:0:4497 +1472:1:118 +1473:0:4497 +1474:1:120 +1475:0:4497 +1476:1:19 +1477:0:4497 +1478:1:255 +1479:1:256 +1480:0:4497 +1481:1:15 +1482:0:4497 +1483:1:16 +1484:0:4497 +1485:1:17 +1486:0:4497 +1487:1:118 +1488:0:4497 +1489:1:120 +1490:0:4497 +1491:1:19 +1492:0:4497 +1493:1:262 +1494:1:263 +1495:1:267 +1496:1:268 +1497:1:276 +1498:1:277 +1499:1:281 +1500:1:282 +1501:1:290 +1502:1:295 +1503:1:299 +1504:1:300 +1505:1:308 +1506:1:309 +1507:1:313 +1508:1:314 +1509:1:308 +1510:1:309 +1511:1:313 +1512:1:314 +1513:1:322 +1514:1:327 +1515:1:328 +1516:1:339 +1517:1:340 +1518:1:341 +1519:1:352 +1520:1:357 +1521:1:358 +1522:1:369 +1523:1:370 +1524:1:371 +1525:1:369 +1526:1:370 +1527:1:371 +1528:1:382 +1529:0:4497 +1530:1:15 +1531:0:4497 +1532:1:16 +1533:0:4497 +1534:1:17 +1535:0:4497 +1536:1:118 +1537:0:4497 +1538:1:120 +1539:0:4497 +1540:1:19 +1541:0:4497 +1542:1:391 +1543:1:392 +1544:1:396 +1545:1:397 +1546:1:405 +1547:1:406 +1548:1:410 +1549:1:411 +1550:1:419 +1551:1:424 +1552:1:428 +1553:1:429 +1554:1:437 +1555:1:438 +1556:1:442 +1557:1:443 +1558:1:437 +1559:1:438 +1560:1:442 +1561:1:443 +1562:1:451 +1563:1:456 +1564:1:457 +1565:1:468 +1566:1:469 +1567:1:470 +1568:1:481 +1569:1:486 +1570:1:487 +1571:1:498 +1572:1:499 +1573:1:500 +1574:1:498 +1575:1:499 +1576:1:500 +1577:1:511 +1578:1:518 +1579:0:4497 +1580:1:15 +1581:0:4497 +1582:1:16 +1583:0:4497 +1584:1:17 +1585:0:4497 +1586:1:118 +1587:0:4497 +1588:1:120 +1589:0:4495 +1590:1:19 +1591:0:4501 +1592:1:1184 +1593:1:1185 +1594:1:1189 +1595:1:1190 +1596:1:1198 +1597:1:1199 +1598:1:1200 +1599:1:1212 +1600:1:1217 +1601:1:1221 +1602:1:1222 +1603:1:1230 +1604:1:1231 +1605:1:1235 +1606:1:1236 +1607:1:1230 +1608:1:1231 +1609:1:1235 +1610:1:1236 +1611:1:1244 +1612:1:1249 +1613:1:1250 +1614:1:1261 +1615:1:1262 +1616:1:1263 +1617:1:1274 +1618:1:1279 +1619:1:1280 +1620:1:1291 +1621:1:1292 +1622:1:1293 +1623:1:1291 +1624:1:1292 +1625:1:1293 +1626:1:1304 +1627:0:4501 +1628:1:15 +1629:0:4501 +1630:1:16 +1631:0:4501 +1632:2:3729 +1633:2:3730 +1634:2:3731 +1635:2:3743 +1636:2:3744 +1637:2:3748 +1638:2:3749 +1639:2:3757 +1640:2:3762 +1641:2:3766 +1642:2:3767 +1643:2:3775 +1644:2:3776 +1645:2:3780 +1646:2:3781 +1647:2:3775 +1648:2:3776 +1649:2:3780 +1650:2:3781 +1651:2:3789 +1652:2:3794 +1653:2:3795 +1654:2:3806 +1655:2:3807 +1656:2:3808 +1657:2:3819 +1658:2:3824 +1659:2:3825 +1660:2:3836 +1661:2:3837 +1662:2:3838 +1663:2:3836 +1664:2:3837 +1665:2:3838 +1666:2:3849 +1667:2:3857 +1668:0:4501 +1669:2:2881 +-1:-1:-1 +1670:0:4501 +1671:2:3863 +1672:2:3864 +1673:2:3868 +1674:2:3869 +1675:2:3877 +1676:2:3878 +1677:2:3882 +1678:2:3883 +1679:2:3891 +1680:2:3896 +1681:2:3900 +1682:2:3901 +1683:2:3909 +1684:2:3910 +1685:2:3914 +1686:2:3915 +1687:2:3909 +1688:2:3910 +1689:2:3914 +1690:2:3915 +1691:2:3923 +1692:2:3928 +1693:2:3929 +1694:2:3940 +1695:2:3941 +1696:2:3942 +1697:2:3953 +1698:2:3958 +1699:2:3959 +1700:2:3970 +1701:2:3971 +1702:2:3972 +1703:2:3970 +1704:2:3971 +1705:2:3972 +1706:2:3983 +1707:0:4501 +1708:2:2881 +1709:0:4501 +1710:2:3729 +1711:2:3730 +1712:2:3734 +1713:2:3735 +1714:2:3743 +1715:2:3744 +1716:2:3748 +1717:2:3749 +1718:2:3757 +1719:2:3762 +1720:2:3766 +1721:2:3767 +1722:2:3775 +1723:2:3776 +1724:2:3780 +1725:2:3781 +1726:2:3775 +1727:2:3776 +1728:2:3780 +1729:2:3781 +1730:2:3789 +1731:2:3794 +1732:2:3795 +1733:2:3806 +1734:2:3807 +1735:2:3808 +1736:2:3819 +1737:2:3824 +1738:2:3825 +1739:2:3836 +1740:2:3837 +1741:2:3838 +1742:2:3836 +1743:2:3837 +1744:2:3838 +1745:2:3849 +1746:2:3857 +1747:0:4501 +1748:2:2881 +1749:0:4501 +1750:2:3863 +1751:2:3864 +1752:2:3868 +1753:2:3869 +1754:2:3877 +1755:2:3878 +1756:2:3882 +1757:2:3883 +1758:2:3891 +1759:2:3896 +1760:2:3900 +1761:2:3901 +1762:2:3909 +1763:2:3910 +1764:2:3914 +1765:2:3915 +1766:2:3909 +1767:2:3910 +1768:2:3914 +1769:2:3915 +1770:2:3923 +1771:2:3928 +1772:2:3929 +1773:2:3940 +1774:2:3941 +1775:2:3942 +1776:2:3953 +1777:2:3958 +1778:2:3959 +1779:2:3970 +1780:2:3971 +1781:2:3972 +1782:2:3970 +1783:2:3971 +1784:2:3972 +1785:2:3983 +1786:0:4501 +1787:2:2881 +1788:0:4501 +1789:2:3729 +1790:2:3730 +1791:2:3734 +1792:2:3735 +1793:2:3743 +1794:2:3744 +1795:2:3748 +1796:2:3749 +1797:2:3757 +1798:2:3762 +1799:2:3766 +1800:2:3767 +1801:2:3775 +1802:2:3776 +1803:2:3780 +1804:2:3781 +1805:2:3775 +1806:2:3776 +1807:2:3780 +1808:2:3781 +1809:2:3789 +1810:2:3794 +1811:2:3795 +1812:2:3806 +1813:2:3807 +1814:2:3808 +1815:2:3819 +1816:2:3824 +1817:2:3825 +1818:2:3836 +1819:2:3837 +1820:2:3838 +1821:2:3836 +1822:2:3837 +1823:2:3838 +1824:2:3849 +1825:2:3857 +1826:0:4501 +1827:2:2881 diff --git a/formal-model/results/urcu-controldataflow-no-ipi/.input.spin b/formal-model/results/urcu-controldataflow-no-ipi/.input.spin new file mode 100644 index 0000000..542625d --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/.input.spin @@ -0,0 +1,1239 @@ + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +//#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/DEFINES b/formal-model/results/urcu-controldataflow-no-ipi/DEFINES new file mode 100644 index 0000000..929f5a1 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/DEFINES @@ -0,0 +1,14 @@ + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +//#define REMOTE_BARRIERS diff --git a/formal-model/results/urcu-controldataflow-no-ipi/Makefile b/formal-model/results/urcu-controldataflow-no-ipi/Makefile new file mode 100644 index 0000000..de47dff --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/Makefile @@ -0,0 +1,170 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# Copyright (C) Mathieu Desnoyers, 2009 +# +# Authors: Mathieu Desnoyers + +#CFLAGS=-DSAFETY +#for multi-core verif, 15.5GB shared mem, use files if full +#CFLAGS=-DHASH64 -DMEMLIM=15500 -DNCORE=2 +#CFLAGS=-DHASH64 -DCOLLAPSE -DMA=88 -DMEMLIM=15500 -DNCORE=8 + +#liveness +#CFLAGS=-DHASH64 -DCOLLAPSE -DMA=88 +CFLAGS=-DHASH64 + +SPINFILE=urcu.spin + +default: + make urcu_free | tee urcu_free.log + make urcu_free_no_mb | tee urcu_free_no_mb.log + make urcu_free_no_rmb | tee urcu_free_no_rmb.log + make urcu_free_no_wmb | tee urcu_free_no_wmb.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 + +#show trail : spin -v -t -N pan.ltl input.spin +# after each individual make. + +summary: + @echo + @echo "Verification summary" + @grep errors: *.log + +asserts: clean + cat DEFINES > .input.spin + cat ${SPINFILE} >> .input.spin + rm -f .input.spin.trail + spin -a -X .input.spin + gcc -O2 -w ${CFLAGS} -DSAFETY -o pan pan.c + ./pan -v -c1 -X -m10000000 -w20 + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free: clean urcu_free_ltl run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_nested: clean urcu_free_ltl urcu_free_nested_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_nested_define: + cp urcu_free_nested.define .input.define + +urcu_free_no_rmb: clean urcu_free_ltl urcu_free_no_rmb_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_no_rmb_define: + cp urcu_free_no_rmb.define .input.define + +urcu_free_no_wmb: clean urcu_free_ltl urcu_free_no_wmb_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_no_wmb_define: + cp urcu_free_no_wmb.define .input.define + +urcu_free_no_mb: clean urcu_free_ltl urcu_free_no_mb_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_no_mb_define: + cp urcu_free_no_mb.define .input.define + +urcu_free_single_flip: clean urcu_free_ltl urcu_free_single_flip_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_single_flip_define: + cp urcu_free_single_flip.define .input.define + +urcu_free_ltl: + touch .input.define + cat .input.define >> pan.ltl + cat DEFINES >> 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 .input.define > pan.ltl + cat DEFINES >> 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 .input.define > pan.ltl + cat DEFINES >> 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 .input.define > pan.ltl + cat DEFINES >> pan.ltl + spin -f "!(`cat urcu_progress.ltl | grep -v ^//`)" >> pan.ltl + + +run_weak_fair: pan + ./pan -a -f -v -c1 -X -m10000000 -w20 + +run: pan + ./pan -a -v -c1 -X -m10000000 -w20 + +pan: pan.c + gcc -O2 -w ${CFLAGS} -o pan pan.c + +pan.c: pan.ltl ${SPINFILE} + cat .input.define > .input.spin + cat DEFINES >> .input.spin + cat ${SPINFILE} >> .input.spin + rm -f .input.spin.trail + spin -a -X -N pan.ltl .input.spin + +.PHONY: clean default distclean summary +clean: + rm -f pan* trail.out .input.spin* *.spin.trail .input.define +distclean: + rm -f *.trail *.input *.log diff --git a/formal-model/results/urcu-controldataflow-no-ipi/asserts.log b/formal-model/results/urcu-controldataflow-no-ipi/asserts.log new file mode 100644 index 0000000..a732917 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/asserts.log @@ -0,0 +1,514 @@ +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +cat DEFINES > .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -DSAFETY -o pan pan.c +./pan -v -c1 -X -m10000000 -w20 +Depth= 4311 States= 1e+06 Transitions= 4.65e+08 Memory= 542.717 t= 480 R= 2e+03 + +(Spin Version 5.1.7 -- 23 December 2008) + + Partial Order Reduction + +Full statespace search for: + never claim - (none specified) + assertion violations + + cycle checks - (disabled by -DSAFETY) + invalid end states + + +State-vector 72 byte, depth reached 4311, errors: 0 + 1884295 states, stored +9.0500014e+08 states, matched +9.0688444e+08 transitions (= stored+matched) +5.3819272e+09 atomic steps +hash conflicts: 4.4436974e+08 (resolved) + +Stats on memory usage (in Megabytes): + 179.700 equivalent memory usage for states (stored*(State-vector + overhead)) + 144.496 actual memory usage for states (compression: 80.41%) + state-vector as stored = 52 byte + 28 byte overhead + 8.000 memory used for hash table (-w20) + 457.764 memory used for DFS stack (-m10000000) + 610.197 total actual memory usage + +unreached in proctype urcu_reader + line 394, ".input.spin", state 17, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 49, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 63, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 82, "(1)" + line 420, ".input.spin", state 112, "(1)" + line 424, ".input.spin", state 125, "(1)" + line 575, ".input.spin", state 146, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 394, ".input.spin", state 153, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 185, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 199, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 218, "(1)" + line 420, ".input.spin", state 248, "(1)" + line 424, ".input.spin", state 261, "(1)" + line 394, ".input.spin", state 282, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 314, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 328, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 347, "(1)" + line 420, ".input.spin", state 377, "(1)" + line 424, ".input.spin", state 390, "(1)" + line 394, ".input.spin", state 413, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 394, ".input.spin", state 415, "(1)" + line 394, ".input.spin", state 416, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 394, ".input.spin", state 416, "else" + line 394, ".input.spin", state 419, "(1)" + line 398, ".input.spin", state 427, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 429, "(1)" + line 398, ".input.spin", state 430, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 398, ".input.spin", state 430, "else" + line 398, ".input.spin", state 433, "(1)" + line 398, ".input.spin", state 434, "(1)" + line 398, ".input.spin", state 434, "(1)" + line 396, ".input.spin", state 439, "((i<1))" + line 396, ".input.spin", state 439, "((i>=1))" + line 403, ".input.spin", state 445, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 447, "(1)" + line 403, ".input.spin", state 448, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 403, ".input.spin", state 448, "else" + line 403, ".input.spin", state 451, "(1)" + line 403, ".input.spin", state 452, "(1)" + line 403, ".input.spin", state 452, "(1)" + line 407, ".input.spin", state 459, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 461, "(1)" + line 407, ".input.spin", state 462, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 407, ".input.spin", state 462, "else" + line 407, ".input.spin", state 465, "(1)" + line 407, ".input.spin", state 466, "(1)" + line 407, ".input.spin", state 466, "(1)" + line 405, ".input.spin", state 471, "((i<2))" + line 405, ".input.spin", state 471, "((i>=2))" + line 411, ".input.spin", state 478, "(1)" + line 411, ".input.spin", state 479, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 411, ".input.spin", state 479, "else" + line 411, ".input.spin", state 482, "(1)" + line 411, ".input.spin", state 483, "(1)" + line 411, ".input.spin", state 483, "(1)" + line 415, ".input.spin", state 491, "(1)" + line 415, ".input.spin", state 492, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 415, ".input.spin", state 492, "else" + line 415, ".input.spin", state 495, "(1)" + line 415, ".input.spin", state 496, "(1)" + line 415, ".input.spin", state 496, "(1)" + line 413, ".input.spin", state 501, "((i<1))" + line 413, ".input.spin", state 501, "((i>=1))" + line 420, ".input.spin", state 508, "(1)" + line 420, ".input.spin", state 509, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 420, ".input.spin", state 509, "else" + line 420, ".input.spin", state 512, "(1)" + line 420, ".input.spin", state 513, "(1)" + line 420, ".input.spin", state 513, "(1)" + line 424, ".input.spin", state 521, "(1)" + line 424, ".input.spin", state 522, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 424, ".input.spin", state 522, "else" + line 424, ".input.spin", state 525, "(1)" + line 424, ".input.spin", state 526, "(1)" + line 424, ".input.spin", state 526, "(1)" + line 422, ".input.spin", state 531, "((i<2))" + line 422, ".input.spin", state 531, "((i>=2))" + line 429, ".input.spin", state 535, "(1)" + line 429, ".input.spin", state 535, "(1)" + line 575, ".input.spin", state 538, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 575, ".input.spin", state 539, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 575, ".input.spin", state 540, "(1)" + line 249, ".input.spin", state 544, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, ".input.spin", state 555, "(1)" + line 257, ".input.spin", state 566, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, ".input.spin", state 575, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, ".input.spin", state 591, "(1)" + line 230, ".input.spin", state 599, "(1)" + line 234, ".input.spin", state 611, "(1)" + line 238, ".input.spin", state 619, "(1)" + line 394, ".input.spin", state 637, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 651, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 669, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 683, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 702, "(1)" + line 415, ".input.spin", state 715, "(1)" + line 420, ".input.spin", state 732, "(1)" + line 424, ".input.spin", state 745, "(1)" + line 394, ".input.spin", state 773, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 394, ".input.spin", state 775, "(1)" + line 394, ".input.spin", state 776, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 394, ".input.spin", state 776, "else" + line 394, ".input.spin", state 779, "(1)" + line 398, ".input.spin", state 787, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 789, "(1)" + line 398, ".input.spin", state 790, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 398, ".input.spin", state 790, "else" + line 398, ".input.spin", state 793, "(1)" + line 398, ".input.spin", state 794, "(1)" + line 398, ".input.spin", state 794, "(1)" + line 396, ".input.spin", state 799, "((i<1))" + line 396, ".input.spin", state 799, "((i>=1))" + line 403, ".input.spin", state 805, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 807, "(1)" + line 403, ".input.spin", state 808, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 403, ".input.spin", state 808, "else" + line 403, ".input.spin", state 811, "(1)" + line 403, ".input.spin", state 812, "(1)" + line 403, ".input.spin", state 812, "(1)" + line 407, ".input.spin", state 819, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 821, "(1)" + line 407, ".input.spin", state 822, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 407, ".input.spin", state 822, "else" + line 407, ".input.spin", state 825, "(1)" + line 407, ".input.spin", state 826, "(1)" + line 407, ".input.spin", state 826, "(1)" + line 405, ".input.spin", state 831, "((i<2))" + line 405, ".input.spin", state 831, "((i>=2))" + line 411, ".input.spin", state 838, "(1)" + line 411, ".input.spin", state 839, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 411, ".input.spin", state 839, "else" + line 411, ".input.spin", state 842, "(1)" + line 411, ".input.spin", state 843, "(1)" + line 411, ".input.spin", state 843, "(1)" + line 415, ".input.spin", state 851, "(1)" + line 415, ".input.spin", state 852, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 415, ".input.spin", state 852, "else" + line 415, ".input.spin", state 855, "(1)" + line 415, ".input.spin", state 856, "(1)" + line 415, ".input.spin", state 856, "(1)" + line 413, ".input.spin", state 861, "((i<1))" + line 413, ".input.spin", state 861, "((i>=1))" + line 420, ".input.spin", state 868, "(1)" + line 420, ".input.spin", state 869, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 420, ".input.spin", state 869, "else" + line 420, ".input.spin", state 872, "(1)" + line 420, ".input.spin", state 873, "(1)" + line 420, ".input.spin", state 873, "(1)" + line 424, ".input.spin", state 881, "(1)" + line 424, ".input.spin", state 882, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 424, ".input.spin", state 882, "else" + line 424, ".input.spin", state 885, "(1)" + line 424, ".input.spin", state 886, "(1)" + line 424, ".input.spin", state 886, "(1)" + line 429, ".input.spin", state 895, "(1)" + line 429, ".input.spin", state 895, "(1)" + line 394, ".input.spin", state 902, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 394, ".input.spin", state 904, "(1)" + line 394, ".input.spin", state 905, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 394, ".input.spin", state 905, "else" + line 394, ".input.spin", state 908, "(1)" + line 398, ".input.spin", state 916, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 918, "(1)" + line 398, ".input.spin", state 919, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 398, ".input.spin", state 919, "else" + line 398, ".input.spin", state 922, "(1)" + line 398, ".input.spin", state 923, "(1)" + line 398, ".input.spin", state 923, "(1)" + line 396, ".input.spin", state 928, "((i<1))" + line 396, ".input.spin", state 928, "((i>=1))" + line 403, ".input.spin", state 934, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 936, "(1)" + line 403, ".input.spin", state 937, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 403, ".input.spin", state 937, "else" + line 403, ".input.spin", state 940, "(1)" + line 403, ".input.spin", state 941, "(1)" + line 403, ".input.spin", state 941, "(1)" + line 407, ".input.spin", state 948, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 950, "(1)" + line 407, ".input.spin", state 951, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 407, ".input.spin", state 951, "else" + line 407, ".input.spin", state 954, "(1)" + line 407, ".input.spin", state 955, "(1)" + line 407, ".input.spin", state 955, "(1)" + line 405, ".input.spin", state 960, "((i<2))" + line 405, ".input.spin", state 960, "((i>=2))" + line 411, ".input.spin", state 967, "(1)" + line 411, ".input.spin", state 968, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 411, ".input.spin", state 968, "else" + line 411, ".input.spin", state 971, "(1)" + line 411, ".input.spin", state 972, "(1)" + line 411, ".input.spin", state 972, "(1)" + line 415, ".input.spin", state 980, "(1)" + line 415, ".input.spin", state 981, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 415, ".input.spin", state 981, "else" + line 415, ".input.spin", state 984, "(1)" + line 415, ".input.spin", state 985, "(1)" + line 415, ".input.spin", state 985, "(1)" + line 413, ".input.spin", state 990, "((i<1))" + line 413, ".input.spin", state 990, "((i>=1))" + line 420, ".input.spin", state 997, "(1)" + line 420, ".input.spin", state 998, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 420, ".input.spin", state 998, "else" + line 420, ".input.spin", state 1001, "(1)" + line 420, ".input.spin", state 1002, "(1)" + line 420, ".input.spin", state 1002, "(1)" + line 424, ".input.spin", state 1010, "(1)" + line 424, ".input.spin", state 1011, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 424, ".input.spin", state 1011, "else" + line 424, ".input.spin", state 1014, "(1)" + line 424, ".input.spin", state 1015, "(1)" + line 424, ".input.spin", state 1015, "(1)" + line 422, ".input.spin", state 1020, "((i<2))" + line 422, ".input.spin", state 1020, "((i>=2))" + line 429, ".input.spin", state 1024, "(1)" + line 429, ".input.spin", state 1024, "(1)" + line 583, ".input.spin", state 1028, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 394, ".input.spin", state 1033, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 1047, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 1065, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 1079, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 1098, "(1)" + line 415, ".input.spin", state 1111, "(1)" + line 420, ".input.spin", state 1128, "(1)" + line 424, ".input.spin", state 1141, "(1)" + line 394, ".input.spin", state 1165, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 1197, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 1211, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 1230, "(1)" + line 420, ".input.spin", state 1260, "(1)" + line 424, ".input.spin", state 1273, "(1)" + line 394, ".input.spin", state 1298, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 1330, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 1344, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 1363, "(1)" + line 420, ".input.spin", state 1393, "(1)" + line 424, ".input.spin", state 1406, "(1)" + line 394, ".input.spin", state 1427, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 1459, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 1473, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 1492, "(1)" + line 420, ".input.spin", state 1522, "(1)" + line 424, ".input.spin", state 1535, "(1)" + line 249, ".input.spin", state 1558, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 257, ".input.spin", state 1580, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, ".input.spin", state 1589, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, ".input.spin", state 1605, "(1)" + line 230, ".input.spin", state 1613, "(1)" + line 234, ".input.spin", state 1625, "(1)" + line 238, ".input.spin", state 1633, "(1)" + line 394, ".input.spin", state 1651, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 1665, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 1683, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 1697, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 1716, "(1)" + line 415, ".input.spin", state 1729, "(1)" + line 420, ".input.spin", state 1746, "(1)" + line 424, ".input.spin", state 1759, "(1)" + line 394, ".input.spin", state 1780, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 1794, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 1812, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 1826, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 1845, "(1)" + line 415, ".input.spin", state 1858, "(1)" + line 420, ".input.spin", state 1875, "(1)" + line 424, ".input.spin", state 1888, "(1)" + line 394, ".input.spin", state 1912, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 1928, "(1)" + line 403, ".input.spin", state 1944, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 1958, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 1977, "(1)" + line 420, ".input.spin", state 2007, "(1)" + line 424, ".input.spin", state 2020, "(1)" + line 622, ".input.spin", state 2041, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 394, ".input.spin", state 2048, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 2080, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 2094, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 2113, "(1)" + line 420, ".input.spin", state 2143, "(1)" + line 424, ".input.spin", state 2156, "(1)" + line 394, ".input.spin", state 2177, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 2209, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 2223, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 2242, "(1)" + line 420, ".input.spin", state 2272, "(1)" + line 424, ".input.spin", state 2285, "(1)" + line 394, ".input.spin", state 2308, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 394, ".input.spin", state 2310, "(1)" + line 394, ".input.spin", state 2311, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 394, ".input.spin", state 2311, "else" + line 394, ".input.spin", state 2314, "(1)" + line 398, ".input.spin", state 2322, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 2324, "(1)" + line 398, ".input.spin", state 2325, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 398, ".input.spin", state 2325, "else" + line 398, ".input.spin", state 2328, "(1)" + line 398, ".input.spin", state 2329, "(1)" + line 398, ".input.spin", state 2329, "(1)" + line 396, ".input.spin", state 2334, "((i<1))" + line 396, ".input.spin", state 2334, "((i>=1))" + line 403, ".input.spin", state 2340, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 2342, "(1)" + line 403, ".input.spin", state 2343, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 403, ".input.spin", state 2343, "else" + line 403, ".input.spin", state 2346, "(1)" + line 403, ".input.spin", state 2347, "(1)" + line 403, ".input.spin", state 2347, "(1)" + line 407, ".input.spin", state 2354, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 2356, "(1)" + line 407, ".input.spin", state 2357, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 407, ".input.spin", state 2357, "else" + line 407, ".input.spin", state 2360, "(1)" + line 407, ".input.spin", state 2361, "(1)" + line 407, ".input.spin", state 2361, "(1)" + line 405, ".input.spin", state 2366, "((i<2))" + line 405, ".input.spin", state 2366, "((i>=2))" + line 411, ".input.spin", state 2373, "(1)" + line 411, ".input.spin", state 2374, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 411, ".input.spin", state 2374, "else" + line 411, ".input.spin", state 2377, "(1)" + line 411, ".input.spin", state 2378, "(1)" + line 411, ".input.spin", state 2378, "(1)" + line 415, ".input.spin", state 2386, "(1)" + line 415, ".input.spin", state 2387, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 415, ".input.spin", state 2387, "else" + line 415, ".input.spin", state 2390, "(1)" + line 415, ".input.spin", state 2391, "(1)" + line 415, ".input.spin", state 2391, "(1)" + line 413, ".input.spin", state 2396, "((i<1))" + line 413, ".input.spin", state 2396, "((i>=1))" + line 420, ".input.spin", state 2403, "(1)" + line 420, ".input.spin", state 2404, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 420, ".input.spin", state 2404, "else" + line 420, ".input.spin", state 2407, "(1)" + line 420, ".input.spin", state 2408, "(1)" + line 420, ".input.spin", state 2408, "(1)" + line 424, ".input.spin", state 2416, "(1)" + line 424, ".input.spin", state 2417, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 424, ".input.spin", state 2417, "else" + line 424, ".input.spin", state 2420, "(1)" + line 424, ".input.spin", state 2421, "(1)" + line 424, ".input.spin", state 2421, "(1)" + line 422, ".input.spin", state 2426, "((i<2))" + line 422, ".input.spin", state 2426, "((i>=2))" + line 429, ".input.spin", state 2430, "(1)" + line 429, ".input.spin", state 2430, "(1)" + line 622, ".input.spin", state 2433, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 622, ".input.spin", state 2434, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 622, ".input.spin", state 2435, "(1)" + line 249, ".input.spin", state 2439, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, ".input.spin", state 2450, "(1)" + line 257, ".input.spin", state 2461, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, ".input.spin", state 2470, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, ".input.spin", state 2486, "(1)" + line 230, ".input.spin", state 2494, "(1)" + line 234, ".input.spin", state 2506, "(1)" + line 238, ".input.spin", state 2514, "(1)" + line 394, ".input.spin", state 2532, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 2546, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 2564, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 2578, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 2597, "(1)" + line 415, ".input.spin", state 2610, "(1)" + line 420, ".input.spin", state 2627, "(1)" + line 424, ".input.spin", state 2640, "(1)" + line 249, ".input.spin", state 2664, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, ".input.spin", state 2673, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, ".input.spin", state 2686, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, ".input.spin", state 2695, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, ".input.spin", state 2711, "(1)" + line 230, ".input.spin", state 2719, "(1)" + line 234, ".input.spin", state 2731, "(1)" + line 238, ".input.spin", state 2739, "(1)" + line 394, ".input.spin", state 2757, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 2771, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 2789, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 2803, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 2822, "(1)" + line 415, ".input.spin", state 2835, "(1)" + line 420, ".input.spin", state 2852, "(1)" + line 424, ".input.spin", state 2865, "(1)" + line 394, ".input.spin", state 2886, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 2900, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 2918, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 2932, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 2951, "(1)" + line 415, ".input.spin", state 2964, "(1)" + line 420, ".input.spin", state 2981, "(1)" + line 424, ".input.spin", state 2994, "(1)" + line 226, ".input.spin", state 3027, "(1)" + line 234, ".input.spin", state 3047, "(1)" + line 238, ".input.spin", state 3055, "(1)" + line 226, ".input.spin", state 3070, "(1)" + line 230, ".input.spin", state 3078, "(1)" + line 234, ".input.spin", state 3090, "(1)" + line 238, ".input.spin", state 3098, "(1)" + line 876, ".input.spin", state 3115, "-end-" + (318 of 3115 states) +unreached in proctype urcu_writer + line 394, ".input.spin", state 18, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 32, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 50, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 83, "(1)" + line 415, ".input.spin", state 96, "(1)" + line 420, ".input.spin", state 113, "(1)" + line 249, ".input.spin", state 149, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, ".input.spin", state 158, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, ".input.spin", state 171, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 394, ".input.spin", state 211, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, ".input.spin", state 225, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 243, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 257, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, ".input.spin", state 276, "(1)" + line 415, ".input.spin", state 289, "(1)" + line 420, ".input.spin", state 306, "(1)" + line 424, ".input.spin", state 319, "(1)" + line 398, ".input.spin", state 356, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 374, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 388, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 415, ".input.spin", state 420, "(1)" + line 420, ".input.spin", state 437, "(1)" + line 424, ".input.spin", state 450, "(1)" + line 398, ".input.spin", state 494, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 512, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 526, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 415, ".input.spin", state 558, "(1)" + line 420, ".input.spin", state 575, "(1)" + line 424, ".input.spin", state 588, "(1)" + line 398, ".input.spin", state 623, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 641, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 655, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 415, ".input.spin", state 687, "(1)" + line 420, ".input.spin", state 704, "(1)" + line 424, ".input.spin", state 717, "(1)" + line 398, ".input.spin", state 754, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, ".input.spin", state 772, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, ".input.spin", state 786, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 415, ".input.spin", state 818, "(1)" + line 420, ".input.spin", state 835, "(1)" + line 424, ".input.spin", state 848, "(1)" + line 249, ".input.spin", state 903, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, ".input.spin", state 912, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, ".input.spin", state 927, "(1)" + line 261, ".input.spin", state 934, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, ".input.spin", state 950, "(1)" + line 230, ".input.spin", state 958, "(1)" + line 234, ".input.spin", state 970, "(1)" + line 238, ".input.spin", state 978, "(1)" + line 253, ".input.spin", state 1003, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, ".input.spin", state 1016, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, ".input.spin", state 1025, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, ".input.spin", state 1041, "(1)" + line 230, ".input.spin", state 1049, "(1)" + line 234, ".input.spin", state 1061, "(1)" + line 238, ".input.spin", state 1069, "(1)" + line 253, ".input.spin", state 1094, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, ".input.spin", state 1107, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, ".input.spin", state 1116, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, ".input.spin", state 1132, "(1)" + line 230, ".input.spin", state 1140, "(1)" + line 234, ".input.spin", state 1152, "(1)" + line 238, ".input.spin", state 1160, "(1)" + line 253, ".input.spin", state 1185, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, ".input.spin", state 1198, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, ".input.spin", state 1207, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, ".input.spin", state 1223, "(1)" + line 230, ".input.spin", state 1231, "(1)" + line 234, ".input.spin", state 1243, "(1)" + line 238, ".input.spin", state 1251, "(1)" + line 1203, ".input.spin", state 1266, "-end-" + (71 of 1266 states) +unreached in proctype :init: + (0 of 78 states) + +pan: elapsed time 944 seconds +pan: rate 1995.0819 states/second +pan: avg transition delay 1.0414e-06 usec +cp .input.spin asserts.spin.input +cp .input.spin.trail asserts.spin.input.trail diff --git a/formal-model/results/urcu-controldataflow-no-ipi/asserts.spin.input b/formal-model/results/urcu-controldataflow-no-ipi/asserts.spin.input new file mode 100644 index 0000000..542625d --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/asserts.spin.input @@ -0,0 +1,1239 @@ + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +//#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/references.txt b/formal-model/results/urcu-controldataflow-no-ipi/references.txt new file mode 100644 index 0000000..72c67a2 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/references.txt @@ -0,0 +1,13 @@ +http://spinroot.com/spin/Man/ltl.html +http://en.wikipedia.org/wiki/Linear_temporal_logic +http://www.dcs.gla.ac.uk/~muffy/MRS4-2002/lect11.ppt + +http://www.lsv.ens-cachan.fr/~gastin/ltl2ba/index.php +http://spinroot.com/spin/Man/index.html +http://spinroot.com/spin/Man/promela.html + +LTL vs CTL : + +http://spinroot.com/spin/Doc/course/lecture12.pdf p. 9, p. 15, p. 18 +http://www-i2.informatik.rwth-aachen.de/i2/fileadmin/user_upload/documents/Introduction_to_Model_Checking/mc_lec18.pdf + (downloaded) diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/DEFINES b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/DEFINES new file mode 100644 index 0000000..980fad6 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/DEFINES @@ -0,0 +1,14 @@ + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/Makefile b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/Makefile new file mode 100644 index 0000000..de47dff --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/Makefile @@ -0,0 +1,170 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# Copyright (C) Mathieu Desnoyers, 2009 +# +# Authors: Mathieu Desnoyers + +#CFLAGS=-DSAFETY +#for multi-core verif, 15.5GB shared mem, use files if full +#CFLAGS=-DHASH64 -DMEMLIM=15500 -DNCORE=2 +#CFLAGS=-DHASH64 -DCOLLAPSE -DMA=88 -DMEMLIM=15500 -DNCORE=8 + +#liveness +#CFLAGS=-DHASH64 -DCOLLAPSE -DMA=88 +CFLAGS=-DHASH64 + +SPINFILE=urcu.spin + +default: + make urcu_free | tee urcu_free.log + make urcu_free_no_mb | tee urcu_free_no_mb.log + make urcu_free_no_rmb | tee urcu_free_no_rmb.log + make urcu_free_no_wmb | tee urcu_free_no_wmb.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 + +#show trail : spin -v -t -N pan.ltl input.spin +# after each individual make. + +summary: + @echo + @echo "Verification summary" + @grep errors: *.log + +asserts: clean + cat DEFINES > .input.spin + cat ${SPINFILE} >> .input.spin + rm -f .input.spin.trail + spin -a -X .input.spin + gcc -O2 -w ${CFLAGS} -DSAFETY -o pan pan.c + ./pan -v -c1 -X -m10000000 -w20 + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free: clean urcu_free_ltl run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_nested: clean urcu_free_ltl urcu_free_nested_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_nested_define: + cp urcu_free_nested.define .input.define + +urcu_free_no_rmb: clean urcu_free_ltl urcu_free_no_rmb_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_no_rmb_define: + cp urcu_free_no_rmb.define .input.define + +urcu_free_no_wmb: clean urcu_free_ltl urcu_free_no_wmb_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_no_wmb_define: + cp urcu_free_no_wmb.define .input.define + +urcu_free_no_mb: clean urcu_free_ltl urcu_free_no_mb_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_no_mb_define: + cp urcu_free_no_mb.define .input.define + +urcu_free_single_flip: clean urcu_free_ltl urcu_free_single_flip_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_single_flip_define: + cp urcu_free_single_flip.define .input.define + +urcu_free_ltl: + touch .input.define + cat .input.define >> pan.ltl + cat DEFINES >> 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 .input.define > pan.ltl + cat DEFINES >> 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 .input.define > pan.ltl + cat DEFINES >> 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 .input.define > pan.ltl + cat DEFINES >> pan.ltl + spin -f "!(`cat urcu_progress.ltl | grep -v ^//`)" >> pan.ltl + + +run_weak_fair: pan + ./pan -a -f -v -c1 -X -m10000000 -w20 + +run: pan + ./pan -a -v -c1 -X -m10000000 -w20 + +pan: pan.c + gcc -O2 -w ${CFLAGS} -o pan pan.c + +pan.c: pan.ltl ${SPINFILE} + cat .input.define > .input.spin + cat DEFINES >> .input.spin + cat ${SPINFILE} >> .input.spin + rm -f .input.spin.trail + spin -a -X -N pan.ltl .input.spin + +.PHONY: clean default distclean summary +clean: + rm -f pan* trail.out .input.spin* *.spin.trail .input.define +distclean: + rm -f *.trail *.input *.log diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/references.txt b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/references.txt new file mode 100644 index 0000000..72c67a2 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/references.txt @@ -0,0 +1,13 @@ +http://spinroot.com/spin/Man/ltl.html +http://en.wikipedia.org/wiki/Linear_temporal_logic +http://www.dcs.gla.ac.uk/~muffy/MRS4-2002/lect11.ppt + +http://www.lsv.ens-cachan.fr/~gastin/ltl2ba/index.php +http://spinroot.com/spin/Man/index.html +http://spinroot.com/spin/Man/promela.html + +LTL vs CTL : + +http://spinroot.com/spin/Doc/course/lecture12.pdf p. 9, p. 15, p. 18 +http://www-i2.informatik.rwth-aachen.de/i2/fileadmin/user_upload/documents/Introduction_to_Model_Checking/mc_lec18.pdf + (downloaded) diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/result-ipi-urcu_free/DEFINES b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/result-ipi-urcu_free/DEFINES new file mode 100644 index 0000000..980fad6 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/result-ipi-urcu_free/DEFINES @@ -0,0 +1,14 @@ + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/result-ipi-urcu_free/Makefile b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/result-ipi-urcu_free/Makefile new file mode 100644 index 0000000..de47dff --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/result-ipi-urcu_free/Makefile @@ -0,0 +1,170 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# Copyright (C) Mathieu Desnoyers, 2009 +# +# Authors: Mathieu Desnoyers + +#CFLAGS=-DSAFETY +#for multi-core verif, 15.5GB shared mem, use files if full +#CFLAGS=-DHASH64 -DMEMLIM=15500 -DNCORE=2 +#CFLAGS=-DHASH64 -DCOLLAPSE -DMA=88 -DMEMLIM=15500 -DNCORE=8 + +#liveness +#CFLAGS=-DHASH64 -DCOLLAPSE -DMA=88 +CFLAGS=-DHASH64 + +SPINFILE=urcu.spin + +default: + make urcu_free | tee urcu_free.log + make urcu_free_no_mb | tee urcu_free_no_mb.log + make urcu_free_no_rmb | tee urcu_free_no_rmb.log + make urcu_free_no_wmb | tee urcu_free_no_wmb.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 + +#show trail : spin -v -t -N pan.ltl input.spin +# after each individual make. + +summary: + @echo + @echo "Verification summary" + @grep errors: *.log + +asserts: clean + cat DEFINES > .input.spin + cat ${SPINFILE} >> .input.spin + rm -f .input.spin.trail + spin -a -X .input.spin + gcc -O2 -w ${CFLAGS} -DSAFETY -o pan pan.c + ./pan -v -c1 -X -m10000000 -w20 + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free: clean urcu_free_ltl run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_nested: clean urcu_free_ltl urcu_free_nested_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_nested_define: + cp urcu_free_nested.define .input.define + +urcu_free_no_rmb: clean urcu_free_ltl urcu_free_no_rmb_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_no_rmb_define: + cp urcu_free_no_rmb.define .input.define + +urcu_free_no_wmb: clean urcu_free_ltl urcu_free_no_wmb_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_no_wmb_define: + cp urcu_free_no_wmb.define .input.define + +urcu_free_no_mb: clean urcu_free_ltl urcu_free_no_mb_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_no_mb_define: + cp urcu_free_no_mb.define .input.define + +urcu_free_single_flip: clean urcu_free_ltl urcu_free_single_flip_define run + cp .input.spin $@.spin.input + -cp .input.spin.trail $@.spin.input.trail + +urcu_free_single_flip_define: + cp urcu_free_single_flip.define .input.define + +urcu_free_ltl: + touch .input.define + cat .input.define >> pan.ltl + cat DEFINES >> 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 .input.define > pan.ltl + cat DEFINES >> 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 .input.define > pan.ltl + cat DEFINES >> 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 .input.define > pan.ltl + cat DEFINES >> pan.ltl + spin -f "!(`cat urcu_progress.ltl | grep -v ^//`)" >> pan.ltl + + +run_weak_fair: pan + ./pan -a -f -v -c1 -X -m10000000 -w20 + +run: pan + ./pan -a -v -c1 -X -m10000000 -w20 + +pan: pan.c + gcc -O2 -w ${CFLAGS} -o pan pan.c + +pan.c: pan.ltl ${SPINFILE} + cat .input.define > .input.spin + cat DEFINES >> .input.spin + cat ${SPINFILE} >> .input.spin + rm -f .input.spin.trail + spin -a -X -N pan.ltl .input.spin + +.PHONY: clean default distclean summary +clean: + rm -f pan* trail.out .input.spin* *.spin.trail .input.define +distclean: + rm -f *.trail *.input *.log diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/result-ipi-urcu_free/asserts.log b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/result-ipi-urcu_free/asserts.log new file mode 100644 index 0000000..60a124e --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/result-ipi-urcu_free/asserts.log @@ -0,0 +1,41 @@ +make[1]: Entering directory `/home/compudj/doc/userspace-rcu/formal-model/urcu-controldataflow' +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +cat DEFINES > .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -DSAFETY -o pan pan.c +./pan -v -c1 -X -m10000000 -w20 +Depth= 6408 States= 1e+06 Transitions= 1.63e+08 Memory= 542.717 t= 163 R= 6e+03 +Depth= 7831 States= 2e+06 Transitions= 3.34e+08 Memory= 618.986 t= 343 R= 6e+03 +Depth= 7831 States= 3e+06 Transitions= 5.11e+08 Memory= 695.354 t= 530 R= 6e+03 +pan: resizing hashtable to -w22.. done +Depth= 7831 States= 4e+06 Transitions= 6.76e+08 Memory= 802.744 t= 697 R= 6e+03 +Depth= 7831 States= 5e+06 Transitions= 9e+08 Memory= 879.014 t= 928 R= 5e+03 +Depth= 7831 States= 6e+06 Transitions= 1.34e+09 Memory= 955.283 t= 1.39e+03 R= 4e+03 +Depth= 7831 States= 7e+06 Transitions= 1.71e+09 Memory= 1031.553 t= 1.79e+03 R= 4e+03 +Depth= 7831 States= 8e+06 Transitions= 2.07e+09 Memory= 1107.920 t= 2.18e+03 R= 4e+03 +Depth= 7831 States= 9e+06 Transitions= 2.39e+09 Memory= 1184.190 t= 2.53e+03 R= 4e+03 +pan: resizing hashtable to -w24.. done +Depth= 7831 States= 1e+07 Transitions= 2.59e+09 Memory= 1384.553 t= 2.74e+03 R= 4e+03 +Depth= 7831 States= 1.1e+07 Transitions= 2.89e+09 Memory= 1460.822 t= 3.04e+03 R= 4e+03 +Depth= 7831 States= 1.2e+07 Transitions= 3.23e+09 Memory= 1537.092 t= 3.4e+03 R= 4e+03 +Depth= 7831 States= 1.3e+07 Transitions= 3.94e+09 Memory= 1613.459 t= 4.17e+03 R= 3e+03 +Depth= 7831 States= 1.4e+07 Transitions= 4.65e+09 Memory= 1689.729 t= 4.93e+03 R= 3e+03 +Depth= 7831 States= 1.5e+07 Transitions= 5.08e+09 Memory= 1765.998 t= 5.39e+03 R= 3e+03 +Depth= 7831 States= 1.6e+07 Transitions= 5.5e+09 Memory= 1842.268 t= 5.84e+03 R= 3e+03 +Depth= 7831 States= 1.7e+07 Transitions= 5.7e+09 Memory= 1918.635 t= 6.04e+03 R= 3e+03 +Depth= 7831 States= 1.8e+07 Transitions= 6.11e+09 Memory= 1994.904 t= 6.49e+03 R= 3e+03 +Depth= 7831 States= 1.9e+07 Transitions= 6.54e+09 Memory= 2071.174 t= 6.95e+03 R= 3e+03 +Depth= 7831 States= 2e+07 Transitions= 6.89e+09 Memory= 2147.443 t= 7.32e+03 R= 3e+03 +Depth= 7991 States= 2.1e+07 Transitions= 7.11e+09 Memory= 2223.811 t= 7.55e+03 R= 3e+03 +Depth= 7991 States= 2.2e+07 Transitions= 7.39e+09 Memory= 2300.080 t= 7.85e+03 R= 3e+03 +Depth= 7991 States= 2.3e+07 Transitions= 7.59e+09 Memory= 2376.350 t= 8.06e+03 R= 3e+03 +Depth= 7991 States= 2.4e+07 Transitions= 7.86e+09 Memory= 2452.619 t= 8.35e+03 R= 3e+03 +Depth= 7991 States= 2.5e+07 Transitions= 8.07e+09 Memory= 2528.986 t= 8.58e+03 R= 3e+03 +Depth= 7991 States= 2.6e+07 Transitions= 8.31e+09 Memory= 2605.256 t= 8.83e+03 R= 3e+03 +Depth= 7991 States= 2.7e+07 Transitions= 8.55e+09 Memory= 2681.526 t= 9.09e+03 R= 3e+03 +Depth= 7991 States= 2.8e+07 Transitions= 8.79e+09 Memory= 2757.795 t= 9.35e+03 R= 3e+03 +Depth= 7991 States= 2.9e+07 Transitions= 9.03e+09 Memory= 2834.162 t= 9.61e+03 R= 3e+03 +Depth= 7991 States= 3e+07 Transitions= 9.24e+09 Memory= 2910.432 t= 9.83e+03 R= 3e+03 diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/result-ipi-urcu_free/asserts.spin.input b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/result-ipi-urcu_free/asserts.spin.input new file mode 100644 index 0000000..a3e31d3 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/result-ipi-urcu_free/asserts.spin.input @@ -0,0 +1,1191 @@ + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +//#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * Busy-looping waiting for other barrier requests is not considered as + * non-progress. + */ +#ifdef READER_PROGRESS +progress_reader2: +#endif +#ifdef WRITER_PROGRESS +//progress_writer_from_reader1: +#endif + skip; + :: 1 -> + /* We choose to ignore writer's non-progress caused from the + * reader ignoring the writer's mb() requests */ +#ifdef WRITER_PROGRESS +//progress_writer_from_reader2: +#endif + break; + od; +} + +#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; \ + /* \ + * 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) \ + do \ + :: (reader_barrier[i] == 1) -> skip; \ + :: (reader_barrier[i] == 0) -> break; \ + od; \ + i++; \ + :: i >= NR_READERS -> \ + break \ + od; \ + smp_mb(i, j); \ +} + +#else + +#define smp_mb_send(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + :: 1 -> skip; + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_PROC_FIRST_MB (1 << 1) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 2) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 3) +#define WRITE_PROC_FIRST_WAIT (1 << 4) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 5) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 6) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 7) +#define WRITE_PROC_SECOND_WAIT (1 << 8) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 9) + +#define WRITE_PROC_SECOND_MB (1 << 10) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 11) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 4) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + /* TODO : add instruction scheduling to this code path to test + * missing wmb effect. */ + /* smp_wmb() ensures order of the following instructions */ + /* malloc */ + cur_data = (cur_data + 1) % SLAB_SIZE; + ooo_mem(i); + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); +#ifndef NO_WMB + smp_wmb(i, j); +#else + ooo_mem(i); +#endif + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + + :: else -> break; + od; + /* + * 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 + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/result-ipi-urcu_free/references.txt b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/result-ipi-urcu_free/references.txt new file mode 100644 index 0000000..72c67a2 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/result-ipi-urcu_free/references.txt @@ -0,0 +1,13 @@ +http://spinroot.com/spin/Man/ltl.html +http://en.wikipedia.org/wiki/Linear_temporal_logic +http://www.dcs.gla.ac.uk/~muffy/MRS4-2002/lect11.ppt + +http://www.lsv.ens-cachan.fr/~gastin/ltl2ba/index.php +http://spinroot.com/spin/Man/index.html +http://spinroot.com/spin/Man/promela.html + +LTL vs CTL : + +http://spinroot.com/spin/Doc/course/lecture12.pdf p. 9, p. 15, p. 18 +http://www-i2.informatik.rwth-aachen.de/i2/fileadmin/user_upload/documents/Introduction_to_Model_Checking/mc_lec18.pdf + (downloaded) diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu.sh b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu.sh new file mode 100644 index 0000000..65ff517 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# +# Compiles and runs the urcu.spin Promela model. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# Copyright (C) IBM Corporation, 2009 +# Mathieu Desnoyers, 2009 +# +# Authors: Paul E. McKenney +# Mathieu Desnoyers + +# Basic execution, without LTL clauses. See Makefile. + +spin -a urcu.spin +cc -DSAFETY -o pan pan.c +./pan -v -c1 -X -m10000000 -w21 diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu.spin b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu.spin new file mode 100644 index 0000000..3751868 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu.spin @@ -0,0 +1,1212 @@ +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* We choose to ignore writer's non-progress caused from the + * reader ignoring the writer's mb() requests */ +#ifdef WRITER_PROGRESS +progress_writer_from_reader: +#endif + break; + od; +} + +#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: +#define PROGRESS_LABEL(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; \ + /* \ + * 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) \ + do \ + :: (reader_barrier[i] == 1) -> skip; \ + :: (reader_barrier[i] == 0) -> break; \ + od; \ + i++; \ + :: i >= NR_READERS -> \ + break \ + od; \ + smp_mb(i, j); \ +} + +#else + +#define smp_mb_send(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + :: 1 -> skip; + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu.spin.bkp.b4ptr b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu.spin.bkp.b4ptr new file mode 100644 index 0000000..6670f3e --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu.spin.bkp.b4ptr @@ -0,0 +1,1123 @@ +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bit { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bit cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(generation_ptr, get_pid()); + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(generation_ptr, get_pid()); + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * Busy-looping waiting for other barrier requests is not considered as + * non-progress. + */ +#ifdef READER_PROGRESS +progress_reader2: +#endif +#ifdef WRITER_PROGRESS +//progress_writer_from_reader1: +#endif + skip; + :: 1 -> + /* We choose to ignore writer's non-progress caused from the + * reader ignoring the writer's mb() requests */ +#ifdef WRITER_PROGRESS +//progress_writer_from_reader2: +#endif + break; + od; +} + +#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; \ + /* \ + * 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) \ + do \ + :: (reader_barrier[i] == 1) -> skip; \ + :: (reader_barrier[i] == 0) -> break; \ + od; \ + i++; \ + :: i >= NR_READERS -> \ + break \ + od; \ + smp_mb(i, j); \ +} + +#else + +#define smp_mb_send(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, wmp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only two readers */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* pointer generation */ +DECLARE_CACHED_VAR(byte, generation_ptr); + +byte last_free_gen = 0; +bit free_done = 0; +byte read_generation[NR_READERS]; +bit data_access[NR_READERS]; + +bit write_lock = 0; + +bit init_done = 0; + +bit sighand_exec = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(generation_ptr, get_pid()); + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(generation_ptr, get_pid()); + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + :: 1 -> skip; + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + read_generation[get_readerid()] = + READ_CACHED_VAR(generation_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + ooo_mem(i); + goto non_atomic; +non_atomic_end: + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + read_generation[get_readerid()] = + READ_CACHED_VAR(generation_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + ooo_mem(i); + goto non_atomic2; +non_atomic2_end: + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +non_atomic: + data_access[get_readerid()] = 1; + data_access[get_readerid()] = 0; + goto non_atomic_end; +non_atomic2: + data_access[get_readerid()] = 1; + data_access[get_readerid()] = 0; + goto non_atomic2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_PROC_FIRST_MB (1 << 1) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 2) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 3) +#define WRITE_PROC_FIRST_WAIT (1 << 4) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 5) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 6) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 7) +#define WRITE_PROC_SECOND_WAIT (1 << 8) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 9) + +#define WRITE_PROC_SECOND_MB (1 << 10) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 11) - 1) + +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte old_gen; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (READ_CACHED_VAR(generation_ptr) < 5) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + ooo_mem(i); + atomic { + 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; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + + write_lock = 0; + /* free-up step, e.g., kfree(). */ + atomic { + last_free_gen = old_gen; + free_done = 1; + } + :: else -> break; + od; + /* + * 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 + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(generation_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + read_generation[i] = 1; + data_access[i] = 0; + i++; + :: i >= NR_READERS -> break + od; + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free.log b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free.log new file mode 100644 index 0000000..886469c --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free.log @@ -0,0 +1,584 @@ +make[1]: Entering directory `/home/compudj/doc/userspace-rcu/formal-model/urcu-controldataflow' +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define >> pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_free.ltl | grep -v ^//`)" >> pan.ltl +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1244) +Depth= 8092 States= 1e+06 Transitions= 1.63e+08 Memory= 550.432 t= 202 R= 5e+03 +Depth= 9706 States= 2e+06 Transitions= 3.34e+08 Memory= 634.318 t= 421 R= 5e+03 +Depth= 9706 States= 3e+06 Transitions= 5.11e+08 Memory= 718.303 t= 649 R= 5e+03 +pan: resizing hashtable to -w22.. done +Depth= 9706 States= 4e+06 Transitions= 6.76e+08 Memory= 833.311 t= 855 R= 5e+03 +Depth= 9706 States= 5e+06 Transitions= 9e+08 Memory= 917.295 t= 1.14e+03 R= 4e+03 +Depth= 9706 States= 6e+06 Transitions= 1.34e+09 Memory= 1001.279 t= 1.7e+03 R= 4e+03 +Depth= 9706 States= 7e+06 Transitions= 1.71e+09 Memory= 1085.264 t= 2.18e+03 R= 3e+03 +Depth= 9706 States= 8e+06 Transitions= 2.07e+09 Memory= 1169.151 t= 2.65e+03 R= 3e+03 +Depth= 9706 States= 9e+06 Transitions= 2.39e+09 Memory= 1253.135 t= 3.08e+03 R= 3e+03 +pan: resizing hashtable to -w24.. done +Depth= 9706 States= 1e+07 Transitions= 2.59e+09 Memory= 1461.115 t= 3.33e+03 R= 3e+03 +Depth= 9706 States= 1.1e+07 Transitions= 2.89e+09 Memory= 1545.100 t= 3.7e+03 R= 3e+03 +Depth= 9706 States= 1.2e+07 Transitions= 3.23e+09 Memory= 1629.084 t= 4.14e+03 R= 3e+03 +Depth= 9706 States= 1.3e+07 Transitions= 3.94e+09 Memory= 1713.068 t= 5.07e+03 R= 3e+03 +Depth= 9706 States= 1.4e+07 Transitions= 4.65e+09 Memory= 1797.053 t= 5.99e+03 R= 2e+03 +Depth= 9706 States= 1.5e+07 Transitions= 5.08e+09 Memory= 1881.037 t= 6.56e+03 R= 2e+03 +Depth= 9706 States= 1.6e+07 Transitions= 5.5e+09 Memory= 1964.924 t= 7.11e+03 R= 2e+03 +Depth= 9706 States= 1.7e+07 Transitions= 5.7e+09 Memory= 2048.908 t= 7.35e+03 R= 2e+03 +Depth= 9706 States= 1.8e+07 Transitions= 6.12e+09 Memory= 2132.893 t= 7.9e+03 R= 2e+03 +Depth= 9706 States= 1.9e+07 Transitions= 6.54e+09 Memory= 2216.877 t= 8.45e+03 R= 2e+03 +Depth= 9706 States= 2e+07 Transitions= 6.89e+09 Memory= 2300.861 t= 8.91e+03 R= 2e+03 +Depth= 9744 States= 2.1e+07 Transitions= 7.11e+09 Memory= 2384.846 t= 9.18e+03 R= 2e+03 +Depth= 9744 States= 2.2e+07 Transitions= 7.39e+09 Memory= 2468.830 t= 9.54e+03 R= 2e+03 +Depth= 9744 States= 2.3e+07 Transitions= 7.59e+09 Memory= 2552.717 t= 9.81e+03 R= 2e+03 +Depth= 9744 States= 2.4e+07 Transitions= 7.86e+09 Memory= 2636.701 t= 1.02e+04 R= 2e+03 +Depth= 9744 States= 2.5e+07 Transitions= 8.07e+09 Memory= 2720.686 t= 1.04e+04 R= 2e+03 +Depth= 9744 States= 2.6e+07 Transitions= 8.31e+09 Memory= 2804.670 t= 1.07e+04 R= 2e+03 +Depth= 9744 States= 2.7e+07 Transitions= 8.55e+09 Memory= 2888.654 t= 1.11e+04 R= 2e+03 +Depth= 9744 States= 2.8e+07 Transitions= 8.79e+09 Memory= 2972.639 t= 1.14e+04 R= 2e+03 +Depth= 9744 States= 2.9e+07 Transitions= 9.03e+09 Memory= 3056.526 t= 1.17e+04 R= 2e+03 +Depth= 9744 States= 3e+07 Transitions= 9.24e+09 Memory= 3140.510 t= 1.2e+04 R= 3e+03 +Depth= 9744 States= 3.1e+07 Transitions= 9.55e+09 Memory= 3224.494 t= 1.24e+04 R= 3e+03 +Depth= 9744 States= 3.2e+07 Transitions= 1e+10 Memory= 3308.479 t= 1.3e+04 R= 2e+03 +Depth= 9744 States= 3.3e+07 Transitions= 1.04e+10 Memory= 3392.463 t= 1.35e+04 R= 2e+03 +Depth= 9744 States= 3.4e+07 Transitions= 1.08e+10 Memory= 3476.447 t= 1.4e+04 R= 2e+03 +pan: resizing hashtable to -w26.. done +Depth= 9744 States= 3.5e+07 Transitions= 1.11e+10 Memory= 4056.416 t= 1.45e+04 R= 2e+03 +Depth= 9744 States= 3.6e+07 Transitions= 1.14e+10 Memory= 4140.401 t= 1.47e+04 R= 2e+03 +Depth= 9744 States= 3.7e+07 Transitions= 1.16e+10 Memory= 4224.385 t= 1.51e+04 R= 2e+03 +Depth= 9744 States= 3.8e+07 Transitions= 1.19e+10 Memory= 4308.369 t= 1.54e+04 R= 2e+03 +Depth= 9744 States= 3.9e+07 Transitions= 1.25e+10 Memory= 4392.354 t= 1.62e+04 R= 2e+03 +Depth= 9744 States= 4e+07 Transitions= 1.33e+10 Memory= 4476.338 t= 1.72e+04 R= 2e+03 +Depth= 9744 States= 4.1e+07 Transitions= 1.38e+10 Memory= 4560.225 t= 1.79e+04 R= 2e+03 +Depth= 9744 States= 4.2e+07 Transitions= 1.43e+10 Memory= 4644.209 t= 1.86e+04 R= 2e+03 +Depth= 9744 States= 4.3e+07 Transitions= 1.45e+10 Memory= 4728.193 t= 1.88e+04 R= 2e+03 +Depth= 9744 States= 4.4e+07 Transitions= 1.48e+10 Memory= 4812.178 t= 1.92e+04 R= 2e+03 +Depth= 9744 States= 4.5e+07 Transitions= 1.52e+10 Memory= 4896.162 t= 1.97e+04 R= 2e+03 +Depth= 9744 States= 4.6e+07 Transitions= 1.55e+10 Memory= 4980.147 t= 2.02e+04 R= 2e+03 +Depth= 9744 States= 4.7e+07 Transitions= 1.58e+10 Memory= 5064.131 t= 2.05e+04 R= 2e+03 +Depth= 9744 States= 4.8e+07 Transitions= 1.61e+10 Memory= 5148.018 t= 2.08e+04 R= 2e+03 +Depth= 9744 States= 4.9e+07 Transitions= 1.63e+10 Memory= 5232.002 t= 2.11e+04 R= 2e+03 +Depth= 9744 States= 5e+07 Transitions= 1.66e+10 Memory= 5315.986 t= 2.15e+04 R= 2e+03 +Depth= 9744 States= 5.1e+07 Transitions= 1.68e+10 Memory= 5399.971 t= 2.17e+04 R= 2e+03 +Depth= 9744 States= 5.2e+07 Transitions= 1.7e+10 Memory= 5483.955 t= 2.2e+04 R= 2e+03 +Depth= 9744 States= 5.3e+07 Transitions= 1.72e+10 Memory= 5567.940 t= 2.23e+04 R= 2e+03 +Depth= 9744 States= 5.4e+07 Transitions= 1.75e+10 Memory= 5651.826 t= 2.26e+04 R= 2e+03 +Depth= 9744 States= 5.5e+07 Transitions= 1.77e+10 Memory= 5735.811 t= 2.29e+04 R= 2e+03 +Depth= 9744 States= 5.6e+07 Transitions= 1.79e+10 Memory= 5819.795 t= 2.32e+04 R= 2e+03 +Depth= 9744 States= 5.7e+07 Transitions= 1.83e+10 Memory= 5903.779 t= 2.36e+04 R= 2e+03 +Depth= 9744 States= 5.8e+07 Transitions= 1.87e+10 Memory= 5987.764 t= 2.42e+04 R= 2e+03 +Depth= 9744 States= 5.9e+07 Transitions= 1.91e+10 Memory= 6071.748 t= 2.46e+04 R= 2e+03 +Depth= 9744 States= 6e+07 Transitions= 1.94e+10 Memory= 6155.733 t= 2.51e+04 R= 2e+03 +Depth= 9744 States= 6.1e+07 Transitions= 1.98e+10 Memory= 6239.619 t= 2.56e+04 R= 2e+03 +Depth= 9744 States= 6.2e+07 Transitions= 2.02e+10 Memory= 6323.604 t= 2.61e+04 R= 2e+03 + +(Spin Version 5.1.7 -- 23 December 2008) + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness disabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 9744, errors: 0 + 62203844 states, stored +2.0186786e+10 states, matched +2.024899e+10 transitions (= stored+matched) +1.1642436e+11 atomic steps +hash conflicts: 1.1759978e+10 (resolved) + +Stats on memory usage (in Megabytes): + 6881.376 equivalent memory usage for states (stored*(State-vector + overhead)) + 5374.024 actual memory usage for states (compression: 78.10%) + state-vector as stored = 63 byte + 28 byte overhead + 512.000 memory used for hash table (-w26) + 457.764 memory used for DFS stack (-m10000000) + 2.996 memory lost to fragmentation + 6340.791 total actual memory usage + +unreached in proctype urcu_reader + line 249, "pan.___", state 32, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 54, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 63, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 79, "(1)" + line 230, "pan.___", state 87, "(1)" + line 234, "pan.___", state 99, "(1)" + line 238, "pan.___", state 107, "(1)" + line 386, "pan.___", state 132, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 164, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 178, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 403, "pan.___", state 197, "(1)" + line 412, "pan.___", state 227, "(1)" + line 416, "pan.___", state 240, "(1)" + line 662, "pan.___", state 261, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 386, "pan.___", state 268, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 300, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 314, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 403, "pan.___", state 333, "(1)" + line 412, "pan.___", state 363, "(1)" + line 416, "pan.___", state 376, "(1)" + line 386, "pan.___", state 397, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 429, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 443, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 403, "pan.___", state 462, "(1)" + line 412, "pan.___", state 492, "(1)" + line 416, "pan.___", state 505, "(1)" + line 386, "pan.___", state 528, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 386, "pan.___", state 530, "(1)" + line 386, "pan.___", state 531, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 386, "pan.___", state 531, "else" + line 386, "pan.___", state 534, "(1)" + line 390, "pan.___", state 542, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 390, "pan.___", state 544, "(1)" + line 390, "pan.___", state 545, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 390, "pan.___", state 545, "else" + line 390, "pan.___", state 548, "(1)" + line 390, "pan.___", state 549, "(1)" + line 390, "pan.___", state 549, "(1)" + line 388, "pan.___", state 554, "((i<1))" + line 388, "pan.___", state 554, "((i>=1))" + line 395, "pan.___", state 560, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 562, "(1)" + line 395, "pan.___", state 563, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 563, "else" + line 395, "pan.___", state 566, "(1)" + line 395, "pan.___", state 567, "(1)" + line 395, "pan.___", state 567, "(1)" + line 399, "pan.___", state 574, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 399, "pan.___", state 576, "(1)" + line 399, "pan.___", state 577, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 399, "pan.___", state 577, "else" + line 399, "pan.___", state 580, "(1)" + line 399, "pan.___", state 581, "(1)" + line 399, "pan.___", state 581, "(1)" + line 397, "pan.___", state 586, "((i<2))" + line 397, "pan.___", state 586, "((i>=2))" + line 403, "pan.___", state 593, "(1)" + line 403, "pan.___", state 594, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 403, "pan.___", state 594, "else" + line 403, "pan.___", state 597, "(1)" + line 403, "pan.___", state 598, "(1)" + line 403, "pan.___", state 598, "(1)" + line 407, "pan.___", state 606, "(1)" + line 407, "pan.___", state 607, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 407, "pan.___", state 607, "else" + line 407, "pan.___", state 610, "(1)" + line 407, "pan.___", state 611, "(1)" + line 407, "pan.___", state 611, "(1)" + line 405, "pan.___", state 616, "((i<1))" + line 405, "pan.___", state 616, "((i>=1))" + line 412, "pan.___", state 623, "(1)" + line 412, "pan.___", state 624, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 624, "else" + line 412, "pan.___", state 627, "(1)" + line 412, "pan.___", state 628, "(1)" + line 412, "pan.___", state 628, "(1)" + line 416, "pan.___", state 636, "(1)" + line 416, "pan.___", state 637, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 416, "pan.___", state 637, "else" + line 416, "pan.___", state 640, "(1)" + line 416, "pan.___", state 641, "(1)" + line 416, "pan.___", state 641, "(1)" + line 414, "pan.___", state 646, "((i<2))" + line 414, "pan.___", state 646, "((i>=2))" + line 421, "pan.___", state 650, "(1)" + line 421, "pan.___", state 650, "(1)" + line 662, "pan.___", state 653, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 662, "pan.___", state 654, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 662, "pan.___", state 655, "(1)" + line 386, "pan.___", state 662, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 694, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 708, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 403, "pan.___", state 727, "(1)" + line 412, "pan.___", state 757, "(1)" + line 416, "pan.___", state 770, "(1)" + line 386, "pan.___", state 798, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 386, "pan.___", state 800, "(1)" + line 386, "pan.___", state 801, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 386, "pan.___", state 801, "else" + line 386, "pan.___", state 804, "(1)" + line 390, "pan.___", state 812, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 390, "pan.___", state 814, "(1)" + line 390, "pan.___", state 815, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 390, "pan.___", state 815, "else" + line 390, "pan.___", state 818, "(1)" + line 390, "pan.___", state 819, "(1)" + line 390, "pan.___", state 819, "(1)" + line 388, "pan.___", state 824, "((i<1))" + line 388, "pan.___", state 824, "((i>=1))" + line 395, "pan.___", state 830, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 832, "(1)" + line 395, "pan.___", state 833, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 833, "else" + line 395, "pan.___", state 836, "(1)" + line 395, "pan.___", state 837, "(1)" + line 395, "pan.___", state 837, "(1)" + line 399, "pan.___", state 844, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 399, "pan.___", state 846, "(1)" + line 399, "pan.___", state 847, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 399, "pan.___", state 847, "else" + line 399, "pan.___", state 850, "(1)" + line 399, "pan.___", state 851, "(1)" + line 399, "pan.___", state 851, "(1)" + line 397, "pan.___", state 856, "((i<2))" + line 397, "pan.___", state 856, "((i>=2))" + line 403, "pan.___", state 863, "(1)" + line 403, "pan.___", state 864, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 403, "pan.___", state 864, "else" + line 403, "pan.___", state 867, "(1)" + line 403, "pan.___", state 868, "(1)" + line 403, "pan.___", state 868, "(1)" + line 407, "pan.___", state 876, "(1)" + line 407, "pan.___", state 877, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 407, "pan.___", state 877, "else" + line 407, "pan.___", state 880, "(1)" + line 407, "pan.___", state 881, "(1)" + line 407, "pan.___", state 881, "(1)" + line 405, "pan.___", state 886, "((i<1))" + line 405, "pan.___", state 886, "((i>=1))" + line 412, "pan.___", state 893, "(1)" + line 412, "pan.___", state 894, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 894, "else" + line 412, "pan.___", state 897, "(1)" + line 412, "pan.___", state 898, "(1)" + line 412, "pan.___", state 898, "(1)" + line 416, "pan.___", state 906, "(1)" + line 416, "pan.___", state 907, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 416, "pan.___", state 907, "else" + line 416, "pan.___", state 910, "(1)" + line 416, "pan.___", state 911, "(1)" + line 416, "pan.___", state 911, "(1)" + line 421, "pan.___", state 920, "(1)" + line 421, "pan.___", state 920, "(1)" + line 386, "pan.___", state 927, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 386, "pan.___", state 929, "(1)" + line 386, "pan.___", state 930, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 386, "pan.___", state 930, "else" + line 386, "pan.___", state 933, "(1)" + line 390, "pan.___", state 941, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 390, "pan.___", state 943, "(1)" + line 390, "pan.___", state 944, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 390, "pan.___", state 944, "else" + line 390, "pan.___", state 947, "(1)" + line 390, "pan.___", state 948, "(1)" + line 390, "pan.___", state 948, "(1)" + line 388, "pan.___", state 953, "((i<1))" + line 388, "pan.___", state 953, "((i>=1))" + line 395, "pan.___", state 959, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 961, "(1)" + line 395, "pan.___", state 962, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 962, "else" + line 395, "pan.___", state 965, "(1)" + line 395, "pan.___", state 966, "(1)" + line 395, "pan.___", state 966, "(1)" + line 399, "pan.___", state 973, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 399, "pan.___", state 975, "(1)" + line 399, "pan.___", state 976, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 399, "pan.___", state 976, "else" + line 399, "pan.___", state 979, "(1)" + line 399, "pan.___", state 980, "(1)" + line 399, "pan.___", state 980, "(1)" + line 397, "pan.___", state 985, "((i<2))" + line 397, "pan.___", state 985, "((i>=2))" + line 403, "pan.___", state 992, "(1)" + line 403, "pan.___", state 993, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 403, "pan.___", state 993, "else" + line 403, "pan.___", state 996, "(1)" + line 403, "pan.___", state 997, "(1)" + line 403, "pan.___", state 997, "(1)" + line 407, "pan.___", state 1005, "(1)" + line 407, "pan.___", state 1006, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 407, "pan.___", state 1006, "else" + line 407, "pan.___", state 1009, "(1)" + line 407, "pan.___", state 1010, "(1)" + line 407, "pan.___", state 1010, "(1)" + line 405, "pan.___", state 1015, "((i<1))" + line 405, "pan.___", state 1015, "((i>=1))" + line 412, "pan.___", state 1022, "(1)" + line 412, "pan.___", state 1023, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 1023, "else" + line 412, "pan.___", state 1026, "(1)" + line 412, "pan.___", state 1027, "(1)" + line 412, "pan.___", state 1027, "(1)" + line 416, "pan.___", state 1035, "(1)" + line 416, "pan.___", state 1036, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 416, "pan.___", state 1036, "else" + line 416, "pan.___", state 1039, "(1)" + line 416, "pan.___", state 1040, "(1)" + line 416, "pan.___", state 1040, "(1)" + line 414, "pan.___", state 1045, "((i<2))" + line 414, "pan.___", state 1045, "((i>=2))" + line 421, "pan.___", state 1049, "(1)" + line 421, "pan.___", state 1049, "(1)" + line 670, "pan.___", state 1053, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 386, "pan.___", state 1058, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 1090, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1104, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1123, "(1)" + line 412, "pan.___", state 1153, "(1)" + line 416, "pan.___", state 1166, "(1)" + line 386, "pan.___", state 1190, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 1222, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1236, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1255, "(1)" + line 412, "pan.___", state 1285, "(1)" + line 416, "pan.___", state 1298, "(1)" + line 386, "pan.___", state 1323, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 1355, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1369, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1388, "(1)" + line 412, "pan.___", state 1418, "(1)" + line 416, "pan.___", state 1431, "(1)" + line 386, "pan.___", state 1452, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 1484, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1498, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1517, "(1)" + line 412, "pan.___", state 1547, "(1)" + line 416, "pan.___", state 1560, "(1)" + line 386, "pan.___", state 1586, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 1618, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1632, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1651, "(1)" + line 412, "pan.___", state 1681, "(1)" + line 416, "pan.___", state 1694, "(1)" + line 386, "pan.___", state 1715, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 1747, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1761, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1780, "(1)" + line 412, "pan.___", state 1810, "(1)" + line 416, "pan.___", state 1823, "(1)" + line 386, "pan.___", state 1847, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 1879, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1893, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1912, "(1)" + line 412, "pan.___", state 1942, "(1)" + line 416, "pan.___", state 1955, "(1)" + line 709, "pan.___", state 1976, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 386, "pan.___", state 1983, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 2015, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2029, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 403, "pan.___", state 2048, "(1)" + line 412, "pan.___", state 2078, "(1)" + line 416, "pan.___", state 2091, "(1)" + line 386, "pan.___", state 2112, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 2144, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2158, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 403, "pan.___", state 2177, "(1)" + line 412, "pan.___", state 2207, "(1)" + line 416, "pan.___", state 2220, "(1)" + line 386, "pan.___", state 2243, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 386, "pan.___", state 2245, "(1)" + line 386, "pan.___", state 2246, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 386, "pan.___", state 2246, "else" + line 386, "pan.___", state 2249, "(1)" + line 390, "pan.___", state 2257, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 390, "pan.___", state 2259, "(1)" + line 390, "pan.___", state 2260, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 390, "pan.___", state 2260, "else" + line 390, "pan.___", state 2263, "(1)" + line 390, "pan.___", state 2264, "(1)" + line 390, "pan.___", state 2264, "(1)" + line 388, "pan.___", state 2269, "((i<1))" + line 388, "pan.___", state 2269, "((i>=1))" + line 395, "pan.___", state 2275, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 2277, "(1)" + line 395, "pan.___", state 2278, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 2278, "else" + line 395, "pan.___", state 2281, "(1)" + line 395, "pan.___", state 2282, "(1)" + line 395, "pan.___", state 2282, "(1)" + line 399, "pan.___", state 2289, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2291, "(1)" + line 399, "pan.___", state 2292, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 399, "pan.___", state 2292, "else" + line 399, "pan.___", state 2295, "(1)" + line 399, "pan.___", state 2296, "(1)" + line 399, "pan.___", state 2296, "(1)" + line 397, "pan.___", state 2301, "((i<2))" + line 397, "pan.___", state 2301, "((i>=2))" + line 403, "pan.___", state 2308, "(1)" + line 403, "pan.___", state 2309, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 403, "pan.___", state 2309, "else" + line 403, "pan.___", state 2312, "(1)" + line 403, "pan.___", state 2313, "(1)" + line 403, "pan.___", state 2313, "(1)" + line 407, "pan.___", state 2321, "(1)" + line 407, "pan.___", state 2322, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 407, "pan.___", state 2322, "else" + line 407, "pan.___", state 2325, "(1)" + line 407, "pan.___", state 2326, "(1)" + line 407, "pan.___", state 2326, "(1)" + line 405, "pan.___", state 2331, "((i<1))" + line 405, "pan.___", state 2331, "((i>=1))" + line 412, "pan.___", state 2338, "(1)" + line 412, "pan.___", state 2339, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 2339, "else" + line 412, "pan.___", state 2342, "(1)" + line 412, "pan.___", state 2343, "(1)" + line 412, "pan.___", state 2343, "(1)" + line 416, "pan.___", state 2351, "(1)" + line 416, "pan.___", state 2352, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 416, "pan.___", state 2352, "else" + line 416, "pan.___", state 2355, "(1)" + line 416, "pan.___", state 2356, "(1)" + line 416, "pan.___", state 2356, "(1)" + line 414, "pan.___", state 2361, "((i<2))" + line 414, "pan.___", state 2361, "((i>=2))" + line 421, "pan.___", state 2365, "(1)" + line 421, "pan.___", state 2365, "(1)" + line 709, "pan.___", state 2368, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 709, "pan.___", state 2369, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 709, "pan.___", state 2370, "(1)" + line 386, "pan.___", state 2377, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 2409, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2423, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 403, "pan.___", state 2442, "(1)" + line 412, "pan.___", state 2472, "(1)" + line 416, "pan.___", state 2485, "(1)" + line 386, "pan.___", state 2512, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 2544, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2558, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 403, "pan.___", state 2577, "(1)" + line 412, "pan.___", state 2607, "(1)" + line 416, "pan.___", state 2620, "(1)" + line 386, "pan.___", state 2641, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 2673, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2687, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 403, "pan.___", state 2706, "(1)" + line 412, "pan.___", state 2736, "(1)" + line 416, "pan.___", state 2749, "(1)" + line 226, "pan.___", state 2782, "(1)" + line 234, "pan.___", state 2802, "(1)" + line 238, "pan.___", state 2810, "(1)" + line 226, "pan.___", state 2825, "(1)" + line 234, "pan.___", state 2845, "(1)" + line 238, "pan.___", state 2853, "(1)" + line 869, "pan.___", state 2870, "-end-" + (278 of 2870 states) +unreached in proctype urcu_writer + line 386, "pan.___", state 18, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 390, "pan.___", state 32, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 50, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 83, "(1)" + line 407, "pan.___", state 96, "(1)" + line 412, "pan.___", state 113, "(1)" + line 249, "pan.___", state 149, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 158, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 171, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 386, "pan.___", state 211, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 390, "pan.___", state 225, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 243, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 257, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 403, "pan.___", state 276, "(1)" + line 407, "pan.___", state 289, "(1)" + line 412, "pan.___", state 306, "(1)" + line 416, "pan.___", state 319, "(1)" + line 390, "pan.___", state 356, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 374, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 388, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, "pan.___", state 420, "(1)" + line 412, "pan.___", state 437, "(1)" + line 416, "pan.___", state 450, "(1)" + line 390, "pan.___", state 494, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 512, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 526, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, "pan.___", state 558, "(1)" + line 412, "pan.___", state 575, "(1)" + line 416, "pan.___", state 588, "(1)" + line 390, "pan.___", state 623, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 641, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 655, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, "pan.___", state 687, "(1)" + line 412, "pan.___", state 704, "(1)" + line 416, "pan.___", state 717, "(1)" + line 390, "pan.___", state 754, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 772, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 786, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, "pan.___", state 818, "(1)" + line 412, "pan.___", state 835, "(1)" + line 416, "pan.___", state 848, "(1)" + line 249, "pan.___", state 903, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 912, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 927, "(1)" + line 261, "pan.___", state 934, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 950, "(1)" + line 230, "pan.___", state 958, "(1)" + line 234, "pan.___", state 970, "(1)" + line 238, "pan.___", state 978, "(1)" + line 249, "pan.___", state 1009, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 1018, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 1031, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1040, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 1056, "(1)" + line 230, "pan.___", state 1064, "(1)" + line 234, "pan.___", state 1076, "(1)" + line 238, "pan.___", state 1084, "(1)" + line 253, "pan.___", state 1110, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 1123, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1132, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 1148, "(1)" + line 230, "pan.___", state 1156, "(1)" + line 234, "pan.___", state 1168, "(1)" + line 238, "pan.___", state 1176, "(1)" + line 249, "pan.___", state 1207, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 1216, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 1229, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1238, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 1254, "(1)" + line 230, "pan.___", state 1262, "(1)" + line 234, "pan.___", state 1274, "(1)" + line 238, "pan.___", state 1282, "(1)" + line 253, "pan.___", state 1308, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 1321, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1330, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 1346, "(1)" + line 230, "pan.___", state 1354, "(1)" + line 234, "pan.___", state 1366, "(1)" + line 238, "pan.___", state 1374, "(1)" + line 249, "pan.___", state 1405, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 1414, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 1427, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1436, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 1452, "(1)" + line 230, "pan.___", state 1460, "(1)" + line 234, "pan.___", state 1472, "(1)" + line 238, "pan.___", state 1480, "(1)" + line 253, "pan.___", state 1506, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 1519, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1528, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 1544, "(1)" + line 230, "pan.___", state 1552, "(1)" + line 234, "pan.___", state 1564, "(1)" + line 238, "pan.___", state 1572, "(1)" + line 249, "pan.___", state 1603, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 1612, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 1625, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1634, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 1650, "(1)" + line 230, "pan.___", state 1658, "(1)" + line 234, "pan.___", state 1670, "(1)" + line 238, "pan.___", state 1678, "(1)" + line 1190, "pan.___", state 1694, "-end-" + (103 of 1694 states) +unreached in proctype :init: + (0 of 78 states) +unreached in proctype :never: + line 1249, "pan.___", state 8, "-end-" + (1 of 8 states) + +pan: elapsed time 2.62e+04 seconds +pan: rate 2378.2573 states/second +pan: avg transition delay 1.2917e-06 usec +cp .input.spin urcu_free.spin.input +cp .input.spin.trail urcu_free.spin.input.trail +make[1]: Leaving directory `/home/compudj/doc/userspace-rcu/formal-model/urcu-controldataflow' diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free.ltl b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free.ltl new file mode 100644 index 0000000..6be1be9 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free.ltl @@ -0,0 +1 @@ +[] (!read_poison) diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free.spin.input b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free.spin.input new file mode 100644 index 0000000..527f16e --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free.spin.input @@ -0,0 +1,1226 @@ + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* We choose to ignore writer's non-progress caused from the + * reader ignoring the writer's mb() requests */ +#ifdef WRITER_PROGRESS +progress_writer_from_reader: +#endif + break; + od; +} + +#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: +#define PROGRESS_LABEL(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; \ + /* \ + * 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) \ + do \ + :: (reader_barrier[i] == 1) -> skip; \ + :: (reader_barrier[i] == 0) -> break; \ + od; \ + i++; \ + :: i >= NR_READERS -> \ + break \ + od; \ + smp_mb(i, j); \ +} + +#else + +#define smp_mb_send(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + :: 1 -> skip; + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free.spin.input.trail b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free.spin.input.trail new file mode 100644 index 0000000..011045f --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free.spin.input.trail @@ -0,0 +1,2598 @@ +-2:3:-2 +-4:-4:-4 +1:0:4863 +2:3:4786 +3:3:4789 +4:3:4789 +5:3:4792 +6:3:4800 +7:3:4800 +8:3:4803 +9:3:4809 +10:3:4813 +11:3:4813 +12:3:4816 +13:3:4823 +14:3:4831 +15:3:4831 +16:3:4834 +17:3:4840 +18:3:4844 +19:3:4844 +20:3:4847 +21:3:4853 +22:3:4857 +23:3:4858 +24:0:4863 +25:3:4860 +26:0:4863 +27:2:3279 +28:0:4863 +29:2:3285 +30:0:4863 +31:2:3286 +32:0:4863 +33:2:3289 +34:2:3293 +35:2:3294 +36:2:3302 +37:2:3303 +38:2:3307 +39:2:3308 +40:2:3316 +41:2:3321 +42:2:3325 +43:2:3326 +44:2:3334 +45:2:3335 +46:2:3339 +47:2:3340 +48:2:3334 +49:2:3335 +50:2:3339 +51:2:3340 +52:2:3348 +53:2:3353 +54:2:3354 +55:2:3365 +56:2:3366 +57:2:3367 +58:2:3378 +59:2:3383 +60:2:3384 +61:2:3395 +62:2:3396 +63:2:3397 +64:2:3395 +65:2:3396 +66:2:3397 +67:2:3408 +68:2:3412 +69:0:4863 +70:2:3415 +71:0:4863 +72:2:3421 +73:2:3422 +74:2:3426 +75:2:3430 +76:2:3431 +77:2:3435 +78:2:3443 +79:2:3444 +80:2:3448 +81:2:3452 +82:2:3453 +83:2:3448 +84:2:3449 +85:2:3457 +86:2:3461 +87:0:4863 +88:2:3464 +89:0:4863 +90:2:3465 +91:2:3469 +92:2:3470 +93:2:3478 +94:2:3479 +95:2:3483 +96:2:3484 +97:2:3492 +98:2:3497 +99:2:3501 +100:2:3502 +101:2:3510 +102:2:3511 +103:2:3515 +104:2:3516 +105:2:3510 +106:2:3511 +107:2:3515 +108:2:3516 +109:2:3524 +110:2:3529 +111:2:3530 +112:2:3541 +113:2:3542 +114:2:3543 +115:2:3554 +116:2:3559 +117:2:3560 +118:2:3571 +119:2:3572 +120:2:3573 +121:2:3571 +122:2:3572 +123:2:3573 +124:2:3584 +125:2:3588 +126:0:4863 +127:2:3591 +128:0:4863 +129:2:3594 +130:2:3598 +131:2:3599 +132:2:3607 +133:2:3608 +134:2:3612 +135:2:3613 +136:2:3621 +137:2:3626 +138:2:3627 +139:2:3639 +140:2:3640 +141:2:3644 +142:2:3645 +143:2:3639 +144:2:3640 +145:2:3644 +146:2:3645 +147:2:3653 +148:2:3658 +149:2:3659 +150:2:3670 +151:2:3671 +152:2:3672 +153:2:3683 +154:2:3688 +155:2:3689 +156:2:3700 +157:2:3701 +158:2:3702 +159:2:3700 +160:2:3701 +161:2:3702 +162:2:3713 +163:2:3717 +164:0:4863 +165:2:3720 +166:0:4863 +167:2:3721 +168:0:4863 +169:2:3722 +170:0:4863 +171:2:4423 +172:2:4424 +173:2:4428 +174:2:4432 +175:2:4433 +176:2:4437 +177:2:4445 +178:2:4446 +179:2:4450 +180:2:4454 +181:2:4455 +182:2:4450 +183:2:4454 +184:2:4455 +185:2:4459 +186:2:4466 +187:2:4473 +188:2:4474 +189:2:4481 +190:2:4486 +191:2:4493 +192:2:4494 +193:2:4493 +194:2:4494 +195:2:4501 +196:2:4505 +197:0:4863 +198:2:3724 +199:2:4401 +200:0:4863 +201:2:3721 +202:0:4863 +203:2:3725 +204:0:4863 +205:2:3721 +206:0:4863 +207:2:3728 +208:2:3729 +209:2:3733 +210:2:3734 +211:2:3742 +212:2:3743 +213:2:3747 +214:2:3748 +215:2:3756 +216:2:3761 +217:2:3765 +218:2:3766 +219:2:3774 +220:2:3775 +221:2:3779 +222:2:3780 +223:2:3774 +224:2:3775 +225:2:3779 +226:2:3780 +227:2:3788 +228:2:3793 +229:2:3794 +230:2:3805 +231:2:3806 +232:2:3807 +233:2:3818 +234:2:3823 +235:2:3824 +236:2:3835 +237:2:3836 +238:2:3837 +239:2:3835 +240:2:3836 +241:2:3837 +242:2:3848 +243:2:3855 +244:0:4863 +245:2:3721 +246:0:4863 +247:2:3859 +248:2:3860 +249:2:3861 +250:2:3873 +251:2:3874 +252:2:3878 +253:2:3879 +254:2:3887 +255:2:3892 +256:2:3896 +257:2:3897 +258:2:3905 +259:2:3906 +260:2:3910 +261:2:3911 +262:2:3905 +263:2:3906 +264:2:3910 +265:2:3911 +266:2:3919 +267:2:3924 +268:2:3925 +269:2:3936 +270:2:3937 +271:2:3938 +272:2:3949 +273:2:3954 +274:2:3955 +275:2:3966 +276:2:3967 +277:2:3968 +278:2:3966 +279:2:3967 +280:2:3968 +281:2:3979 +282:2:3990 +283:2:3991 +284:0:4863 +285:2:3721 +286:0:4863 +287:2:3997 +288:2:3998 +289:2:4002 +290:2:4003 +291:2:4011 +292:2:4012 +293:2:4016 +294:2:4017 +295:2:4025 +296:2:4030 +297:2:4034 +298:2:4035 +299:2:4043 +300:2:4044 +301:2:4048 +302:2:4049 +303:2:4043 +304:2:4044 +305:2:4048 +306:2:4049 +307:2:4057 +308:2:4062 +309:2:4063 +310:2:4074 +311:2:4075 +312:2:4076 +313:2:4087 +314:2:4092 +315:2:4093 +316:2:4104 +317:2:4105 +318:2:4106 +319:2:4104 +320:2:4105 +321:2:4106 +322:2:4117 +323:0:4863 +324:2:3721 +325:0:4863 +326:2:4126 +327:2:4127 +328:2:4131 +329:2:4132 +330:2:4140 +331:2:4141 +332:2:4145 +333:2:4146 +334:2:4154 +335:2:4159 +336:2:4163 +337:2:4164 +338:2:4172 +339:2:4173 +340:2:4177 +341:2:4178 +342:2:4172 +343:2:4173 +344:2:4177 +345:2:4178 +346:2:4186 +347:2:4191 +348:2:4192 +349:2:4203 +350:2:4204 +351:2:4205 +352:2:4216 +353:2:4221 +354:2:4222 +355:2:4233 +356:2:4234 +357:2:4235 +358:2:4233 +359:2:4234 +360:2:4235 +361:2:4246 +362:2:4253 +363:0:4863 +364:2:3721 +365:0:4863 +366:2:4257 +367:2:4258 +368:2:4259 +369:2:4271 +370:2:4272 +371:2:4276 +372:2:4277 +373:2:4285 +374:2:4290 +375:2:4294 +376:2:4295 +377:2:4303 +378:2:4304 +379:2:4308 +380:2:4309 +381:2:4303 +382:2:4304 +383:2:4308 +384:2:4309 +385:2:4317 +386:2:4322 +387:2:4323 +388:2:4334 +389:2:4335 +390:2:4336 +391:2:4347 +392:2:4352 +393:2:4353 +394:2:4364 +395:2:4365 +396:2:4366 +397:2:4364 +398:2:4365 +399:2:4366 +400:2:4377 +401:2:4387 +402:2:4388 +403:0:4863 +404:2:3721 +405:0:4863 +406:2:4394 +407:0:4863 +408:2:4696 +409:2:4697 +410:2:4701 +411:2:4705 +412:2:4706 +413:2:4710 +414:2:4718 +415:2:4719 +416:2:4723 +417:2:4727 +418:2:4728 +419:2:4723 +420:2:4727 +421:2:4728 +422:2:4732 +423:2:4739 +424:2:4746 +425:2:4747 +426:2:4754 +427:2:4759 +428:2:4766 +429:2:4767 +430:2:4766 +431:2:4767 +432:2:4774 +433:2:4778 +434:0:4863 +435:2:4396 +436:2:4401 +437:0:4863 +438:2:3721 +439:0:4863 +440:2:4397 +441:0:4863 +442:2:4405 +443:0:4863 +444:2:4406 +445:0:4863 +446:2:3286 +447:0:4863 +448:2:3289 +449:2:3293 +450:2:3294 +451:2:3302 +452:2:3303 +453:2:3307 +454:2:3308 +455:2:3316 +456:2:3321 +457:2:3325 +458:2:3326 +459:2:3334 +460:2:3335 +461:2:3336 +462:2:3334 +463:2:3335 +464:2:3339 +465:2:3340 +466:2:3348 +467:2:3353 +468:2:3354 +469:2:3365 +470:2:3366 +471:2:3367 +472:2:3378 +473:2:3383 +474:2:3384 +475:2:3395 +476:2:3396 +477:2:3397 +478:2:3395 +479:2:3396 +480:2:3397 +481:2:3408 +482:2:3412 +483:0:4863 +484:2:3415 +485:0:4863 +486:2:3421 +487:2:3422 +488:2:3426 +489:2:3430 +490:2:3431 +491:2:3435 +492:2:3443 +493:2:3444 +494:2:3448 +495:2:3449 +496:2:3448 +497:2:3452 +498:2:3453 +499:2:3457 +500:2:3461 +501:0:4863 +502:2:3464 +503:0:4863 +504:2:3465 +505:2:3469 +506:2:3470 +507:2:3478 +508:2:3479 +509:2:3483 +510:2:3484 +511:2:3492 +512:2:3497 +513:2:3501 +514:2:3502 +515:2:3510 +516:2:3511 +517:2:3515 +518:2:3516 +519:2:3510 +520:2:3511 +521:2:3515 +522:2:3516 +523:2:3524 +524:2:3529 +525:2:3530 +526:2:3541 +527:2:3542 +528:2:3543 +529:2:3554 +530:2:3559 +531:2:3560 +532:2:3571 +533:2:3572 +534:2:3573 +535:2:3571 +536:2:3572 +537:2:3573 +538:2:3584 +539:2:3588 +540:0:4863 +541:2:3591 +542:0:4863 +543:2:3594 +544:2:3598 +545:2:3599 +546:2:3607 +547:2:3608 +548:2:3612 +549:2:3613 +550:2:3621 +551:2:3626 +552:2:3627 +553:2:3639 +554:2:3640 +555:2:3644 +556:2:3645 +557:2:3639 +558:2:3640 +559:2:3644 +560:2:3645 +561:2:3653 +562:2:3658 +563:2:3659 +564:2:3670 +565:2:3671 +566:2:3672 +567:2:3683 +568:2:3688 +569:2:3689 +570:2:3700 +571:2:3701 +572:2:3702 +573:2:3700 +574:2:3701 +575:2:3702 +576:2:3713 +577:2:3717 +578:0:4863 +579:2:3720 +580:0:4863 +581:2:3721 +582:0:4863 +583:2:3722 +584:0:4863 +585:2:4423 +586:2:4424 +587:2:4428 +588:2:4432 +589:2:4433 +590:2:4437 +591:2:4445 +592:2:4446 +593:2:4450 +594:2:4454 +595:2:4455 +596:2:4450 +597:2:4454 +598:2:4455 +599:2:4459 +600:2:4466 +601:2:4473 +602:2:4474 +603:2:4481 +604:2:4486 +605:2:4493 +606:2:4494 +607:2:4493 +608:2:4494 +609:2:4501 +610:2:4505 +611:0:4863 +612:2:3724 +613:2:4401 +614:0:4863 +615:2:3721 +616:0:4863 +617:2:3725 +618:0:4863 +619:2:3721 +620:0:4863 +621:2:3728 +622:2:3729 +623:2:3733 +624:2:3734 +625:2:3742 +626:2:3743 +627:2:3747 +628:2:3748 +629:2:3756 +630:2:3761 +631:2:3765 +632:2:3766 +633:2:3774 +634:2:3775 +635:2:3779 +636:2:3780 +637:2:3774 +638:2:3775 +639:2:3779 +640:2:3780 +641:2:3788 +642:2:3793 +643:2:3794 +644:2:3805 +645:2:3806 +646:2:3807 +647:2:3818 +648:2:3823 +649:2:3824 +650:2:3835 +651:2:3836 +652:2:3837 +653:2:3835 +654:2:3836 +655:2:3837 +656:2:3848 +657:2:3855 +658:0:4863 +659:2:3721 +660:0:4863 +661:2:3859 +662:2:3860 +663:2:3861 +664:2:3873 +665:2:3874 +666:2:3878 +667:2:3879 +668:2:3887 +669:2:3892 +670:2:3896 +671:2:3897 +672:2:3905 +673:2:3906 +674:2:3910 +675:2:3911 +676:2:3905 +677:2:3906 +678:2:3910 +679:2:3911 +680:2:3919 +681:2:3924 +682:2:3925 +683:2:3936 +684:2:3937 +685:2:3938 +686:2:3949 +687:2:3954 +688:2:3955 +689:2:3966 +690:2:3967 +691:2:3968 +692:2:3966 +693:2:3967 +694:2:3968 +695:2:3979 +696:2:3990 +697:2:3991 +698:0:4863 +699:2:3721 +700:0:4863 +701:2:3997 +702:2:3998 +703:2:4002 +704:2:4003 +705:2:4011 +706:2:4012 +707:2:4016 +708:2:4017 +709:2:4025 +710:2:4030 +711:2:4034 +712:2:4035 +713:2:4043 +714:2:4044 +715:2:4048 +716:2:4049 +717:2:4043 +718:2:4044 +719:2:4048 +720:2:4049 +721:2:4057 +722:2:4062 +723:2:4063 +724:2:4074 +725:2:4075 +726:2:4076 +727:2:4087 +728:2:4092 +729:2:4093 +730:2:4104 +731:2:4105 +732:2:4106 +733:2:4104 +734:2:4105 +735:2:4106 +736:2:4117 +737:0:4863 +738:2:3721 +739:0:4863 +740:2:4126 +741:2:4127 +742:2:4131 +743:2:4132 +744:2:4140 +745:2:4141 +746:2:4145 +747:2:4146 +748:2:4154 +749:2:4159 +750:2:4163 +751:2:4164 +752:2:4172 +753:2:4173 +754:2:4177 +755:2:4178 +756:2:4172 +757:2:4173 +758:2:4177 +759:2:4178 +760:2:4186 +761:2:4191 +762:2:4192 +763:2:4203 +764:2:4204 +765:2:4205 +766:2:4216 +767:2:4221 +768:2:4222 +769:2:4233 +770:2:4234 +771:2:4235 +772:2:4233 +773:2:4234 +774:2:4235 +775:2:4246 +776:2:4253 +777:0:4863 +778:2:3721 +779:0:4863 +780:2:4257 +781:2:4258 +782:2:4259 +783:2:4271 +784:2:4272 +785:2:4276 +786:2:4277 +787:2:4285 +788:2:4290 +789:2:4294 +790:2:4295 +791:2:4303 +792:2:4304 +793:2:4308 +794:2:4309 +795:2:4303 +796:2:4304 +797:2:4308 +798:2:4309 +799:2:4317 +800:2:4322 +801:2:4323 +802:2:4334 +803:2:4335 +804:2:4336 +805:2:4347 +806:2:4352 +807:2:4353 +808:2:4364 +809:2:4365 +810:2:4366 +811:2:4364 +812:2:4365 +813:2:4366 +814:2:4377 +815:2:4387 +816:2:4388 +817:0:4863 +818:2:3721 +819:0:4863 +820:2:4394 +821:0:4863 +822:2:4696 +823:2:4697 +824:2:4701 +825:2:4705 +826:2:4706 +827:2:4710 +828:2:4718 +829:2:4719 +830:2:4723 +831:2:4727 +832:2:4728 +833:2:4723 +834:2:4727 +835:2:4728 +836:2:4732 +837:2:4739 +838:2:4746 +839:2:4747 +840:2:4754 +841:2:4759 +842:2:4766 +843:2:4767 +844:2:4766 +845:2:4767 +846:2:4774 +847:2:4778 +848:0:4863 +849:2:4396 +850:2:4401 +851:0:4863 +852:2:3721 +853:0:4863 +854:2:4397 +855:0:4863 +856:2:4405 +857:0:4863 +858:2:4406 +859:0:4863 +860:2:3286 +861:0:4863 +862:2:3289 +863:2:3293 +864:2:3294 +865:2:3302 +866:2:3303 +867:2:3307 +868:2:3308 +869:2:3316 +870:2:3321 +871:2:3325 +872:2:3326 +873:2:3334 +874:2:3335 +875:2:3339 +876:2:3340 +877:2:3334 +878:2:3335 +879:2:3336 +880:2:3348 +881:2:3353 +882:2:3354 +883:2:3365 +884:2:3366 +885:2:3367 +886:2:3378 +887:2:3383 +888:2:3384 +889:2:3395 +890:2:3396 +891:2:3397 +892:2:3395 +893:2:3396 +894:2:3397 +895:2:3408 +896:2:3412 +897:0:4863 +898:2:3415 +899:0:4863 +900:2:3421 +901:2:3422 +902:2:3426 +903:2:3430 +904:2:3431 +905:2:3435 +906:2:3443 +907:2:3444 +908:2:3448 +909:2:3452 +910:2:3453 +911:2:3448 +912:2:3449 +913:2:3457 +914:2:3461 +915:0:4863 +916:2:3464 +917:0:4863 +918:2:3465 +919:2:3469 +920:2:3470 +921:2:3478 +922:2:3479 +923:2:3483 +924:2:3484 +925:2:3492 +926:2:3497 +927:2:3501 +928:2:3502 +929:2:3510 +930:2:3511 +931:2:3515 +932:2:3516 +933:2:3510 +934:2:3511 +935:2:3515 +936:2:3516 +937:2:3524 +938:2:3529 +939:2:3530 +940:2:3541 +941:2:3542 +942:2:3543 +943:2:3554 +944:2:3559 +945:2:3560 +946:2:3571 +947:2:3572 +948:2:3573 +949:2:3571 +950:2:3572 +951:2:3573 +952:2:3584 +953:2:3588 +954:0:4863 +955:2:3591 +956:0:4863 +957:2:3594 +958:2:3598 +959:2:3599 +960:2:3607 +961:2:3608 +962:2:3612 +963:2:3613 +964:2:3621 +965:2:3626 +966:2:3627 +967:2:3639 +968:2:3640 +969:2:3644 +970:2:3645 +971:2:3639 +972:2:3640 +973:2:3644 +974:2:3645 +975:2:3653 +976:2:3658 +977:2:3659 +978:2:3670 +979:2:3671 +980:2:3672 +981:2:3683 +982:2:3688 +983:2:3689 +984:2:3700 +985:2:3701 +986:2:3702 +987:2:3700 +988:2:3701 +989:2:3702 +990:2:3713 +991:2:3717 +992:0:4863 +993:2:3720 +994:0:4863 +995:2:3721 +996:0:4863 +997:2:3722 +998:0:4863 +999:2:4423 +1000:2:4424 +1001:2:4428 +1002:2:4432 +1003:2:4433 +1004:2:4437 +1005:2:4445 +1006:2:4446 +1007:2:4450 +1008:2:4454 +1009:2:4455 +1010:2:4450 +1011:2:4454 +1012:2:4455 +1013:2:4459 +1014:2:4466 +1015:2:4473 +1016:2:4474 +1017:2:4481 +1018:2:4486 +1019:2:4493 +1020:2:4494 +1021:2:4493 +1022:2:4494 +1023:2:4501 +1024:2:4505 +1025:0:4863 +1026:2:3724 +1027:2:4401 +1028:0:4863 +1029:2:3721 +1030:0:4863 +1031:2:3725 +1032:0:4863 +1033:2:3721 +1034:0:4863 +1035:2:3728 +1036:2:3729 +1037:2:3733 +1038:2:3734 +1039:2:3742 +1040:2:3743 +1041:2:3747 +1042:2:3748 +1043:2:3756 +1044:2:3761 +1045:2:3765 +1046:2:3766 +1047:2:3774 +1048:2:3775 +1049:2:3779 +1050:2:3780 +1051:2:3774 +1052:2:3775 +1053:2:3779 +1054:2:3780 +1055:2:3788 +1056:2:3793 +1057:2:3794 +1058:2:3805 +1059:2:3806 +1060:2:3807 +1061:2:3818 +1062:2:3823 +1063:2:3824 +1064:2:3835 +1065:2:3836 +1066:2:3837 +1067:2:3835 +1068:2:3836 +1069:2:3837 +1070:2:3848 +1071:2:3855 +1072:0:4863 +1073:2:3721 +1074:0:4863 +1075:2:3859 +1076:2:3860 +1077:2:3861 +1078:2:3873 +1079:2:3874 +1080:2:3878 +1081:2:3879 +1082:2:3887 +1083:2:3892 +1084:2:3896 +1085:2:3897 +1086:2:3905 +1087:2:3906 +1088:2:3910 +1089:2:3911 +1090:2:3905 +1091:2:3906 +1092:2:3910 +1093:2:3911 +1094:2:3919 +1095:2:3924 +1096:2:3925 +1097:2:3936 +1098:2:3937 +1099:2:3938 +1100:2:3949 +1101:2:3954 +1102:2:3955 +1103:2:3966 +1104:2:3967 +1105:2:3968 +1106:2:3966 +1107:2:3967 +1108:2:3968 +1109:2:3979 +1110:2:3990 +1111:2:3991 +1112:0:4863 +1113:2:3721 +1114:0:4863 +1115:2:3997 +1116:2:3998 +1117:2:4002 +1118:2:4003 +1119:2:4011 +1120:2:4012 +1121:2:4016 +1122:2:4017 +1123:2:4025 +1124:2:4030 +1125:2:4034 +1126:2:4035 +1127:2:4043 +1128:2:4044 +1129:2:4048 +1130:2:4049 +1131:2:4043 +1132:2:4044 +1133:2:4048 +1134:2:4049 +1135:2:4057 +1136:2:4062 +1137:2:4063 +1138:2:4074 +1139:2:4075 +1140:2:4076 +1141:2:4087 +1142:2:4092 +1143:2:4093 +1144:2:4104 +1145:2:4105 +1146:2:4106 +1147:2:4104 +1148:2:4105 +1149:2:4106 +1150:2:4117 +1151:0:4863 +1152:2:3721 +1153:0:4863 +1154:2:4126 +1155:2:4127 +1156:2:4131 +1157:2:4132 +1158:2:4140 +1159:2:4141 +1160:2:4145 +1161:2:4146 +1162:2:4154 +1163:2:4159 +1164:2:4163 +1165:2:4164 +1166:2:4172 +1167:2:4173 +1168:2:4177 +1169:2:4178 +1170:2:4172 +1171:2:4173 +1172:2:4177 +1173:2:4178 +1174:2:4186 +1175:2:4191 +1176:2:4192 +1177:2:4203 +1178:2:4204 +1179:2:4205 +1180:2:4216 +1181:2:4221 +1182:2:4222 +1183:2:4233 +1184:2:4234 +1185:2:4235 +1186:2:4233 +1187:2:4234 +1188:2:4235 +1189:2:4246 +1190:2:4253 +1191:0:4863 +1192:2:3721 +1193:0:4863 +1194:2:4257 +1195:2:4258 +1196:2:4259 +1197:2:4271 +1198:2:4272 +1199:2:4276 +1200:2:4277 +1201:2:4285 +1202:2:4290 +1203:2:4294 +1204:2:4295 +1205:2:4303 +1206:2:4304 +1207:2:4308 +1208:2:4309 +1209:2:4303 +1210:2:4304 +1211:2:4308 +1212:2:4309 +1213:2:4317 +1214:2:4322 +1215:2:4323 +1216:2:4334 +1217:2:4335 +1218:2:4336 +1219:2:4347 +1220:2:4352 +1221:2:4353 +1222:2:4364 +1223:2:4365 +1224:2:4366 +1225:2:4364 +1226:2:4365 +1227:2:4366 +1228:2:4377 +1229:2:4387 +1230:2:4388 +1231:0:4863 +1232:2:3721 +1233:0:4863 +1234:2:4394 +1235:0:4863 +1236:2:4696 +1237:2:4697 +1238:2:4701 +1239:2:4705 +1240:2:4706 +1241:2:4710 +1242:2:4718 +1243:2:4719 +1244:2:4723 +1245:2:4727 +1246:2:4728 +1247:2:4723 +1248:2:4727 +1249:2:4728 +1250:2:4732 +1251:2:4739 +1252:2:4746 +1253:2:4747 +1254:2:4754 +1255:2:4759 +1256:2:4766 +1257:2:4767 +1258:2:4766 +1259:2:4767 +1260:2:4774 +1261:2:4778 +1262:0:4863 +1263:2:4396 +1264:2:4401 +1265:0:4863 +1266:2:3721 +1267:0:4863 +1268:2:4397 +1269:0:4863 +1270:2:4405 +1271:0:4863 +1272:2:4406 +1273:0:4863 +1274:2:3286 +1275:0:4863 +1276:2:3289 +1277:2:3293 +1278:2:3294 +1279:2:3302 +1280:2:3303 +1281:2:3307 +1282:2:3308 +1283:2:3316 +1284:2:3321 +1285:2:3325 +1286:2:3326 +1287:2:3334 +1288:2:3335 +1289:2:3336 +1290:2:3334 +1291:2:3335 +1292:2:3339 +1293:2:3340 +1294:2:3348 +1295:2:3353 +1296:2:3354 +1297:2:3365 +1298:2:3366 +1299:2:3367 +1300:2:3378 +1301:2:3383 +1302:2:3384 +1303:2:3395 +1304:2:3396 +1305:2:3397 +1306:2:3395 +1307:2:3396 +1308:2:3397 +1309:2:3408 +1310:2:3412 +1311:0:4863 +1312:2:3415 +1313:0:4863 +1314:2:3421 +1315:2:3422 +1316:2:3426 +1317:2:3430 +1318:2:3431 +1319:2:3435 +1320:2:3443 +1321:2:3444 +1322:2:3448 +1323:2:3449 +1324:2:3448 +1325:2:3452 +1326:2:3453 +1327:2:3457 +1328:2:3461 +1329:0:4863 +1330:2:3464 +1331:0:4863 +1332:2:3465 +1333:2:3469 +1334:2:3470 +1335:2:3478 +1336:2:3479 +1337:2:3483 +1338:2:3484 +1339:2:3492 +1340:2:3497 +1341:2:3501 +1342:2:3502 +1343:2:3510 +1344:2:3511 +1345:2:3515 +1346:2:3516 +1347:2:3510 +1348:2:3511 +1349:2:3515 +1350:2:3516 +1351:2:3524 +1352:2:3529 +1353:2:3530 +1354:2:3541 +1355:2:3542 +1356:2:3543 +1357:2:3554 +1358:2:3559 +1359:2:3560 +1360:2:3571 +1361:2:3572 +1362:2:3573 +1363:2:3571 +1364:2:3572 +1365:2:3573 +1366:2:3584 +1367:2:3588 +1368:0:4863 +1369:2:3591 +1370:0:4863 +1371:2:3594 +1372:2:3598 +1373:2:3599 +1374:2:3607 +1375:2:3608 +1376:2:3612 +1377:2:3613 +1378:2:3621 +1379:2:3626 +1380:2:3627 +1381:2:3639 +1382:2:3640 +1383:2:3644 +1384:2:3645 +1385:2:3639 +1386:2:3640 +1387:2:3644 +1388:2:3645 +1389:2:3653 +1390:2:3658 +1391:2:3659 +1392:2:3670 +1393:2:3671 +1394:2:3672 +1395:2:3683 +1396:2:3688 +1397:2:3689 +1398:2:3700 +1399:2:3701 +1400:2:3702 +1401:2:3700 +1402:2:3701 +1403:2:3702 +1404:2:3713 +1405:2:3717 +1406:0:4863 +1407:2:3720 +1408:0:4863 +1409:2:3721 +1410:0:4863 +1411:2:3722 +1412:0:4863 +1413:2:4423 +1414:2:4424 +1415:2:4428 +1416:2:4432 +1417:2:4433 +1418:2:4437 +1419:2:4445 +1420:2:4446 +1421:2:4450 +1422:2:4454 +1423:2:4455 +1424:2:4450 +1425:2:4454 +1426:2:4455 +1427:2:4459 +1428:2:4466 +1429:2:4473 +1430:2:4474 +1431:2:4481 +1432:2:4486 +1433:2:4493 +1434:2:4494 +1435:2:4493 +1436:2:4494 +1437:2:4501 +1438:2:4505 +1439:0:4863 +1440:2:3724 +1441:2:4401 +1442:0:4863 +1443:2:3721 +1444:0:4863 +1445:2:3725 +1446:0:4863 +1447:2:3721 +1448:0:4863 +1449:2:3728 +1450:2:3729 +1451:2:3733 +1452:2:3734 +1453:2:3742 +1454:2:3743 +1455:2:3747 +1456:2:3748 +1457:2:3756 +1458:2:3761 +1459:2:3765 +1460:2:3766 +1461:2:3774 +1462:2:3775 +1463:2:3779 +1464:2:3780 +1465:2:3774 +1466:2:3775 +1467:2:3779 +1468:2:3780 +1469:2:3788 +1470:2:3793 +1471:2:3794 +1472:2:3805 +1473:2:3806 +1474:2:3807 +1475:2:3818 +1476:2:3823 +1477:2:3824 +1478:2:3835 +1479:2:3836 +1480:2:3837 +1481:2:3835 +1482:2:3836 +1483:2:3837 +1484:2:3848 +1485:2:3855 +1486:0:4863 +1487:2:3721 +1488:0:4863 +1489:2:3859 +1490:2:3860 +1491:2:3861 +1492:2:3873 +1493:2:3874 +1494:2:3878 +1495:2:3879 +1496:2:3887 +1497:2:3892 +1498:2:3896 +1499:2:3897 +1500:2:3905 +1501:2:3906 +1502:2:3910 +1503:2:3911 +1504:2:3905 +1505:2:3906 +1506:2:3910 +1507:2:3911 +1508:2:3919 +1509:2:3924 +1510:2:3925 +1511:2:3936 +1512:2:3937 +1513:2:3938 +1514:2:3949 +1515:2:3954 +1516:2:3955 +1517:2:3966 +1518:2:3967 +1519:2:3968 +1520:2:3966 +1521:2:3967 +1522:2:3968 +1523:2:3979 +1524:2:3990 +1525:2:3991 +1526:0:4863 +1527:2:3721 +1528:0:4863 +1529:2:3997 +1530:2:3998 +1531:2:4002 +1532:2:4003 +1533:2:4011 +1534:2:4012 +1535:2:4016 +1536:2:4017 +1537:2:4025 +1538:2:4030 +1539:2:4034 +1540:2:4035 +1541:2:4043 +1542:2:4044 +1543:2:4048 +1544:2:4049 +1545:2:4043 +1546:2:4044 +1547:2:4048 +1548:2:4049 +1549:2:4057 +1550:2:4062 +1551:2:4063 +1552:2:4074 +1553:2:4075 +1554:2:4076 +1555:2:4087 +1556:2:4092 +1557:2:4093 +1558:2:4104 +1559:2:4105 +1560:2:4106 +1561:2:4104 +1562:2:4105 +1563:2:4106 +1564:2:4117 +1565:0:4863 +1566:2:3721 +1567:0:4863 +1568:2:4126 +1569:2:4127 +1570:2:4131 +1571:2:4132 +1572:2:4140 +1573:2:4141 +1574:2:4145 +1575:2:4146 +1576:2:4154 +1577:2:4159 +1578:2:4163 +1579:2:4164 +1580:2:4172 +1581:2:4173 +1582:2:4177 +1583:2:4178 +1584:2:4172 +1585:2:4173 +1586:2:4177 +1587:2:4178 +1588:2:4186 +1589:2:4191 +1590:2:4192 +1591:2:4203 +1592:2:4204 +1593:2:4205 +1594:2:4216 +1595:2:4221 +1596:2:4222 +1597:2:4233 +1598:2:4234 +1599:2:4235 +1600:2:4233 +1601:2:4234 +1602:2:4235 +1603:2:4246 +1604:2:4253 +1605:0:4863 +1606:2:3721 +1607:0:4863 +1608:2:4257 +1609:2:4258 +1610:2:4259 +1611:2:4271 +1612:2:4272 +1613:2:4276 +1614:2:4277 +1615:2:4285 +1616:2:4290 +1617:2:4294 +1618:2:4295 +1619:2:4303 +1620:2:4304 +1621:2:4308 +1622:2:4309 +1623:2:4303 +1624:2:4304 +1625:2:4308 +1626:2:4309 +1627:2:4317 +1628:2:4322 +1629:2:4323 +1630:2:4334 +1631:2:4335 +1632:2:4336 +1633:2:4347 +1634:2:4352 +1635:2:4353 +1636:2:4364 +1637:2:4365 +1638:2:4366 +1639:2:4364 +1640:2:4365 +1641:2:4366 +1642:2:4377 +1643:2:4387 +1644:2:4388 +1645:0:4863 +1646:2:3721 +1647:0:4863 +1648:2:4394 +1649:0:4863 +1650:2:4696 +1651:2:4697 +1652:2:4701 +1653:2:4705 +1654:2:4706 +1655:2:4710 +1656:2:4718 +1657:2:4719 +1658:2:4723 +1659:2:4727 +1660:2:4728 +1661:2:4723 +1662:2:4727 +1663:2:4728 +1664:2:4732 +1665:2:4739 +1666:2:4746 +1667:2:4747 +1668:2:4754 +1669:2:4759 +1670:2:4766 +1671:2:4767 +1672:2:4766 +1673:2:4767 +1674:2:4774 +1675:2:4778 +1676:0:4863 +1677:2:4396 +1678:2:4401 +1679:0:4863 +1680:2:3721 +1681:0:4863 +1682:2:4397 +1683:0:4863 +1684:2:4405 +1685:0:4863 +1686:2:4406 +1687:0:4863 +1688:2:3286 +1689:0:4863 +1690:2:3289 +1691:2:3293 +1692:2:3294 +1693:2:3302 +1694:2:3303 +1695:2:3307 +1696:2:3308 +1697:2:3316 +1698:2:3321 +1699:2:3325 +1700:2:3326 +1701:2:3334 +1702:2:3335 +1703:2:3339 +1704:2:3340 +1705:2:3334 +1706:2:3335 +1707:2:3336 +1708:2:3348 +1709:2:3353 +1710:2:3354 +1711:2:3365 +1712:2:3366 +1713:2:3367 +1714:2:3378 +1715:2:3383 +1716:2:3384 +1717:2:3395 +1718:2:3396 +1719:2:3397 +1720:2:3395 +1721:2:3396 +1722:2:3397 +1723:2:3408 +1724:2:3412 +1725:0:4863 +1726:2:3415 +1727:0:4863 +1728:1:2 +1729:0:4863 +1730:1:8 +1731:0:4863 +1732:1:9 +1733:0:4863 +1734:1:10 +1735:0:4863 +1736:1:11 +1737:0:4863 +1738:1:12 +1739:1:13 +1740:1:17 +1741:1:18 +1742:1:26 +1743:1:27 +1744:1:31 +1745:1:32 +1746:1:40 +1747:1:45 +1748:1:49 +1749:1:50 +1750:1:58 +1751:1:59 +1752:1:63 +1753:1:64 +1754:1:58 +1755:1:59 +1756:1:63 +1757:1:64 +1758:1:72 +1759:1:77 +1760:1:78 +1761:1:89 +1762:1:90 +1763:1:91 +1764:1:102 +1765:1:107 +1766:1:108 +1767:1:119 +1768:1:120 +1769:1:121 +1770:1:119 +1771:1:120 +1772:1:121 +1773:1:132 +1774:0:4863 +1775:1:11 +1776:0:4863 +1777:1:141 +1778:1:142 +1779:0:4863 +1780:1:11 +1781:0:4863 +1782:1:148 +1783:1:149 +1784:1:153 +1785:1:154 +1786:1:162 +1787:1:163 +1788:1:167 +1789:1:168 +1790:1:176 +1791:1:181 +1792:1:185 +1793:1:186 +1794:1:194 +1795:1:195 +1796:1:199 +1797:1:200 +1798:1:194 +1799:1:195 +1800:1:199 +1801:1:200 +1802:1:208 +1803:1:213 +1804:1:214 +1805:1:225 +1806:1:226 +1807:1:227 +1808:1:238 +1809:1:243 +1810:1:244 +1811:1:255 +1812:1:256 +1813:1:257 +1814:1:255 +1815:1:256 +1816:1:257 +1817:1:268 +1818:0:4863 +1819:1:11 +1820:0:4863 +1821:1:277 +1822:1:278 +1823:1:282 +1824:1:283 +1825:1:291 +1826:1:292 +1827:1:296 +1828:1:297 +1829:1:305 +1830:1:310 +1831:1:314 +1832:1:315 +1833:1:323 +1834:1:324 +1835:1:328 +1836:1:329 +1837:1:323 +1838:1:324 +1839:1:328 +1840:1:329 +1841:1:337 +1842:1:342 +1843:1:343 +1844:1:354 +1845:1:355 +1846:1:356 +1847:1:367 +1848:1:372 +1849:1:373 +1850:1:384 +1851:1:385 +1852:1:386 +1853:1:384 +1854:1:385 +1855:1:386 +1856:1:397 +1857:1:404 +1858:0:4863 +1859:1:11 +1860:0:4863 +1861:1:540 +1862:1:544 +1863:1:545 +1864:1:549 +1865:1:550 +1866:1:558 +1867:1:566 +1868:1:567 +1869:1:571 +1870:1:575 +1871:1:576 +1872:1:571 +1873:1:575 +1874:1:576 +1875:1:580 +1876:1:587 +1877:1:594 +1878:1:595 +1879:1:602 +1880:1:607 +1881:1:614 +1882:1:615 +1883:1:614 +1884:1:615 +1885:1:622 +1886:0:4863 +1887:1:11 +1888:0:4863 +1889:2:3421 +1890:2:3422 +1891:2:3426 +1892:2:3430 +1893:2:3431 +1894:2:3435 +1895:2:3443 +1896:2:3444 +1897:2:3448 +1898:2:3452 +1899:2:3453 +1900:2:3448 +1901:2:3449 +1902:2:3457 +1903:2:3461 +1904:0:4863 +1905:2:3464 +1906:0:4863 +1907:2:3465 +1908:2:3469 +1909:2:3470 +1910:2:3478 +1911:2:3479 +1912:2:3483 +1913:2:3484 +1914:2:3492 +1915:2:3497 +1916:2:3501 +1917:2:3502 +1918:2:3510 +1919:2:3511 +1920:2:3515 +1921:2:3516 +1922:2:3510 +1923:2:3511 +1924:2:3515 +1925:2:3516 +1926:2:3524 +1927:2:3529 +1928:2:3530 +1929:2:3541 +1930:2:3542 +1931:2:3543 +1932:2:3554 +1933:2:3559 +1934:2:3560 +1935:2:3571 +1936:2:3572 +1937:2:3573 +1938:2:3571 +1939:2:3572 +1940:2:3573 +1941:2:3584 +1942:2:3588 +1943:0:4863 +1944:2:3591 +1945:0:4863 +1946:2:3594 +1947:2:3598 +1948:2:3599 +1949:2:3607 +1950:2:3608 +1951:2:3612 +1952:2:3613 +1953:2:3621 +1954:2:3626 +1955:2:3627 +1956:2:3639 +1957:2:3640 +1958:2:3644 +1959:2:3645 +1960:2:3639 +1961:2:3640 +1962:2:3644 +1963:2:3645 +1964:2:3653 +1965:2:3658 +1966:2:3659 +1967:2:3670 +1968:2:3671 +1969:2:3672 +1970:2:3683 +1971:2:3688 +1972:2:3689 +1973:2:3700 +1974:2:3701 +1975:2:3702 +1976:2:3700 +1977:2:3701 +1978:2:3702 +1979:2:3713 +1980:2:3717 +1981:0:4863 +1982:2:3720 +1983:0:4863 +1984:2:3721 +1985:0:4863 +1986:2:3722 +1987:0:4863 +1988:2:4423 +1989:2:4424 +1990:2:4428 +1991:2:4432 +1992:2:4433 +1993:2:4437 +1994:2:4445 +1995:2:4446 +1996:2:4450 +1997:2:4454 +1998:2:4455 +1999:2:4450 +2000:2:4454 +2001:2:4455 +2002:2:4459 +2003:2:4466 +2004:2:4473 +2005:2:4474 +2006:2:4481 +2007:2:4486 +2008:2:4493 +2009:2:4494 +2010:2:4493 +2011:2:4494 +2012:2:4501 +2013:2:4505 +2014:0:4863 +2015:2:3724 +2016:2:4401 +2017:0:4863 +2018:2:3721 +2019:0:4863 +2020:2:3725 +2021:0:4863 +2022:2:3721 +2023:0:4863 +2024:2:3728 +2025:2:3729 +2026:2:3733 +2027:2:3734 +2028:2:3742 +2029:2:3743 +2030:2:3747 +2031:2:3748 +2032:2:3756 +2033:2:3761 +2034:2:3765 +2035:2:3766 +2036:2:3774 +2037:2:3775 +2038:2:3779 +2039:2:3780 +2040:2:3774 +2041:2:3775 +2042:2:3779 +2043:2:3780 +2044:2:3788 +2045:2:3793 +2046:2:3794 +2047:2:3805 +2048:2:3806 +2049:2:3807 +2050:2:3818 +2051:2:3823 +2052:2:3824 +2053:2:3835 +2054:2:3836 +2055:2:3837 +2056:2:3835 +2057:2:3836 +2058:2:3837 +2059:2:3848 +2060:2:3855 +2061:0:4863 +2062:2:3721 +2063:0:4863 +2064:2:3859 +2065:2:3860 +2066:2:3861 +2067:2:3873 +2068:2:3874 +2069:2:3878 +2070:2:3879 +2071:2:3887 +2072:2:3892 +2073:2:3896 +2074:2:3897 +2075:2:3905 +2076:2:3906 +2077:2:3910 +2078:2:3911 +2079:2:3905 +2080:2:3906 +2081:2:3910 +2082:2:3911 +2083:2:3919 +2084:2:3924 +2085:2:3925 +2086:2:3936 +2087:2:3937 +2088:2:3938 +2089:2:3949 +2090:2:3954 +2091:2:3955 +2092:2:3966 +2093:2:3967 +2094:2:3968 +2095:2:3966 +2096:2:3967 +2097:2:3968 +2098:2:3979 +2099:2:3988 +2100:0:4863 +2101:2:3721 +2102:0:4863 +2103:2:3994 +2104:0:4863 +2105:2:4514 +2106:2:4515 +2107:2:4519 +2108:2:4523 +2109:2:4524 +2110:2:4528 +2111:2:4536 +2112:2:4537 +2113:2:4541 +2114:2:4545 +2115:2:4546 +2116:2:4541 +2117:2:4545 +2118:2:4546 +2119:2:4550 +2120:2:4557 +2121:2:4564 +2122:2:4565 +2123:2:4572 +2124:2:4577 +2125:2:4584 +2126:2:4585 +2127:2:4584 +2128:2:4585 +2129:2:4592 +2130:2:4596 +2131:0:4863 +2132:2:3996 +2133:2:4401 +2134:0:4863 +2135:2:3721 +2136:0:4863 +2137:1:632 +2138:1:633 +2139:1:637 +2140:1:638 +2141:1:646 +2142:1:647 +2143:1:651 +2144:1:652 +2145:1:660 +2146:1:665 +2147:1:669 +2148:1:670 +2149:1:678 +2150:1:679 +2151:1:683 +2152:1:684 +2153:1:678 +2154:1:679 +2155:1:683 +2156:1:684 +2157:1:692 +2158:1:697 +2159:1:698 +2160:1:709 +2161:1:710 +2162:1:711 +2163:1:722 +2164:1:727 +2165:1:728 +2166:1:739 +2167:1:740 +2168:1:741 +2169:1:739 +2170:1:747 +2171:1:748 +2172:1:752 +2173:0:4863 +2174:1:11 +2175:0:4863 +2176:2:3859 +2177:2:3860 +2178:2:3864 +2179:2:3865 +2180:2:3873 +2181:2:3874 +2182:2:3878 +2183:2:3879 +2184:2:3887 +2185:2:3892 +2186:2:3896 +2187:2:3897 +2188:2:3905 +2189:2:3906 +2190:2:3910 +2191:2:3911 +2192:2:3905 +2193:2:3906 +2194:2:3910 +2195:2:3911 +2196:2:3919 +2197:2:3924 +2198:2:3925 +2199:2:3936 +2200:2:3937 +2201:2:3938 +2202:2:3949 +2203:2:3954 +2204:2:3955 +2205:2:3966 +2206:2:3967 +2207:2:3968 +2208:2:3966 +2209:2:3967 +2210:2:3968 +2211:2:3979 +2212:2:3988 +2213:0:4863 +2214:2:3721 +2215:0:4863 +2216:2:3994 +2217:0:4863 +2218:2:4514 +2219:2:4515 +2220:2:4519 +2221:2:4523 +2222:2:4524 +2223:2:4528 +2224:2:4536 +2225:2:4537 +2226:2:4541 +2227:2:4545 +2228:2:4546 +2229:2:4541 +2230:2:4545 +2231:2:4546 +2232:2:4550 +2233:2:4557 +2234:2:4564 +2235:2:4565 +2236:2:4572 +2237:2:4577 +2238:2:4584 +2239:2:4585 +2240:2:4584 +2241:2:4585 +2242:2:4592 +2243:2:4596 +2244:0:4863 +2245:2:3996 +2246:2:4401 +2247:0:4863 +2248:1:761 +2249:1:764 +2250:1:765 +2251:0:4863 +2252:2:3721 +2253:0:4863 +2254:1:11 +2255:0:4863 +2256:2:3859 +2257:2:3860 +2258:2:3864 +2259:2:3865 +2260:2:3873 +2261:2:3874 +2262:2:3878 +2263:2:3879 +2264:2:3887 +2265:2:3892 +2266:2:3896 +2267:2:3897 +2268:2:3905 +2269:2:3906 +2270:2:3910 +2271:2:3911 +2272:2:3905 +2273:2:3906 +2274:2:3910 +2275:2:3911 +2276:2:3919 +2277:2:3924 +2278:2:3925 +2279:2:3936 +2280:2:3937 +2281:2:3938 +2282:2:3949 +2283:2:3954 +2284:2:3955 +2285:2:3966 +2286:2:3967 +2287:2:3968 +2288:2:3966 +2289:2:3967 +2290:2:3968 +2291:2:3979 +2292:2:3988 +2293:0:4863 +2294:2:3721 +2295:0:4863 +2296:2:3994 +2297:0:4863 +2298:2:4514 +2299:2:4515 +2300:2:4519 +2301:2:4523 +2302:2:4524 +2303:2:4528 +2304:2:4536 +2305:2:4537 +2306:2:4541 +2307:2:4545 +2308:2:4546 +2309:2:4541 +2310:2:4545 +2311:2:4546 +2312:2:4550 +2313:2:4557 +2314:2:4564 +2315:2:4565 +2316:2:4572 +2317:2:4577 +2318:2:4584 +2319:2:4585 +2320:2:4584 +2321:2:4585 +2322:2:4592 +2323:2:4596 +2324:0:4863 +2325:2:3996 +2326:2:4401 +2327:0:4863 +2328:1:1028 +2329:1:1029 +2330:1:1033 +2331:1:1034 +2332:1:1042 +2333:1:1043 +2334:1:1047 +2335:1:1048 +2336:1:1056 +2337:1:1061 +2338:1:1065 +2339:1:1066 +2340:1:1074 +2341:1:1075 +2342:1:1079 +2343:1:1080 +2344:1:1074 +2345:1:1075 +2346:1:1079 +2347:1:1080 +2348:1:1088 +2349:1:1093 +2350:1:1094 +2351:1:1105 +2352:1:1106 +2353:1:1107 +2354:1:1118 +2355:1:1123 +2356:1:1124 +2357:1:1135 +2358:1:1136 +2359:1:1137 +2360:1:1135 +2361:1:1143 +2362:1:1144 +2363:1:1148 +2364:1:1155 +2365:1:1159 +2366:0:4863 +2367:2:3721 +2368:0:4863 +2369:1:11 +2370:0:4863 +2371:2:3859 +2372:2:3860 +2373:2:3864 +2374:2:3865 +2375:2:3873 +2376:2:3874 +2377:2:3878 +2378:2:3879 +2379:2:3887 +2380:2:3892 +2381:2:3896 +2382:2:3897 +2383:2:3905 +2384:2:3906 +2385:2:3910 +2386:2:3911 +2387:2:3905 +2388:2:3906 +2389:2:3910 +2390:2:3911 +2391:2:3919 +2392:2:3924 +2393:2:3925 +2394:2:3936 +2395:2:3937 +2396:2:3938 +2397:2:3949 +2398:2:3954 +2399:2:3955 +2400:2:3966 +2401:2:3967 +2402:2:3968 +2403:2:3966 +2404:2:3967 +2405:2:3968 +2406:2:3979 +2407:2:3988 +2408:0:4863 +2409:2:3721 +2410:0:4863 +2411:2:3994 +2412:0:4863 +2413:2:4514 +2414:2:4515 +2415:2:4519 +2416:2:4523 +2417:2:4524 +2418:2:4528 +2419:2:4536 +2420:2:4537 +2421:2:4541 +2422:2:4545 +2423:2:4546 +2424:2:4541 +2425:2:4545 +2426:2:4546 +2427:2:4550 +2428:2:4557 +2429:2:4564 +2430:2:4565 +2431:2:4572 +2432:2:4577 +2433:2:4584 +2434:2:4585 +2435:2:4584 +2436:2:4585 +2437:2:4592 +2438:2:4596 +2439:0:4863 +2440:2:3996 +2441:2:4401 +2442:0:4863 +2443:1:1160 +2444:1:1161 +2445:1:1165 +2446:1:1166 +2447:1:1174 +2448:1:1175 +2449:1:1176 +2450:1:1188 +2451:1:1193 +2452:1:1197 +2453:1:1198 +2454:1:1206 +2455:1:1207 +2456:1:1211 +2457:1:1212 +2458:1:1206 +2459:1:1207 +2460:1:1211 +2461:1:1212 +2462:1:1220 +2463:1:1225 +2464:1:1226 +2465:1:1237 +2466:1:1238 +2467:1:1239 +2468:1:1250 +2469:1:1255 +2470:1:1256 +2471:1:1267 +2472:1:1268 +2473:1:1269 +2474:1:1267 +2475:1:1275 +2476:1:1276 +2477:1:1280 +2478:0:4863 +2479:2:3721 +2480:0:4863 +2481:1:11 +2482:0:4863 +2483:2:3859 +2484:2:3860 +2485:2:3864 +2486:2:3865 +2487:2:3873 +2488:2:3874 +2489:2:3878 +2490:2:3879 +2491:2:3887 +2492:2:3892 +2493:2:3896 +2494:2:3897 +2495:2:3905 +2496:2:3906 +2497:2:3910 +2498:2:3911 +2499:2:3905 +2500:2:3906 +2501:2:3910 +2502:2:3911 +2503:2:3919 +2504:2:3924 +2505:2:3925 +2506:2:3936 +2507:2:3937 +2508:2:3938 +2509:2:3949 +2510:2:3954 +2511:2:3955 +2512:2:3966 +2513:2:3967 +2514:2:3968 +2515:2:3966 +2516:2:3967 +2517:2:3968 +2518:2:3979 +2519:2:3988 +2520:0:4863 +2521:2:3721 +2522:0:4863 +2523:2:3994 +2524:0:4863 +2525:2:4514 +2526:2:4515 +2527:2:4519 +2528:2:4523 +2529:2:4524 +2530:2:4528 +2531:2:4536 +2532:2:4537 +2533:2:4541 +2534:2:4545 +2535:2:4546 +2536:2:4541 +2537:2:4545 +2538:2:4546 +2539:2:4550 +2540:2:4557 +2541:2:4564 +2542:2:4565 +2543:2:4572 +2544:2:4577 +2545:2:4584 +2546:2:4585 +2547:2:4584 +2548:2:4585 +2549:2:4592 +2550:2:4596 +2551:0:4863 +2552:2:3996 +2553:2:4401 +2554:0:4863 +2555:2:3721 +2556:0:4863 +2557:1:1289 +2558:1:1290 +2559:1:1294 +2560:1:1295 +2561:1:1303 +2562:1:1304 +2563:1:1308 +2564:1:1309 +2565:1:1317 +2566:1:1322 +2567:1:1326 +2568:1:1327 +2569:1:1335 +2570:1:1336 +2571:1:1340 +2572:1:1341 +2573:1:1335 +2574:1:1336 +2575:1:1340 +2576:1:1341 +2577:1:1349 +2578:1:1354 +2579:1:1355 +2580:1:1366 +2581:1:1367 +2582:1:1368 +2583:1:1379 +2584:1:1384 +2585:1:1385 +2586:1:1396 +2587:1:1397 +2588:1:1398 +2589:1:1396 +2590:1:1404 +2591:1:1405 +2592:1:1409 +2593:0:4861 +2594:1:11 +2595:0:4867 +2596:0:4863 diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_nested.define b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_nested.define new file mode 100644 index 0000000..0fb59bd --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_nested.define @@ -0,0 +1 @@ +#define READER_NEST_LEVEL 2 diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_mb.define b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_mb.define new file mode 100644 index 0000000..d99d793 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_mb.define @@ -0,0 +1 @@ +#define NO_MB diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_mb.log b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_mb.log new file mode 100644 index 0000000..282f866 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_mb.log @@ -0,0 +1,880 @@ +make[1]: Entering directory `/home/compudj/doc/userspace-rcu/formal-model/urcu-controldataflow' +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define >> pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_free.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_free_no_mb.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1245) +Depth= 9118 States= 1e+06 Transitions= 1.65e+08 Memory= 550.432 t= 207 R= 5e+03 +Depth= 9118 States= 2e+06 Transitions= 3.77e+08 Memory= 634.318 t= 477 R= 4e+03 +Depth= 9118 States= 3e+06 Transitions= 5.23e+08 Memory= 718.303 t= 664 R= 5e+03 +pan: resizing hashtable to -w22.. done +pan: claim violated! (at depth 1384) +pan: wrote .input.spin.trail + +(Spin Version 5.1.7 -- 23 December 2008) +Warning: Search not completed + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness disabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 9118, errors: 1 + 3611143 states, stored +6.1053642e+08 states, matched +6.1414756e+08 transitions (= stored+matched) +3.4001615e+09 atomic steps +hash conflicts: 3.9831098e+08 (resolved) + +Stats on memory usage (in Megabytes): + 399.487 equivalent memory usage for states (stored*(State-vector + overhead)) + 311.150 actual memory usage for states (compression: 77.89%) + state-vector as stored = 62 byte + 28 byte overhead + 32.000 memory used for hash table (-w22) + 457.764 memory used for DFS stack (-m10000000) + 800.693 total actual memory usage + +unreached in proctype urcu_reader + line 250, "pan.___", state 36, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 58, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 67, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 83, "(1)" + line 231, "pan.___", state 91, "(1)" + line 235, "pan.___", state 103, "(1)" + line 239, "pan.___", state 111, "(1)" + line 387, "pan.___", state 136, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 168, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 182, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 201, "(1)" + line 413, "pan.___", state 231, "(1)" + line 417, "pan.___", state 244, "(1)" + line 672, "pan.___", state 265, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 387, "pan.___", state 272, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 304, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 318, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 337, "(1)" + line 413, "pan.___", state 367, "(1)" + line 417, "pan.___", state 380, "(1)" + line 387, "pan.___", state 401, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 433, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 447, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 466, "(1)" + line 413, "pan.___", state 496, "(1)" + line 417, "pan.___", state 509, "(1)" + line 387, "pan.___", state 532, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 534, "(1)" + line 387, "pan.___", state 535, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 535, "else" + line 387, "pan.___", state 538, "(1)" + line 391, "pan.___", state 546, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 548, "(1)" + line 391, "pan.___", state 549, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 549, "else" + line 391, "pan.___", state 552, "(1)" + line 391, "pan.___", state 553, "(1)" + line 391, "pan.___", state 553, "(1)" + line 389, "pan.___", state 558, "((i<1))" + line 389, "pan.___", state 558, "((i>=1))" + line 396, "pan.___", state 564, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 566, "(1)" + line 396, "pan.___", state 567, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 567, "else" + line 396, "pan.___", state 570, "(1)" + line 396, "pan.___", state 571, "(1)" + line 396, "pan.___", state 571, "(1)" + line 400, "pan.___", state 578, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 580, "(1)" + line 400, "pan.___", state 581, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 581, "else" + line 400, "pan.___", state 584, "(1)" + line 400, "pan.___", state 585, "(1)" + line 400, "pan.___", state 585, "(1)" + line 398, "pan.___", state 590, "((i<2))" + line 398, "pan.___", state 590, "((i>=2))" + line 404, "pan.___", state 597, "(1)" + line 404, "pan.___", state 598, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 598, "else" + line 404, "pan.___", state 601, "(1)" + line 404, "pan.___", state 602, "(1)" + line 404, "pan.___", state 602, "(1)" + line 408, "pan.___", state 610, "(1)" + line 408, "pan.___", state 611, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 611, "else" + line 408, "pan.___", state 614, "(1)" + line 408, "pan.___", state 615, "(1)" + line 408, "pan.___", state 615, "(1)" + line 406, "pan.___", state 620, "((i<1))" + line 406, "pan.___", state 620, "((i>=1))" + line 413, "pan.___", state 627, "(1)" + line 413, "pan.___", state 628, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 628, "else" + line 413, "pan.___", state 631, "(1)" + line 413, "pan.___", state 632, "(1)" + line 413, "pan.___", state 632, "(1)" + line 417, "pan.___", state 640, "(1)" + line 417, "pan.___", state 641, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 641, "else" + line 417, "pan.___", state 644, "(1)" + line 417, "pan.___", state 645, "(1)" + line 417, "pan.___", state 645, "(1)" + line 415, "pan.___", state 650, "((i<2))" + line 415, "pan.___", state 650, "((i>=2))" + line 422, "pan.___", state 654, "(1)" + line 422, "pan.___", state 654, "(1)" + line 672, "pan.___", state 657, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 672, "pan.___", state 658, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 672, "pan.___", state 659, "(1)" + line 387, "pan.___", state 666, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 698, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 712, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 731, "(1)" + line 413, "pan.___", state 761, "(1)" + line 417, "pan.___", state 774, "(1)" + line 387, "pan.___", state 802, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 804, "(1)" + line 387, "pan.___", state 805, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 805, "else" + line 387, "pan.___", state 808, "(1)" + line 391, "pan.___", state 816, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 818, "(1)" + line 391, "pan.___", state 819, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 819, "else" + line 391, "pan.___", state 822, "(1)" + line 391, "pan.___", state 823, "(1)" + line 391, "pan.___", state 823, "(1)" + line 389, "pan.___", state 828, "((i<1))" + line 389, "pan.___", state 828, "((i>=1))" + line 396, "pan.___", state 834, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 836, "(1)" + line 396, "pan.___", state 837, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 837, "else" + line 396, "pan.___", state 840, "(1)" + line 396, "pan.___", state 841, "(1)" + line 396, "pan.___", state 841, "(1)" + line 400, "pan.___", state 848, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 850, "(1)" + line 400, "pan.___", state 851, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 851, "else" + line 400, "pan.___", state 854, "(1)" + line 400, "pan.___", state 855, "(1)" + line 400, "pan.___", state 855, "(1)" + line 398, "pan.___", state 860, "((i<2))" + line 398, "pan.___", state 860, "((i>=2))" + line 404, "pan.___", state 867, "(1)" + line 404, "pan.___", state 868, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 868, "else" + line 404, "pan.___", state 871, "(1)" + line 404, "pan.___", state 872, "(1)" + line 404, "pan.___", state 872, "(1)" + line 408, "pan.___", state 880, "(1)" + line 408, "pan.___", state 881, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 881, "else" + line 408, "pan.___", state 884, "(1)" + line 408, "pan.___", state 885, "(1)" + line 408, "pan.___", state 885, "(1)" + line 406, "pan.___", state 890, "((i<1))" + line 406, "pan.___", state 890, "((i>=1))" + line 413, "pan.___", state 897, "(1)" + line 413, "pan.___", state 898, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 898, "else" + line 413, "pan.___", state 901, "(1)" + line 413, "pan.___", state 902, "(1)" + line 413, "pan.___", state 902, "(1)" + line 417, "pan.___", state 910, "(1)" + line 417, "pan.___", state 911, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 911, "else" + line 417, "pan.___", state 914, "(1)" + line 417, "pan.___", state 915, "(1)" + line 417, "pan.___", state 915, "(1)" + line 422, "pan.___", state 924, "(1)" + line 422, "pan.___", state 924, "(1)" + line 387, "pan.___", state 931, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 933, "(1)" + line 387, "pan.___", state 934, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 934, "else" + line 387, "pan.___", state 937, "(1)" + line 391, "pan.___", state 945, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 947, "(1)" + line 391, "pan.___", state 948, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 948, "else" + line 391, "pan.___", state 951, "(1)" + line 391, "pan.___", state 952, "(1)" + line 391, "pan.___", state 952, "(1)" + line 389, "pan.___", state 957, "((i<1))" + line 389, "pan.___", state 957, "((i>=1))" + line 396, "pan.___", state 963, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 965, "(1)" + line 396, "pan.___", state 966, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 966, "else" + line 396, "pan.___", state 969, "(1)" + line 396, "pan.___", state 970, "(1)" + line 396, "pan.___", state 970, "(1)" + line 400, "pan.___", state 977, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 979, "(1)" + line 400, "pan.___", state 980, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 980, "else" + line 400, "pan.___", state 983, "(1)" + line 400, "pan.___", state 984, "(1)" + line 400, "pan.___", state 984, "(1)" + line 398, "pan.___", state 989, "((i<2))" + line 398, "pan.___", state 989, "((i>=2))" + line 404, "pan.___", state 996, "(1)" + line 404, "pan.___", state 997, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 997, "else" + line 404, "pan.___", state 1000, "(1)" + line 404, "pan.___", state 1001, "(1)" + line 404, "pan.___", state 1001, "(1)" + line 408, "pan.___", state 1009, "(1)" + line 408, "pan.___", state 1010, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 1010, "else" + line 408, "pan.___", state 1013, "(1)" + line 408, "pan.___", state 1014, "(1)" + line 408, "pan.___", state 1014, "(1)" + line 406, "pan.___", state 1019, "((i<1))" + line 406, "pan.___", state 1019, "((i>=1))" + line 413, "pan.___", state 1026, "(1)" + line 413, "pan.___", state 1027, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 1027, "else" + line 413, "pan.___", state 1030, "(1)" + line 413, "pan.___", state 1031, "(1)" + line 413, "pan.___", state 1031, "(1)" + line 417, "pan.___", state 1039, "(1)" + line 417, "pan.___", state 1040, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 1040, "else" + line 417, "pan.___", state 1043, "(1)" + line 417, "pan.___", state 1044, "(1)" + line 417, "pan.___", state 1044, "(1)" + line 415, "pan.___", state 1049, "((i<2))" + line 415, "pan.___", state 1049, "((i>=2))" + line 422, "pan.___", state 1053, "(1)" + line 422, "pan.___", state 1053, "(1)" + line 680, "pan.___", state 1057, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 387, "pan.___", state 1062, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1094, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1108, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1127, "(1)" + line 413, "pan.___", state 1157, "(1)" + line 417, "pan.___", state 1170, "(1)" + line 387, "pan.___", state 1194, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1226, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1240, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1259, "(1)" + line 413, "pan.___", state 1289, "(1)" + line 417, "pan.___", state 1302, "(1)" + line 387, "pan.___", state 1327, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1359, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1373, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1392, "(1)" + line 413, "pan.___", state 1422, "(1)" + line 417, "pan.___", state 1435, "(1)" + line 387, "pan.___", state 1456, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1488, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1502, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1521, "(1)" + line 413, "pan.___", state 1551, "(1)" + line 417, "pan.___", state 1564, "(1)" + line 387, "pan.___", state 1590, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1622, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1636, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1655, "(1)" + line 413, "pan.___", state 1685, "(1)" + line 417, "pan.___", state 1698, "(1)" + line 387, "pan.___", state 1719, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1751, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1765, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1784, "(1)" + line 413, "pan.___", state 1814, "(1)" + line 417, "pan.___", state 1827, "(1)" + line 387, "pan.___", state 1851, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1883, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1897, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1916, "(1)" + line 413, "pan.___", state 1946, "(1)" + line 417, "pan.___", state 1959, "(1)" + line 719, "pan.___", state 1980, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 387, "pan.___", state 1987, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2019, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2033, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2052, "(1)" + line 413, "pan.___", state 2082, "(1)" + line 417, "pan.___", state 2095, "(1)" + line 387, "pan.___", state 2116, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2148, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2162, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2181, "(1)" + line 413, "pan.___", state 2211, "(1)" + line 417, "pan.___", state 2224, "(1)" + line 387, "pan.___", state 2247, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 2249, "(1)" + line 387, "pan.___", state 2250, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 2250, "else" + line 387, "pan.___", state 2253, "(1)" + line 391, "pan.___", state 2261, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 2263, "(1)" + line 391, "pan.___", state 2264, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 2264, "else" + line 391, "pan.___", state 2267, "(1)" + line 391, "pan.___", state 2268, "(1)" + line 391, "pan.___", state 2268, "(1)" + line 389, "pan.___", state 2273, "((i<1))" + line 389, "pan.___", state 2273, "((i>=1))" + line 396, "pan.___", state 2279, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2281, "(1)" + line 396, "pan.___", state 2282, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 2282, "else" + line 396, "pan.___", state 2285, "(1)" + line 396, "pan.___", state 2286, "(1)" + line 396, "pan.___", state 2286, "(1)" + line 400, "pan.___", state 2293, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2295, "(1)" + line 400, "pan.___", state 2296, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 2296, "else" + line 400, "pan.___", state 2299, "(1)" + line 400, "pan.___", state 2300, "(1)" + line 400, "pan.___", state 2300, "(1)" + line 398, "pan.___", state 2305, "((i<2))" + line 398, "pan.___", state 2305, "((i>=2))" + line 404, "pan.___", state 2312, "(1)" + line 404, "pan.___", state 2313, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 2313, "else" + line 404, "pan.___", state 2316, "(1)" + line 404, "pan.___", state 2317, "(1)" + line 404, "pan.___", state 2317, "(1)" + line 408, "pan.___", state 2325, "(1)" + line 408, "pan.___", state 2326, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 2326, "else" + line 408, "pan.___", state 2329, "(1)" + line 408, "pan.___", state 2330, "(1)" + line 408, "pan.___", state 2330, "(1)" + line 406, "pan.___", state 2335, "((i<1))" + line 406, "pan.___", state 2335, "((i>=1))" + line 413, "pan.___", state 2342, "(1)" + line 413, "pan.___", state 2343, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 2343, "else" + line 413, "pan.___", state 2346, "(1)" + line 413, "pan.___", state 2347, "(1)" + line 413, "pan.___", state 2347, "(1)" + line 417, "pan.___", state 2355, "(1)" + line 417, "pan.___", state 2356, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 2356, "else" + line 417, "pan.___", state 2359, "(1)" + line 417, "pan.___", state 2360, "(1)" + line 417, "pan.___", state 2360, "(1)" + line 415, "pan.___", state 2365, "((i<2))" + line 415, "pan.___", state 2365, "((i>=2))" + line 422, "pan.___", state 2369, "(1)" + line 422, "pan.___", state 2369, "(1)" + line 719, "pan.___", state 2372, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 719, "pan.___", state 2373, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 719, "pan.___", state 2374, "(1)" + line 387, "pan.___", state 2381, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2413, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2427, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2446, "(1)" + line 413, "pan.___", state 2476, "(1)" + line 417, "pan.___", state 2489, "(1)" + line 387, "pan.___", state 2516, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2548, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2562, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2581, "(1)" + line 413, "pan.___", state 2611, "(1)" + line 417, "pan.___", state 2624, "(1)" + line 387, "pan.___", state 2645, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2677, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2691, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2710, "(1)" + line 413, "pan.___", state 2740, "(1)" + line 417, "pan.___", state 2753, "(1)" + line 227, "pan.___", state 2786, "(1)" + line 235, "pan.___", state 2806, "(1)" + line 239, "pan.___", state 2814, "(1)" + line 227, "pan.___", state 2829, "(1)" + line 235, "pan.___", state 2849, "(1)" + line 239, "pan.___", state 2857, "(1)" + line 870, "pan.___", state 2874, "-end-" + (278 of 2874 states) +unreached in proctype urcu_writer + line 387, "pan.___", state 20, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 26, "(1)" + line 391, "pan.___", state 34, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 40, "(1)" + line 391, "pan.___", state 41, "(1)" + line 391, "pan.___", state 41, "(1)" + line 389, "pan.___", state 46, "((i<1))" + line 389, "pan.___", state 46, "((i>=1))" + line 396, "pan.___", state 52, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 58, "(1)" + line 396, "pan.___", state 59, "(1)" + line 396, "pan.___", state 59, "(1)" + line 400, "pan.___", state 72, "(1)" + line 400, "pan.___", state 73, "(1)" + line 400, "pan.___", state 73, "(1)" + line 398, "pan.___", state 78, "((i<2))" + line 398, "pan.___", state 78, "((i>=2))" + line 404, "pan.___", state 85, "(1)" + line 404, "pan.___", state 86, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 86, "else" + line 404, "pan.___", state 89, "(1)" + line 404, "pan.___", state 90, "(1)" + line 404, "pan.___", state 90, "(1)" + line 408, "pan.___", state 98, "(1)" + line 408, "pan.___", state 99, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 99, "else" + line 408, "pan.___", state 102, "(1)" + line 408, "pan.___", state 103, "(1)" + line 408, "pan.___", state 103, "(1)" + line 406, "pan.___", state 108, "((i<1))" + line 406, "pan.___", state 108, "((i>=1))" + line 413, "pan.___", state 115, "(1)" + line 413, "pan.___", state 116, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 116, "else" + line 413, "pan.___", state 119, "(1)" + line 413, "pan.___", state 120, "(1)" + line 413, "pan.___", state 120, "(1)" + line 417, "pan.___", state 128, "(1)" + line 417, "pan.___", state 129, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 129, "else" + line 417, "pan.___", state 132, "(1)" + line 417, "pan.___", state 133, "(1)" + line 417, "pan.___", state 133, "(1)" + line 415, "pan.___", state 138, "((i<2))" + line 415, "pan.___", state 138, "((i>=2))" + line 422, "pan.___", state 142, "(1)" + line 422, "pan.___", state 142, "(1)" + line 250, "pan.___", state 151, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 160, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 252, "pan.___", state 168, "((i<1))" + line 252, "pan.___", state 168, "((i>=1))" + line 258, "pan.___", state 173, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 993, "pan.___", state 201, "old_data = cached_rcu_ptr.val[_pid]" + line 1004, "pan.___", state 205, "_proc_urcu_writer = (_proc_urcu_writer|(1<<4))" + line 387, "pan.___", state 213, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 219, "(1)" + line 391, "pan.___", state 227, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 233, "(1)" + line 391, "pan.___", state 234, "(1)" + line 391, "pan.___", state 234, "(1)" + line 389, "pan.___", state 239, "((i<1))" + line 389, "pan.___", state 239, "((i>=1))" + line 396, "pan.___", state 247, "(1)" + line 396, "pan.___", state 248, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 248, "else" + line 396, "pan.___", state 251, "(1)" + line 396, "pan.___", state 252, "(1)" + line 396, "pan.___", state 252, "(1)" + line 400, "pan.___", state 259, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 265, "(1)" + line 400, "pan.___", state 266, "(1)" + line 400, "pan.___", state 266, "(1)" + line 398, "pan.___", state 271, "((i<2))" + line 398, "pan.___", state 271, "((i>=2))" + line 404, "pan.___", state 278, "(1)" + line 404, "pan.___", state 279, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 279, "else" + line 404, "pan.___", state 282, "(1)" + line 404, "pan.___", state 283, "(1)" + line 404, "pan.___", state 283, "(1)" + line 408, "pan.___", state 291, "(1)" + line 408, "pan.___", state 292, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 292, "else" + line 408, "pan.___", state 295, "(1)" + line 408, "pan.___", state 296, "(1)" + line 408, "pan.___", state 296, "(1)" + line 406, "pan.___", state 301, "((i<1))" + line 406, "pan.___", state 301, "((i>=1))" + line 413, "pan.___", state 308, "(1)" + line 413, "pan.___", state 309, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 309, "else" + line 413, "pan.___", state 312, "(1)" + line 413, "pan.___", state 313, "(1)" + line 413, "pan.___", state 313, "(1)" + line 417, "pan.___", state 321, "(1)" + line 417, "pan.___", state 322, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 322, "else" + line 417, "pan.___", state 325, "(1)" + line 417, "pan.___", state 326, "(1)" + line 417, "pan.___", state 326, "(1)" + line 415, "pan.___", state 331, "((i<2))" + line 415, "pan.___", state 331, "((i>=2))" + line 422, "pan.___", state 335, "(1)" + line 422, "pan.___", state 335, "(1)" + line 387, "pan.___", state 346, "(1)" + line 387, "pan.___", state 347, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 347, "else" + line 387, "pan.___", state 350, "(1)" + line 391, "pan.___", state 358, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 364, "(1)" + line 391, "pan.___", state 365, "(1)" + line 391, "pan.___", state 365, "(1)" + line 389, "pan.___", state 370, "((i<1))" + line 389, "pan.___", state 370, "((i>=1))" + line 396, "pan.___", state 376, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 382, "(1)" + line 396, "pan.___", state 383, "(1)" + line 396, "pan.___", state 383, "(1)" + line 400, "pan.___", state 390, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 396, "(1)" + line 400, "pan.___", state 397, "(1)" + line 400, "pan.___", state 397, "(1)" + line 398, "pan.___", state 402, "((i<2))" + line 398, "pan.___", state 402, "((i>=2))" + line 404, "pan.___", state 409, "(1)" + line 404, "pan.___", state 410, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 410, "else" + line 404, "pan.___", state 413, "(1)" + line 404, "pan.___", state 414, "(1)" + line 404, "pan.___", state 414, "(1)" + line 408, "pan.___", state 422, "(1)" + line 408, "pan.___", state 423, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 423, "else" + line 408, "pan.___", state 426, "(1)" + line 408, "pan.___", state 427, "(1)" + line 408, "pan.___", state 427, "(1)" + line 406, "pan.___", state 432, "((i<1))" + line 406, "pan.___", state 432, "((i>=1))" + line 413, "pan.___", state 439, "(1)" + line 413, "pan.___", state 440, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 440, "else" + line 413, "pan.___", state 443, "(1)" + line 413, "pan.___", state 444, "(1)" + line 413, "pan.___", state 444, "(1)" + line 417, "pan.___", state 452, "(1)" + line 417, "pan.___", state 453, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 453, "else" + line 417, "pan.___", state 456, "(1)" + line 417, "pan.___", state 457, "(1)" + line 417, "pan.___", state 457, "(1)" + line 415, "pan.___", state 462, "((i<2))" + line 415, "pan.___", state 462, "((i>=2))" + line 422, "pan.___", state 466, "(1)" + line 422, "pan.___", state 466, "(1)" + line 1056, "pan.___", state 477, "_proc_urcu_writer = (_proc_urcu_writer&~(((1<<8)|(1<<7))))" + line 387, "pan.___", state 482, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 488, "(1)" + line 391, "pan.___", state 496, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 502, "(1)" + line 391, "pan.___", state 503, "(1)" + line 391, "pan.___", state 503, "(1)" + line 389, "pan.___", state 508, "((i<1))" + line 389, "pan.___", state 508, "((i>=1))" + line 396, "pan.___", state 514, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 520, "(1)" + line 396, "pan.___", state 521, "(1)" + line 396, "pan.___", state 521, "(1)" + line 400, "pan.___", state 528, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 534, "(1)" + line 400, "pan.___", state 535, "(1)" + line 400, "pan.___", state 535, "(1)" + line 398, "pan.___", state 540, "((i<2))" + line 398, "pan.___", state 540, "((i>=2))" + line 404, "pan.___", state 547, "(1)" + line 404, "pan.___", state 548, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 548, "else" + line 404, "pan.___", state 551, "(1)" + line 404, "pan.___", state 552, "(1)" + line 404, "pan.___", state 552, "(1)" + line 408, "pan.___", state 560, "(1)" + line 408, "pan.___", state 561, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 561, "else" + line 408, "pan.___", state 564, "(1)" + line 408, "pan.___", state 565, "(1)" + line 408, "pan.___", state 565, "(1)" + line 406, "pan.___", state 570, "((i<1))" + line 406, "pan.___", state 570, "((i>=1))" + line 413, "pan.___", state 577, "(1)" + line 413, "pan.___", state 578, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 578, "else" + line 413, "pan.___", state 581, "(1)" + line 413, "pan.___", state 582, "(1)" + line 413, "pan.___", state 582, "(1)" + line 417, "pan.___", state 590, "(1)" + line 417, "pan.___", state 591, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 591, "else" + line 417, "pan.___", state 594, "(1)" + line 417, "pan.___", state 595, "(1)" + line 417, "pan.___", state 595, "(1)" + line 422, "pan.___", state 604, "(1)" + line 422, "pan.___", state 604, "(1)" + line 387, "pan.___", state 611, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 625, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 643, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 676, "(1)" + line 408, "pan.___", state 689, "(1)" + line 413, "pan.___", state 706, "(1)" + line 417, "pan.___", state 719, "(1)" + line 391, "pan.___", state 756, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 774, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 788, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 820, "(1)" + line 413, "pan.___", state 837, "(1)" + line 417, "pan.___", state 850, "(1)" + line 1128, "pan.___", state 877, "_proc_urcu_writer = (_proc_urcu_writer|(1<<13))" + line 250, "pan.___", state 905, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 907, "(1)" + line 254, "pan.___", state 914, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 916, "(1)" + line 254, "pan.___", state 917, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 917, "else" + line 252, "pan.___", state 922, "((i<1))" + line 252, "pan.___", state 922, "((i>=1))" + line 258, "pan.___", state 927, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 929, "(1)" + line 258, "pan.___", state 930, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 930, "else" + line 262, "pan.___", state 936, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 938, "(1)" + line 262, "pan.___", state 939, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 939, "else" + line 260, "pan.___", state 944, "((i<2))" + line 260, "pan.___", state 944, "((i>=2))" + line 227, "pan.___", state 952, "(1)" + line 231, "pan.___", state 960, "(1)" + line 231, "pan.___", state 961, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 961, "else" + line 229, "pan.___", state 966, "((i<1))" + line 229, "pan.___", state 966, "((i>=1))" + line 235, "pan.___", state 972, "(1)" + line 235, "pan.___", state 973, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 973, "else" + line 239, "pan.___", state 980, "(1)" + line 239, "pan.___", state 981, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 981, "else" + line 244, "pan.___", state 990, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 990, "else" + line 1176, "pan.___", state 1006, "((i<1))" + line 1176, "pan.___", state 1006, "((i>=1))" + line 250, "pan.___", state 1011, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1013, "(1)" + line 254, "pan.___", state 1020, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1022, "(1)" + line 254, "pan.___", state 1023, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1023, "else" + line 252, "pan.___", state 1028, "((i<1))" + line 252, "pan.___", state 1028, "((i>=1))" + line 258, "pan.___", state 1033, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1035, "(1)" + line 258, "pan.___", state 1036, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1036, "else" + line 262, "pan.___", state 1042, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1044, "(1)" + line 262, "pan.___", state 1045, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1045, "else" + line 260, "pan.___", state 1050, "((i<2))" + line 260, "pan.___", state 1050, "((i>=2))" + line 227, "pan.___", state 1058, "(1)" + line 231, "pan.___", state 1066, "(1)" + line 231, "pan.___", state 1067, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1067, "else" + line 229, "pan.___", state 1072, "((i<1))" + line 229, "pan.___", state 1072, "((i>=1))" + line 235, "pan.___", state 1078, "(1)" + line 235, "pan.___", state 1079, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1079, "else" + line 239, "pan.___", state 1086, "(1)" + line 239, "pan.___", state 1087, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1087, "else" + line 244, "pan.___", state 1096, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1096, "else" + line 277, "pan.___", state 1098, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 1098, "else" + line 1176, "pan.___", state 1099, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 1176, "pan.___", state 1099, "else" + line 250, "pan.___", state 1103, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1105, "(1)" + line 254, "pan.___", state 1112, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1114, "(1)" + line 254, "pan.___", state 1115, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1115, "else" + line 252, "pan.___", state 1120, "((i<1))" + line 252, "pan.___", state 1120, "((i>=1))" + line 258, "pan.___", state 1125, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1127, "(1)" + line 258, "pan.___", state 1128, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1128, "else" + line 262, "pan.___", state 1134, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1136, "(1)" + line 262, "pan.___", state 1137, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1137, "else" + line 260, "pan.___", state 1142, "((i<2))" + line 260, "pan.___", state 1142, "((i>=2))" + line 227, "pan.___", state 1150, "(1)" + line 231, "pan.___", state 1158, "(1)" + line 231, "pan.___", state 1159, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1159, "else" + line 229, "pan.___", state 1164, "((i<1))" + line 229, "pan.___", state 1164, "((i>=1))" + line 235, "pan.___", state 1170, "(1)" + line 235, "pan.___", state 1171, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1171, "else" + line 239, "pan.___", state 1178, "(1)" + line 239, "pan.___", state 1179, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1179, "else" + line 244, "pan.___", state 1188, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1188, "else" + line 1180, "pan.___", state 1191, "i = 0" + line 1180, "pan.___", state 1193, "reader_barrier = 1" + line 1180, "pan.___", state 1204, "((i<1))" + line 1180, "pan.___", state 1204, "((i>=1))" + line 250, "pan.___", state 1209, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1211, "(1)" + line 254, "pan.___", state 1218, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1220, "(1)" + line 254, "pan.___", state 1221, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1221, "else" + line 252, "pan.___", state 1226, "((i<1))" + line 252, "pan.___", state 1226, "((i>=1))" + line 258, "pan.___", state 1231, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1233, "(1)" + line 258, "pan.___", state 1234, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1234, "else" + line 262, "pan.___", state 1240, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1242, "(1)" + line 262, "pan.___", state 1243, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1243, "else" + line 260, "pan.___", state 1248, "((i<2))" + line 260, "pan.___", state 1248, "((i>=2))" + line 227, "pan.___", state 1256, "(1)" + line 231, "pan.___", state 1264, "(1)" + line 231, "pan.___", state 1265, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1265, "else" + line 229, "pan.___", state 1270, "((i<1))" + line 229, "pan.___", state 1270, "((i>=1))" + line 235, "pan.___", state 1276, "(1)" + line 235, "pan.___", state 1277, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1277, "else" + line 239, "pan.___", state 1284, "(1)" + line 239, "pan.___", state 1285, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1285, "else" + line 244, "pan.___", state 1294, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1294, "else" + line 277, "pan.___", state 1296, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 1296, "else" + line 1180, "pan.___", state 1297, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 1180, "pan.___", state 1297, "else" + line 254, "pan.___", state 1310, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1323, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1332, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1348, "(1)" + line 231, "pan.___", state 1356, "(1)" + line 235, "pan.___", state 1368, "(1)" + line 239, "pan.___", state 1376, "(1)" + line 250, "pan.___", state 1407, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1416, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1429, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1438, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1454, "(1)" + line 231, "pan.___", state 1462, "(1)" + line 235, "pan.___", state 1474, "(1)" + line 239, "pan.___", state 1482, "(1)" + line 250, "pan.___", state 1499, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1501, "(1)" + line 254, "pan.___", state 1508, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1510, "(1)" + line 254, "pan.___", state 1511, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1511, "else" + line 252, "pan.___", state 1516, "((i<1))" + line 252, "pan.___", state 1516, "((i>=1))" + line 258, "pan.___", state 1521, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1523, "(1)" + line 258, "pan.___", state 1524, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1524, "else" + line 262, "pan.___", state 1530, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1532, "(1)" + line 262, "pan.___", state 1533, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1533, "else" + line 260, "pan.___", state 1538, "((i<2))" + line 260, "pan.___", state 1538, "((i>=2))" + line 227, "pan.___", state 1546, "(1)" + line 231, "pan.___", state 1554, "(1)" + line 231, "pan.___", state 1555, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1555, "else" + line 229, "pan.___", state 1560, "((i<1))" + line 229, "pan.___", state 1560, "((i>=1))" + line 235, "pan.___", state 1566, "(1)" + line 235, "pan.___", state 1567, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1567, "else" + line 239, "pan.___", state 1574, "(1)" + line 239, "pan.___", state 1575, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1575, "else" + line 244, "pan.___", state 1584, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1584, "else" + line 1187, "pan.___", state 1587, "i = 0" + line 1187, "pan.___", state 1589, "reader_barrier = 1" + line 1187, "pan.___", state 1600, "((i<1))" + line 1187, "pan.___", state 1600, "((i>=1))" + line 250, "pan.___", state 1605, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1607, "(1)" + line 254, "pan.___", state 1614, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1616, "(1)" + line 254, "pan.___", state 1617, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1617, "else" + line 252, "pan.___", state 1622, "((i<1))" + line 252, "pan.___", state 1622, "((i>=1))" + line 258, "pan.___", state 1627, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1629, "(1)" + line 258, "pan.___", state 1630, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1630, "else" + line 262, "pan.___", state 1636, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1638, "(1)" + line 262, "pan.___", state 1639, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1639, "else" + line 260, "pan.___", state 1644, "((i<2))" + line 260, "pan.___", state 1644, "((i>=2))" + line 227, "pan.___", state 1652, "(1)" + line 231, "pan.___", state 1660, "(1)" + line 231, "pan.___", state 1661, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1661, "else" + line 229, "pan.___", state 1666, "((i<1))" + line 229, "pan.___", state 1666, "((i>=1))" + line 235, "pan.___", state 1672, "(1)" + line 235, "pan.___", state 1673, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1673, "else" + line 239, "pan.___", state 1680, "(1)" + line 239, "pan.___", state 1681, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1681, "else" + line 244, "pan.___", state 1690, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1690, "else" + line 277, "pan.___", state 1692, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 1692, "else" + line 1187, "pan.___", state 1693, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 1187, "pan.___", state 1693, "else" + line 1191, "pan.___", state 1696, "-end-" + (310 of 1696 states) +unreached in proctype :init: + line 1202, "pan.___", state 9, "((j<2))" + line 1202, "pan.___", state 9, "((j>=2))" + line 1203, "pan.___", state 20, "((j<2))" + line 1203, "pan.___", state 20, "((j>=2))" + line 1208, "pan.___", state 33, "((j<2))" + line 1208, "pan.___", state 33, "((j>=2))" + line 1206, "pan.___", state 43, "((i<1))" + line 1206, "pan.___", state 43, "((i>=1))" + line 1216, "pan.___", state 54, "((j<2))" + line 1216, "pan.___", state 54, "((j>=2))" + line 1220, "pan.___", state 67, "((j<2))" + line 1220, "pan.___", state 67, "((j>=2))" + (6 of 78 states) +unreached in proctype :never: + line 1250, "pan.___", state 8, "-end-" + (1 of 8 states) + +pan: elapsed time 781 seconds +pan: rate 4622.6181 states/second +pan: avg transition delay 1.272e-06 usec +cp .input.spin urcu_free_no_mb.spin.input +cp .input.spin.trail urcu_free_no_mb.spin.input.trail +make[1]: Leaving directory `/home/compudj/doc/userspace-rcu/formal-model/urcu-controldataflow' diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_mb.spin.input b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_mb.spin.input new file mode 100644 index 0000000..e95f5b1 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_mb.spin.input @@ -0,0 +1,1227 @@ +#define NO_MB + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* We choose to ignore writer's non-progress caused from the + * reader ignoring the writer's mb() requests */ +#ifdef WRITER_PROGRESS +progress_writer_from_reader: +#endif + break; + od; +} + +#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: +#define PROGRESS_LABEL(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; \ + /* \ + * 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) \ + do \ + :: (reader_barrier[i] == 1) -> skip; \ + :: (reader_barrier[i] == 0) -> break; \ + od; \ + i++; \ + :: i >= NR_READERS -> \ + break \ + od; \ + smp_mb(i, j); \ +} + +#else + +#define smp_mb_send(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + :: 1 -> skip; + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_mb.spin.input.trail b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_mb.spin.input.trail new file mode 100644 index 0000000..4be75cd --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_mb.spin.input.trail @@ -0,0 +1,1387 @@ +-2:3:-2 +-4:-4:-4 +1:0:4650 +2:3:4570 +3:3:4573 +4:3:4573 +5:3:4576 +6:3:4584 +7:3:4584 +8:3:4587 +9:3:4593 +10:3:4597 +11:3:4597 +12:3:4600 +13:3:4610 +14:3:4618 +15:3:4618 +16:3:4621 +17:3:4627 +18:3:4631 +19:3:4631 +20:3:4634 +21:3:4640 +22:3:4644 +23:3:4645 +24:0:4650 +25:3:4647 +26:0:4650 +27:2:2876 +28:0:4650 +29:2:2882 +30:0:4650 +31:2:2883 +32:0:4650 +33:2:2885 +34:0:4650 +35:2:2886 +36:0:4650 +37:2:2887 +38:0:4650 +39:2:2888 +40:0:4650 +41:2:2889 +42:2:2890 +43:2:2894 +44:2:2895 +45:2:2903 +46:2:2904 +47:2:2908 +48:2:2909 +49:2:2917 +50:2:2922 +51:2:2926 +52:2:2927 +53:2:2935 +54:2:2936 +55:2:2940 +56:2:2941 +57:2:2935 +58:2:2936 +59:2:2940 +60:2:2941 +61:2:2949 +62:2:2954 +63:2:2955 +64:2:2966 +65:2:2967 +66:2:2968 +67:2:2979 +68:2:2984 +69:2:2985 +70:2:2996 +71:2:2997 +72:2:2998 +73:2:2996 +74:2:2997 +75:2:2998 +76:2:3009 +77:2:3017 +78:0:4650 +79:2:2888 +80:0:4650 +81:2:3021 +82:2:3025 +83:2:3026 +84:2:3030 +85:2:3034 +86:2:3035 +87:2:3039 +88:2:3047 +89:2:3048 +90:2:3052 +91:2:3056 +92:2:3057 +93:2:3052 +94:2:3053 +95:2:3061 +96:0:4650 +97:2:2888 +98:0:4650 +99:2:3069 +100:2:3070 +101:2:3071 +102:0:4650 +103:2:2888 +104:0:4650 +105:2:3079 +106:0:4650 +107:2:2888 +108:0:4650 +109:2:3082 +110:2:3083 +111:2:3087 +112:2:3088 +113:2:3096 +114:2:3097 +115:2:3101 +116:2:3102 +117:2:3110 +118:2:3115 +119:2:3116 +120:2:3128 +121:2:3129 +122:2:3133 +123:2:3134 +124:2:3128 +125:2:3129 +126:2:3133 +127:2:3134 +128:2:3142 +129:2:3147 +130:2:3148 +131:2:3159 +132:2:3160 +133:2:3161 +134:2:3172 +135:2:3177 +136:2:3178 +137:2:3189 +138:2:3190 +139:2:3191 +140:2:3189 +141:2:3190 +142:2:3191 +143:2:3202 +144:2:3209 +145:0:4650 +146:2:2888 +147:0:4650 +148:2:3213 +149:2:3214 +150:2:3215 +151:2:3227 +152:2:3228 +153:2:3232 +154:2:3233 +155:2:3241 +156:2:3246 +157:2:3250 +158:2:3251 +159:2:3259 +160:2:3260 +161:2:3264 +162:2:3265 +163:2:3259 +164:2:3260 +165:2:3264 +166:2:3265 +167:2:3273 +168:2:3278 +169:2:3279 +170:2:3290 +171:2:3291 +172:2:3292 +173:2:3303 +174:2:3308 +175:2:3309 +176:2:3320 +177:2:3321 +178:2:3322 +179:2:3320 +180:2:3321 +181:2:3322 +182:2:3333 +183:2:3344 +184:2:3345 +185:0:4650 +186:2:2888 +187:0:4650 +188:2:3351 +189:2:3352 +190:2:3356 +191:2:3357 +192:2:3365 +193:2:3366 +194:2:3370 +195:2:3371 +196:2:3379 +197:2:3384 +198:2:3388 +199:2:3389 +200:2:3397 +201:2:3398 +202:2:3402 +203:2:3403 +204:2:3397 +205:2:3398 +206:2:3402 +207:2:3403 +208:2:3411 +209:2:3416 +210:2:3417 +211:2:3428 +212:2:3429 +213:2:3430 +214:2:3441 +215:2:3446 +216:2:3447 +217:2:3458 +218:2:3459 +219:2:3460 +220:2:3458 +221:2:3459 +222:2:3460 +223:2:3471 +224:0:4650 +225:2:2888 +226:0:4650 +227:2:3480 +228:2:3481 +229:2:3485 +230:2:3486 +231:2:3494 +232:2:3495 +233:2:3499 +234:2:3500 +235:2:3508 +236:2:3513 +237:2:3517 +238:2:3518 +239:2:3526 +240:2:3527 +241:2:3531 +242:2:3532 +243:2:3526 +244:2:3527 +245:2:3531 +246:2:3532 +247:2:3540 +248:2:3545 +249:2:3546 +250:2:3557 +251:2:3558 +252:2:3559 +253:2:3570 +254:2:3575 +255:2:3576 +256:2:3587 +257:2:3588 +258:2:3589 +259:2:3587 +260:2:3588 +261:2:3589 +262:2:3600 +263:2:3607 +264:0:4650 +265:2:2888 +266:0:4650 +267:2:3611 +268:2:3612 +269:2:3613 +270:2:3625 +271:2:3626 +272:2:3630 +273:2:3631 +274:2:3639 +275:2:3644 +276:2:3648 +277:2:3649 +278:2:3657 +279:2:3658 +280:2:3662 +281:2:3663 +282:2:3657 +283:2:3658 +284:2:3662 +285:2:3663 +286:2:3671 +287:2:3676 +288:2:3677 +289:2:3688 +290:2:3689 +291:2:3690 +292:2:3701 +293:2:3706 +294:2:3707 +295:2:3718 +296:2:3719 +297:2:3720 +298:2:3718 +299:2:3719 +300:2:3720 +301:2:3731 +302:2:3741 +303:2:3742 +304:0:4650 +305:2:2888 +306:0:4650 +307:2:3751 +308:2:3752 +309:0:4650 +310:2:2888 +311:0:4650 +312:2:3756 +313:0:4650 +314:2:3764 +315:0:4650 +316:2:2883 +317:0:4650 +318:2:2885 +319:0:4650 +320:2:2886 +321:0:4650 +322:2:2887 +323:0:4650 +324:2:2888 +325:0:4650 +326:2:2889 +327:2:2890 +328:2:2894 +329:2:2895 +330:2:2903 +331:2:2904 +332:2:2908 +333:2:2909 +334:2:2917 +335:2:2922 +336:2:2926 +337:2:2927 +338:2:2935 +339:2:2936 +340:2:2937 +341:2:2935 +342:2:2936 +343:2:2940 +344:2:2941 +345:2:2949 +346:2:2954 +347:2:2955 +348:2:2966 +349:2:2967 +350:2:2968 +351:2:2979 +352:2:2984 +353:2:2985 +354:2:2996 +355:2:2997 +356:2:2998 +357:2:2996 +358:2:2997 +359:2:2998 +360:2:3009 +361:2:3017 +362:0:4650 +363:2:2888 +364:0:4650 +365:2:3021 +366:2:3025 +367:2:3026 +368:2:3030 +369:2:3034 +370:2:3035 +371:2:3039 +372:2:3047 +373:2:3048 +374:2:3052 +375:2:3053 +376:2:3052 +377:2:3056 +378:2:3057 +379:2:3061 +380:0:4650 +381:2:2888 +382:0:4650 +383:2:3069 +384:2:3070 +385:2:3071 +386:0:4650 +387:2:2888 +388:0:4650 +389:2:3079 +390:0:4650 +391:2:2888 +392:0:4650 +393:2:3082 +394:2:3083 +395:2:3087 +396:2:3088 +397:2:3096 +398:2:3097 +399:2:3101 +400:2:3102 +401:2:3110 +402:2:3115 +403:2:3116 +404:2:3128 +405:2:3129 +406:2:3133 +407:2:3134 +408:2:3128 +409:2:3129 +410:2:3133 +411:2:3134 +412:2:3142 +413:2:3147 +414:2:3148 +415:2:3159 +416:2:3160 +417:2:3161 +418:2:3172 +419:2:3177 +420:2:3178 +421:2:3189 +422:2:3190 +423:2:3191 +424:2:3189 +425:2:3190 +426:2:3191 +427:2:3202 +428:2:3209 +429:0:4650 +430:2:2888 +431:0:4650 +432:2:3213 +433:2:3214 +434:2:3215 +435:2:3227 +436:2:3228 +437:2:3232 +438:2:3233 +439:2:3241 +440:2:3246 +441:2:3250 +442:2:3251 +443:2:3259 +444:2:3260 +445:2:3264 +446:2:3265 +447:2:3259 +448:2:3260 +449:2:3264 +450:2:3265 +451:2:3273 +452:2:3278 +453:2:3279 +454:2:3290 +455:2:3291 +456:2:3292 +457:2:3303 +458:2:3308 +459:2:3309 +460:2:3320 +461:2:3321 +462:2:3322 +463:2:3320 +464:2:3321 +465:2:3322 +466:2:3333 +467:2:3344 +468:2:3345 +469:0:4650 +470:2:2888 +471:0:4650 +472:2:3351 +473:2:3352 +474:2:3356 +475:2:3357 +476:2:3365 +477:2:3366 +478:2:3370 +479:2:3371 +480:2:3379 +481:2:3384 +482:2:3388 +483:2:3389 +484:2:3397 +485:2:3398 +486:2:3402 +487:2:3403 +488:2:3397 +489:2:3398 +490:2:3402 +491:2:3403 +492:2:3411 +493:2:3416 +494:2:3417 +495:2:3428 +496:2:3429 +497:2:3430 +498:2:3441 +499:2:3446 +500:2:3447 +501:2:3458 +502:2:3459 +503:2:3460 +504:2:3458 +505:2:3459 +506:2:3460 +507:2:3471 +508:0:4650 +509:2:2888 +510:0:4650 +511:2:3480 +512:2:3481 +513:2:3485 +514:2:3486 +515:2:3494 +516:2:3495 +517:2:3499 +518:2:3500 +519:2:3508 +520:2:3513 +521:2:3517 +522:2:3518 +523:2:3526 +524:2:3527 +525:2:3531 +526:2:3532 +527:2:3526 +528:2:3527 +529:2:3531 +530:2:3532 +531:2:3540 +532:2:3545 +533:2:3546 +534:2:3557 +535:2:3558 +536:2:3559 +537:2:3570 +538:2:3575 +539:2:3576 +540:2:3587 +541:2:3588 +542:2:3589 +543:2:3587 +544:2:3588 +545:2:3589 +546:2:3600 +547:2:3607 +548:0:4650 +549:2:2888 +550:0:4650 +551:2:3611 +552:2:3612 +553:2:3613 +554:2:3625 +555:2:3626 +556:2:3630 +557:2:3631 +558:2:3639 +559:2:3644 +560:2:3648 +561:2:3649 +562:2:3657 +563:2:3658 +564:2:3662 +565:2:3663 +566:2:3657 +567:2:3658 +568:2:3662 +569:2:3663 +570:2:3671 +571:2:3676 +572:2:3677 +573:2:3688 +574:2:3689 +575:2:3690 +576:2:3701 +577:2:3706 +578:2:3707 +579:2:3718 +580:2:3719 +581:2:3720 +582:2:3718 +583:2:3719 +584:2:3720 +585:2:3731 +586:2:3741 +587:2:3742 +588:0:4650 +589:2:2888 +590:0:4650 +591:2:3751 +592:2:3752 +593:0:4650 +594:2:2888 +595:0:4650 +596:2:3756 +597:0:4650 +598:2:3764 +599:0:4650 +600:2:2883 +601:0:4650 +602:2:2885 +603:0:4650 +604:2:2886 +605:0:4650 +606:2:2887 +607:0:4650 +608:2:2888 +609:0:4650 +610:2:2889 +611:2:2890 +612:2:2894 +613:2:2895 +614:2:2903 +615:2:2904 +616:2:2908 +617:2:2909 +618:2:2917 +619:2:2922 +620:2:2926 +621:2:2927 +622:2:2935 +623:2:2936 +624:2:2940 +625:2:2941 +626:2:2935 +627:2:2936 +628:2:2937 +629:2:2949 +630:2:2954 +631:2:2955 +632:2:2966 +633:2:2967 +634:2:2968 +635:2:2979 +636:2:2984 +637:2:2985 +638:2:2996 +639:2:2997 +640:2:2998 +641:2:2996 +642:2:2997 +643:2:2998 +644:2:3009 +645:2:3017 +646:0:4650 +647:2:2888 +648:0:4650 +649:2:3021 +650:2:3025 +651:2:3026 +652:2:3030 +653:2:3034 +654:2:3035 +655:2:3039 +656:2:3047 +657:2:3048 +658:2:3052 +659:2:3056 +660:2:3057 +661:2:3052 +662:2:3053 +663:2:3061 +664:0:4650 +665:2:2888 +666:0:4650 +667:2:3069 +668:2:3070 +669:2:3071 +670:0:4650 +671:2:2888 +672:0:4650 +673:2:3079 +674:0:4650 +675:2:2888 +676:0:4650 +677:2:3082 +678:2:3083 +679:2:3087 +680:2:3088 +681:2:3096 +682:2:3097 +683:2:3101 +684:2:3102 +685:2:3110 +686:2:3115 +687:2:3116 +688:2:3128 +689:2:3129 +690:2:3133 +691:2:3134 +692:2:3128 +693:2:3129 +694:2:3133 +695:2:3134 +696:2:3142 +697:2:3147 +698:2:3148 +699:2:3159 +700:2:3160 +701:2:3161 +702:2:3172 +703:2:3177 +704:2:3178 +705:2:3189 +706:2:3190 +707:2:3191 +708:2:3189 +709:2:3190 +710:2:3191 +711:2:3202 +712:2:3209 +713:0:4650 +714:2:2888 +715:0:4650 +716:2:3213 +717:2:3214 +718:2:3215 +719:2:3227 +720:2:3228 +721:2:3232 +722:2:3233 +723:2:3241 +724:2:3246 +725:2:3250 +726:2:3251 +727:2:3259 +728:2:3260 +729:2:3264 +730:2:3265 +731:2:3259 +732:2:3260 +733:2:3264 +734:2:3265 +735:2:3273 +736:2:3278 +737:2:3279 +738:2:3290 +739:2:3291 +740:2:3292 +741:2:3303 +742:2:3308 +743:2:3309 +744:2:3320 +745:2:3321 +746:2:3322 +747:2:3320 +748:2:3321 +749:2:3322 +750:2:3333 +751:2:3344 +752:2:3345 +753:0:4650 +754:2:2888 +755:0:4650 +756:2:3351 +757:2:3352 +758:2:3356 +759:2:3357 +760:2:3365 +761:2:3366 +762:2:3370 +763:2:3371 +764:2:3379 +765:2:3384 +766:2:3388 +767:2:3389 +768:2:3397 +769:2:3398 +770:2:3402 +771:2:3403 +772:2:3397 +773:2:3398 +774:2:3402 +775:2:3403 +776:2:3411 +777:2:3416 +778:2:3417 +779:2:3428 +780:2:3429 +781:2:3430 +782:2:3441 +783:2:3446 +784:2:3447 +785:2:3458 +786:2:3459 +787:2:3460 +788:2:3458 +789:2:3459 +790:2:3460 +791:2:3471 +792:0:4650 +793:2:2888 +794:0:4650 +795:2:3611 +796:2:3612 +797:2:3616 +798:2:3617 +799:2:3625 +800:2:3626 +801:2:3630 +802:2:3631 +803:2:3639 +804:2:3644 +805:2:3648 +806:2:3649 +807:2:3657 +808:2:3658 +809:2:3662 +810:2:3663 +811:2:3657 +812:2:3658 +813:2:3662 +814:2:3663 +815:2:3671 +816:2:3676 +817:2:3677 +818:2:3688 +819:2:3689 +820:2:3690 +821:2:3701 +822:2:3706 +823:2:3707 +824:2:3718 +825:2:3719 +826:2:3720 +827:2:3718 +828:2:3719 +829:2:3720 +830:2:3731 +831:2:3741 +832:2:3742 +833:0:4650 +834:2:2888 +835:0:4650 +836:2:3751 +837:2:3752 +838:0:4650 +839:2:2888 +840:0:4650 +841:2:3480 +842:2:3481 +843:2:3485 +844:2:3486 +845:2:3494 +846:2:3495 +847:2:3499 +848:2:3500 +849:2:3508 +850:2:3513 +851:2:3517 +852:2:3518 +853:2:3526 +854:2:3527 +855:2:3528 +856:2:3526 +857:2:3527 +858:2:3531 +859:2:3532 +860:2:3540 +861:2:3545 +862:2:3546 +863:2:3557 +864:2:3558 +865:2:3559 +866:2:3570 +867:2:3575 +868:2:3576 +869:2:3587 +870:2:3588 +871:2:3589 +872:2:3587 +873:2:3588 +874:2:3589 +875:2:3600 +876:2:3607 +877:0:4650 +878:2:2888 +879:0:4650 +880:2:3756 +881:0:4650 +882:2:3764 +883:0:4650 +884:2:3765 +885:0:4650 +886:2:3770 +887:0:4650 +888:1:2 +889:0:4650 +890:2:3771 +891:0:4650 +892:1:8 +893:0:4650 +894:2:3770 +895:0:4650 +896:1:9 +897:0:4650 +898:2:3771 +899:0:4650 +900:1:10 +901:0:4650 +902:2:3770 +903:0:4650 +904:1:11 +905:0:4650 +906:2:3771 +907:0:4650 +908:1:12 +909:0:4650 +910:2:3770 +911:0:4650 +912:1:13 +913:0:4650 +914:2:3771 +915:0:4650 +916:1:14 +917:0:4650 +918:2:3770 +919:0:4650 +920:1:15 +921:0:4650 +922:2:3771 +923:0:4650 +924:1:16 +925:0:4650 +926:2:3770 +927:0:4650 +928:1:17 +929:0:4650 +930:2:3771 +931:0:4650 +932:1:18 +933:0:4650 +934:2:3770 +935:0:4650 +936:1:19 +937:0:4650 +938:2:3771 +939:0:4650 +940:1:20 +941:0:4650 +942:2:3770 +943:0:4650 +944:1:21 +945:0:4650 +946:2:3771 +947:0:4650 +948:1:124 +949:0:4650 +950:2:3770 +951:0:4650 +952:1:23 +953:0:4650 +954:2:3771 +955:0:4650 +956:1:131 +957:1:132 +958:1:136 +959:1:137 +960:1:145 +961:1:146 +962:1:150 +963:1:151 +964:1:159 +965:1:164 +966:1:168 +967:1:169 +968:1:177 +969:1:178 +970:1:182 +971:1:183 +972:1:177 +973:1:178 +974:1:182 +975:1:183 +976:1:191 +977:1:196 +978:1:197 +979:1:208 +980:1:209 +981:1:210 +982:1:221 +983:1:233 +984:1:234 +985:1:238 +986:1:239 +987:1:240 +988:1:238 +989:1:239 +990:1:240 +991:1:251 +992:0:4650 +993:2:3770 +994:0:4650 +995:1:19 +996:0:4650 +997:2:3771 +998:0:4650 +999:1:20 +1000:0:4650 +1001:2:3770 +1002:0:4650 +1003:1:21 +1004:0:4650 +1005:2:3771 +1006:0:4650 +1007:1:124 +1008:0:4650 +1009:2:3770 +1010:0:4650 +1011:1:23 +1012:0:4650 +1013:2:3771 +1014:0:4650 +1015:1:260 +1016:1:261 +1017:0:4650 +1018:2:3770 +1019:0:4650 +1020:1:19 +1021:0:4650 +1022:2:3771 +1023:0:4650 +1024:1:20 +1025:0:4650 +1026:2:3770 +1027:0:4650 +1028:1:21 +1029:0:4650 +1030:2:3771 +1031:0:4650 +1032:1:124 +1033:0:4650 +1034:2:3770 +1035:0:4650 +1036:1:23 +1037:0:4650 +1038:2:3771 +1039:0:4650 +1040:1:267 +1041:1:268 +1042:1:272 +1043:1:273 +1044:1:281 +1045:1:282 +1046:1:286 +1047:1:287 +1048:1:295 +1049:1:300 +1050:1:304 +1051:1:305 +1052:1:313 +1053:1:314 +1054:1:318 +1055:1:319 +1056:1:313 +1057:1:314 +1058:1:318 +1059:1:319 +1060:1:327 +1061:1:332 +1062:1:333 +1063:1:344 +1064:1:345 +1065:1:346 +1066:1:357 +1067:1:369 +1068:1:370 +1069:1:374 +1070:1:375 +1071:1:376 +1072:1:374 +1073:1:375 +1074:1:376 +1075:1:387 +1076:0:4650 +1077:2:3770 +1078:0:4650 +1079:1:19 +1080:0:4650 +1081:2:3771 +1082:0:4650 +1083:1:20 +1084:0:4650 +1085:2:3770 +1086:0:4650 +1087:1:21 +1088:0:4650 +1089:2:3771 +1090:0:4650 +1091:1:124 +1092:0:4650 +1093:2:3770 +1094:0:4650 +1095:1:23 +1096:0:4650 +1097:2:3771 +1098:0:4650 +1099:1:396 +1100:1:397 +1101:1:401 +1102:1:402 +1103:1:410 +1104:1:411 +1105:1:415 +1106:1:416 +1107:1:424 +1108:1:429 +1109:1:433 +1110:1:434 +1111:1:442 +1112:1:443 +1113:1:447 +1114:1:448 +1115:1:442 +1116:1:443 +1117:1:447 +1118:1:448 +1119:1:456 +1120:1:461 +1121:1:462 +1122:1:473 +1123:1:474 +1124:1:475 +1125:1:486 +1126:1:498 +1127:1:499 +1128:1:503 +1129:1:504 +1130:1:505 +1131:1:503 +1132:1:504 +1133:1:505 +1134:1:516 +1135:1:523 +1136:0:4650 +1137:2:3770 +1138:0:4650 +1139:1:19 +1140:0:4650 +1141:2:3771 +1142:0:4650 +1143:1:20 +1144:0:4650 +1145:2:3770 +1146:0:4650 +1147:1:21 +1148:0:4650 +1149:2:3771 +1150:0:4650 +1151:1:124 +1152:0:4650 +1153:2:3770 +1154:0:4650 +1155:1:23 +1156:0:4650 +1157:2:3771 +1158:0:4650 +1159:1:661 +1160:1:662 +1161:1:666 +1162:1:667 +1163:1:675 +1164:1:676 +1165:1:677 +1166:1:689 +1167:1:694 +1168:1:698 +1169:1:699 +1170:1:707 +1171:1:708 +1172:1:712 +1173:1:713 +1174:1:707 +1175:1:708 +1176:1:712 +1177:1:713 +1178:1:721 +1179:1:726 +1180:1:727 +1181:1:738 +1182:1:739 +1183:1:740 +1184:1:751 +1185:1:763 +1186:1:764 +1187:1:768 +1188:1:769 +1189:1:770 +1190:1:768 +1191:1:769 +1192:1:770 +1193:1:781 +1194:0:4650 +1195:2:3770 +1196:0:4650 +1197:1:19 +1198:0:4650 +1199:2:3771 +1200:0:4650 +1201:1:20 +1202:0:4650 +1203:2:3770 +1204:0:4650 +1205:1:21 +1206:0:4650 +1207:2:3771 +1208:0:4650 +1209:1:124 +1210:0:4650 +1211:2:3770 +1212:0:4650 +1213:1:23 +1214:0:4650 +1215:2:3771 +1216:0:4650 +1217:1:790 +1218:1:793 +1219:1:794 +1220:0:4650 +1221:2:3770 +1222:0:4650 +1223:1:19 +1224:0:4650 +1225:2:3771 +1226:0:4650 +1227:1:20 +1228:0:4650 +1229:2:3770 +1230:0:4650 +1231:1:21 +1232:0:4650 +1233:2:3771 +1234:0:4650 +1235:1:124 +1236:0:4650 +1237:2:3770 +1238:0:4650 +1239:1:23 +1240:0:4650 +1241:2:3771 +1242:0:4650 +1243:1:1057 +1244:1:1058 +1245:1:1062 +1246:1:1063 +1247:1:1071 +1248:1:1072 +1249:1:1076 +1250:1:1077 +1251:1:1085 +1252:1:1090 +1253:1:1094 +1254:1:1095 +1255:1:1103 +1256:1:1104 +1257:1:1108 +1258:1:1109 +1259:1:1103 +1260:1:1104 +1261:1:1108 +1262:1:1109 +1263:1:1117 +1264:1:1122 +1265:1:1123 +1266:1:1134 +1267:1:1135 +1268:1:1136 +1269:1:1147 +1270:1:1159 +1271:1:1160 +1272:1:1164 +1273:1:1165 +1274:1:1166 +1275:1:1164 +1276:1:1165 +1277:1:1166 +1278:1:1177 +1279:1:1184 +1280:1:1188 +1281:0:4650 +1282:2:3770 +1283:0:4650 +1284:1:19 +1285:0:4650 +1286:2:3771 +1287:0:4650 +1288:1:20 +1289:0:4650 +1290:2:3770 +1291:0:4650 +1292:1:21 +1293:0:4650 +1294:2:3771 +1295:0:4650 +1296:1:124 +1297:0:4650 +1298:2:3770 +1299:0:4650 +1300:1:23 +1301:0:4650 +1302:2:3771 +1303:0:4650 +1304:1:1189 +1305:1:1190 +1306:1:1194 +1307:1:1195 +1308:1:1203 +1309:1:1204 +1310:1:1205 +1311:1:1217 +1312:1:1222 +1313:1:1226 +1314:1:1227 +1315:1:1235 +1316:1:1236 +1317:1:1240 +1318:1:1241 +1319:1:1235 +1320:1:1236 +1321:1:1240 +1322:1:1241 +1323:1:1249 +1324:1:1254 +1325:1:1255 +1326:1:1266 +1327:1:1267 +1328:1:1268 +1329:1:1279 +1330:1:1291 +1331:1:1292 +1332:1:1296 +1333:1:1297 +1334:1:1298 +1335:1:1296 +1336:1:1297 +1337:1:1298 +1338:1:1309 +1339:0:4650 +1340:2:3770 +1341:0:4650 +1342:1:19 +1343:0:4650 +1344:2:3771 +1345:0:4650 +1346:1:20 +1347:0:4650 +1348:2:3770 +1349:0:4650 +1350:1:21 +1351:0:4650 +1352:2:3771 +1353:0:4650 +1354:1:124 +1355:0:4650 +1356:2:3770 +1357:0:4650 +1358:1:23 +1359:0:4650 +1360:2:3771 +1361:0:4650 +1362:1:1318 +1363:0:4650 +1364:2:3770 +1365:0:4650 +1366:1:2782 +1367:1:2789 +1368:1:2790 +1369:1:2797 +1370:1:2802 +1371:1:2809 +1372:1:2810 +1373:1:2809 +1374:1:2810 +1375:1:2817 +1376:1:2821 +1377:0:4650 +1378:2:3771 +1379:0:4650 +1380:1:1320 +1381:1:1321 +1382:0:4648 +1383:2:3770 +1384:0:4654 +1385:1:1438 diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_rmb.define b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_rmb.define new file mode 100644 index 0000000..73e61a4 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_rmb.define @@ -0,0 +1 @@ +#define NO_RMB diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_rmb.log b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_rmb.log new file mode 100644 index 0000000..43a1b71 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_rmb.log @@ -0,0 +1,592 @@ +make[1]: Entering directory `/home/compudj/doc/userspace-rcu/formal-model/urcu-controldataflow' +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define >> pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_free.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_free_no_rmb.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1245) +Depth= 8403 States= 1e+06 Transitions= 2.27e+08 Memory= 550.432 t= 277 R= 4e+03 +Depth= 10017 States= 2e+06 Transitions= 4.61e+08 Memory= 634.318 t= 573 R= 3e+03 +Depth= 10017 States= 3e+06 Transitions= 7.1e+08 Memory= 718.303 t= 888 R= 3e+03 +pan: resizing hashtable to -w22.. done +Depth= 10017 States= 4e+06 Transitions= 9.4e+08 Memory= 833.311 t= 1.17e+03 R= 3e+03 +Depth= 10017 States= 5e+06 Transitions= 1.2e+09 Memory= 917.295 t= 1.49e+03 R= 3e+03 +Depth= 10017 States= 6e+06 Transitions= 1.73e+09 Memory= 1001.279 t= 2.17e+03 R= 3e+03 +Depth= 10017 States= 7e+06 Transitions= 2.17e+09 Memory= 1085.264 t= 2.72e+03 R= 3e+03 +Depth= 10017 States= 8e+06 Transitions= 2.56e+09 Memory= 1169.151 t= 3.23e+03 R= 2e+03 +Depth= 10017 States= 9e+06 Transitions= 2.96e+09 Memory= 1253.135 t= 3.74e+03 R= 2e+03 +pan: resizing hashtable to -w24.. done +pan: claim violated! (at depth 1606) +pan: wrote .input.spin.trail + +(Spin Version 5.1.7 -- 23 December 2008) +Warning: Search not completed + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness disabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 10017, errors: 1 + 9005656 states, stored +2.9547657e+09 states, matched +2.9637714e+09 transitions (= stored+matched) +1.6918577e+10 atomic steps +hash conflicts: 2.3126803e+09 (resolved) + +Stats on memory usage (in Megabytes): + 996.262 equivalent memory usage for states (stored*(State-vector + overhead)) + 795.835 actual memory usage for states (compression: 79.88%) + state-vector as stored = 65 byte + 28 byte overhead + 128.000 memory used for hash table (-w24) + 457.764 memory used for DFS stack (-m10000000) + 1381.135 total actual memory usage + +unreached in proctype urcu_reader + line 250, "pan.___", state 32, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 54, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 63, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 79, "(1)" + line 231, "pan.___", state 87, "(1)" + line 235, "pan.___", state 99, "(1)" + line 239, "pan.___", state 107, "(1)" + line 387, "pan.___", state 132, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 164, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 178, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 197, "(1)" + line 413, "pan.___", state 227, "(1)" + line 417, "pan.___", state 240, "(1)" + line 663, "pan.___", state 261, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 387, "pan.___", state 268, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 300, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 314, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 333, "(1)" + line 413, "pan.___", state 363, "(1)" + line 417, "pan.___", state 376, "(1)" + line 387, "pan.___", state 397, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 429, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 443, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 462, "(1)" + line 413, "pan.___", state 492, "(1)" + line 417, "pan.___", state 505, "(1)" + line 387, "pan.___", state 528, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 530, "(1)" + line 387, "pan.___", state 531, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 531, "else" + line 387, "pan.___", state 534, "(1)" + line 391, "pan.___", state 542, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 544, "(1)" + line 391, "pan.___", state 545, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 545, "else" + line 391, "pan.___", state 548, "(1)" + line 391, "pan.___", state 549, "(1)" + line 391, "pan.___", state 549, "(1)" + line 389, "pan.___", state 554, "((i<1))" + line 389, "pan.___", state 554, "((i>=1))" + line 396, "pan.___", state 560, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 562, "(1)" + line 396, "pan.___", state 563, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 563, "else" + line 396, "pan.___", state 566, "(1)" + line 396, "pan.___", state 567, "(1)" + line 396, "pan.___", state 567, "(1)" + line 400, "pan.___", state 574, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 576, "(1)" + line 400, "pan.___", state 577, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 577, "else" + line 400, "pan.___", state 580, "(1)" + line 400, "pan.___", state 581, "(1)" + line 400, "pan.___", state 581, "(1)" + line 398, "pan.___", state 586, "((i<2))" + line 398, "pan.___", state 586, "((i>=2))" + line 404, "pan.___", state 593, "(1)" + line 404, "pan.___", state 594, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 594, "else" + line 404, "pan.___", state 597, "(1)" + line 404, "pan.___", state 598, "(1)" + line 404, "pan.___", state 598, "(1)" + line 408, "pan.___", state 606, "(1)" + line 408, "pan.___", state 607, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 607, "else" + line 408, "pan.___", state 610, "(1)" + line 408, "pan.___", state 611, "(1)" + line 408, "pan.___", state 611, "(1)" + line 406, "pan.___", state 616, "((i<1))" + line 406, "pan.___", state 616, "((i>=1))" + line 413, "pan.___", state 623, "(1)" + line 413, "pan.___", state 624, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 624, "else" + line 413, "pan.___", state 627, "(1)" + line 413, "pan.___", state 628, "(1)" + line 413, "pan.___", state 628, "(1)" + line 417, "pan.___", state 636, "(1)" + line 417, "pan.___", state 637, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 637, "else" + line 417, "pan.___", state 640, "(1)" + line 417, "pan.___", state 641, "(1)" + line 417, "pan.___", state 641, "(1)" + line 415, "pan.___", state 646, "((i<2))" + line 415, "pan.___", state 646, "((i>=2))" + line 422, "pan.___", state 650, "(1)" + line 422, "pan.___", state 650, "(1)" + line 663, "pan.___", state 653, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 663, "pan.___", state 654, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 663, "pan.___", state 655, "(1)" + line 387, "pan.___", state 662, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 694, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 708, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 727, "(1)" + line 413, "pan.___", state 757, "(1)" + line 417, "pan.___", state 770, "(1)" + line 387, "pan.___", state 798, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 800, "(1)" + line 387, "pan.___", state 801, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 801, "else" + line 387, "pan.___", state 804, "(1)" + line 391, "pan.___", state 812, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 814, "(1)" + line 391, "pan.___", state 815, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 815, "else" + line 391, "pan.___", state 818, "(1)" + line 391, "pan.___", state 819, "(1)" + line 391, "pan.___", state 819, "(1)" + line 389, "pan.___", state 824, "((i<1))" + line 389, "pan.___", state 824, "((i>=1))" + line 396, "pan.___", state 830, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 832, "(1)" + line 396, "pan.___", state 833, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 833, "else" + line 396, "pan.___", state 836, "(1)" + line 396, "pan.___", state 837, "(1)" + line 396, "pan.___", state 837, "(1)" + line 400, "pan.___", state 844, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 846, "(1)" + line 400, "pan.___", state 847, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 847, "else" + line 400, "pan.___", state 850, "(1)" + line 400, "pan.___", state 851, "(1)" + line 400, "pan.___", state 851, "(1)" + line 398, "pan.___", state 856, "((i<2))" + line 398, "pan.___", state 856, "((i>=2))" + line 404, "pan.___", state 863, "(1)" + line 404, "pan.___", state 864, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 864, "else" + line 404, "pan.___", state 867, "(1)" + line 404, "pan.___", state 868, "(1)" + line 404, "pan.___", state 868, "(1)" + line 408, "pan.___", state 876, "(1)" + line 408, "pan.___", state 877, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 877, "else" + line 408, "pan.___", state 880, "(1)" + line 408, "pan.___", state 881, "(1)" + line 408, "pan.___", state 881, "(1)" + line 406, "pan.___", state 886, "((i<1))" + line 406, "pan.___", state 886, "((i>=1))" + line 413, "pan.___", state 893, "(1)" + line 413, "pan.___", state 894, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 894, "else" + line 413, "pan.___", state 897, "(1)" + line 413, "pan.___", state 898, "(1)" + line 413, "pan.___", state 898, "(1)" + line 417, "pan.___", state 906, "(1)" + line 417, "pan.___", state 907, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 907, "else" + line 417, "pan.___", state 910, "(1)" + line 417, "pan.___", state 911, "(1)" + line 417, "pan.___", state 911, "(1)" + line 422, "pan.___", state 920, "(1)" + line 422, "pan.___", state 920, "(1)" + line 387, "pan.___", state 927, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 929, "(1)" + line 387, "pan.___", state 930, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 930, "else" + line 387, "pan.___", state 933, "(1)" + line 391, "pan.___", state 941, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 943, "(1)" + line 391, "pan.___", state 944, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 944, "else" + line 391, "pan.___", state 947, "(1)" + line 391, "pan.___", state 948, "(1)" + line 391, "pan.___", state 948, "(1)" + line 389, "pan.___", state 953, "((i<1))" + line 389, "pan.___", state 953, "((i>=1))" + line 396, "pan.___", state 959, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 961, "(1)" + line 396, "pan.___", state 962, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 962, "else" + line 396, "pan.___", state 965, "(1)" + line 396, "pan.___", state 966, "(1)" + line 396, "pan.___", state 966, "(1)" + line 400, "pan.___", state 973, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 975, "(1)" + line 400, "pan.___", state 976, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 976, "else" + line 400, "pan.___", state 979, "(1)" + line 400, "pan.___", state 980, "(1)" + line 400, "pan.___", state 980, "(1)" + line 398, "pan.___", state 985, "((i<2))" + line 398, "pan.___", state 985, "((i>=2))" + line 404, "pan.___", state 992, "(1)" + line 404, "pan.___", state 993, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 993, "else" + line 404, "pan.___", state 996, "(1)" + line 404, "pan.___", state 997, "(1)" + line 404, "pan.___", state 997, "(1)" + line 408, "pan.___", state 1005, "(1)" + line 408, "pan.___", state 1006, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 1006, "else" + line 408, "pan.___", state 1009, "(1)" + line 408, "pan.___", state 1010, "(1)" + line 408, "pan.___", state 1010, "(1)" + line 406, "pan.___", state 1015, "((i<1))" + line 406, "pan.___", state 1015, "((i>=1))" + line 413, "pan.___", state 1022, "(1)" + line 413, "pan.___", state 1023, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 1023, "else" + line 413, "pan.___", state 1026, "(1)" + line 413, "pan.___", state 1027, "(1)" + line 413, "pan.___", state 1027, "(1)" + line 417, "pan.___", state 1035, "(1)" + line 417, "pan.___", state 1036, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 1036, "else" + line 417, "pan.___", state 1039, "(1)" + line 417, "pan.___", state 1040, "(1)" + line 417, "pan.___", state 1040, "(1)" + line 415, "pan.___", state 1045, "((i<2))" + line 415, "pan.___", state 1045, "((i>=2))" + line 422, "pan.___", state 1049, "(1)" + line 422, "pan.___", state 1049, "(1)" + line 671, "pan.___", state 1053, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 387, "pan.___", state 1058, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1090, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1104, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1123, "(1)" + line 413, "pan.___", state 1153, "(1)" + line 417, "pan.___", state 1166, "(1)" + line 387, "pan.___", state 1190, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1222, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1236, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1255, "(1)" + line 413, "pan.___", state 1285, "(1)" + line 417, "pan.___", state 1298, "(1)" + line 387, "pan.___", state 1323, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1355, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1369, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1388, "(1)" + line 413, "pan.___", state 1418, "(1)" + line 417, "pan.___", state 1431, "(1)" + line 387, "pan.___", state 1452, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1484, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1498, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1517, "(1)" + line 413, "pan.___", state 1547, "(1)" + line 417, "pan.___", state 1560, "(1)" + line 387, "pan.___", state 1586, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1618, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1632, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1651, "(1)" + line 413, "pan.___", state 1681, "(1)" + line 417, "pan.___", state 1694, "(1)" + line 387, "pan.___", state 1715, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1747, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1761, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1780, "(1)" + line 413, "pan.___", state 1810, "(1)" + line 417, "pan.___", state 1823, "(1)" + line 387, "pan.___", state 1847, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1879, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1893, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1912, "(1)" + line 413, "pan.___", state 1942, "(1)" + line 417, "pan.___", state 1955, "(1)" + line 710, "pan.___", state 1976, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 387, "pan.___", state 1983, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2015, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2029, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2048, "(1)" + line 413, "pan.___", state 2078, "(1)" + line 417, "pan.___", state 2091, "(1)" + line 387, "pan.___", state 2112, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2144, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2158, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2177, "(1)" + line 413, "pan.___", state 2207, "(1)" + line 417, "pan.___", state 2220, "(1)" + line 387, "pan.___", state 2243, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 2245, "(1)" + line 387, "pan.___", state 2246, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 2246, "else" + line 387, "pan.___", state 2249, "(1)" + line 391, "pan.___", state 2257, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 2259, "(1)" + line 391, "pan.___", state 2260, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 2260, "else" + line 391, "pan.___", state 2263, "(1)" + line 391, "pan.___", state 2264, "(1)" + line 391, "pan.___", state 2264, "(1)" + line 389, "pan.___", state 2269, "((i<1))" + line 389, "pan.___", state 2269, "((i>=1))" + line 396, "pan.___", state 2275, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2277, "(1)" + line 396, "pan.___", state 2278, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 2278, "else" + line 396, "pan.___", state 2281, "(1)" + line 396, "pan.___", state 2282, "(1)" + line 396, "pan.___", state 2282, "(1)" + line 400, "pan.___", state 2289, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2291, "(1)" + line 400, "pan.___", state 2292, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 2292, "else" + line 400, "pan.___", state 2295, "(1)" + line 400, "pan.___", state 2296, "(1)" + line 400, "pan.___", state 2296, "(1)" + line 398, "pan.___", state 2301, "((i<2))" + line 398, "pan.___", state 2301, "((i>=2))" + line 404, "pan.___", state 2308, "(1)" + line 404, "pan.___", state 2309, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 2309, "else" + line 404, "pan.___", state 2312, "(1)" + line 404, "pan.___", state 2313, "(1)" + line 404, "pan.___", state 2313, "(1)" + line 408, "pan.___", state 2321, "(1)" + line 408, "pan.___", state 2322, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 2322, "else" + line 408, "pan.___", state 2325, "(1)" + line 408, "pan.___", state 2326, "(1)" + line 408, "pan.___", state 2326, "(1)" + line 406, "pan.___", state 2331, "((i<1))" + line 406, "pan.___", state 2331, "((i>=1))" + line 413, "pan.___", state 2338, "(1)" + line 413, "pan.___", state 2339, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 2339, "else" + line 413, "pan.___", state 2342, "(1)" + line 413, "pan.___", state 2343, "(1)" + line 413, "pan.___", state 2343, "(1)" + line 417, "pan.___", state 2351, "(1)" + line 417, "pan.___", state 2352, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 2352, "else" + line 417, "pan.___", state 2355, "(1)" + line 417, "pan.___", state 2356, "(1)" + line 417, "pan.___", state 2356, "(1)" + line 415, "pan.___", state 2361, "((i<2))" + line 415, "pan.___", state 2361, "((i>=2))" + line 422, "pan.___", state 2365, "(1)" + line 422, "pan.___", state 2365, "(1)" + line 710, "pan.___", state 2368, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 710, "pan.___", state 2369, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 710, "pan.___", state 2370, "(1)" + line 387, "pan.___", state 2377, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2409, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2423, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2442, "(1)" + line 413, "pan.___", state 2472, "(1)" + line 417, "pan.___", state 2485, "(1)" + line 387, "pan.___", state 2512, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2544, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2558, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2577, "(1)" + line 413, "pan.___", state 2607, "(1)" + line 417, "pan.___", state 2620, "(1)" + line 387, "pan.___", state 2641, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2673, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2687, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2706, "(1)" + line 413, "pan.___", state 2736, "(1)" + line 417, "pan.___", state 2749, "(1)" + line 387, "pan.___", state 2782, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2814, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2828, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2847, "(1)" + line 413, "pan.___", state 2877, "(1)" + line 417, "pan.___", state 2890, "(1)" + line 387, "pan.___", state 2909, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2941, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2955, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2974, "(1)" + line 413, "pan.___", state 3004, "(1)" + line 417, "pan.___", state 3017, "(1)" + line 870, "pan.___", state 3038, "-end-" + (284 of 3038 states) +unreached in proctype urcu_writer + line 387, "pan.___", state 18, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 24, "(1)" + line 391, "pan.___", state 32, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 38, "(1)" + line 391, "pan.___", state 39, "(1)" + line 391, "pan.___", state 39, "(1)" + line 389, "pan.___", state 44, "((i<1))" + line 389, "pan.___", state 44, "((i>=1))" + line 396, "pan.___", state 50, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 56, "(1)" + line 396, "pan.___", state 57, "(1)" + line 396, "pan.___", state 57, "(1)" + line 400, "pan.___", state 70, "(1)" + line 400, "pan.___", state 71, "(1)" + line 400, "pan.___", state 71, "(1)" + line 398, "pan.___", state 76, "((i<2))" + line 398, "pan.___", state 76, "((i>=2))" + line 404, "pan.___", state 83, "(1)" + line 404, "pan.___", state 84, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 84, "else" + line 404, "pan.___", state 87, "(1)" + line 404, "pan.___", state 88, "(1)" + line 404, "pan.___", state 88, "(1)" + line 408, "pan.___", state 96, "(1)" + line 408, "pan.___", state 97, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 97, "else" + line 408, "pan.___", state 100, "(1)" + line 408, "pan.___", state 101, "(1)" + line 408, "pan.___", state 101, "(1)" + line 406, "pan.___", state 106, "((i<1))" + line 406, "pan.___", state 106, "((i>=1))" + line 413, "pan.___", state 113, "(1)" + line 413, "pan.___", state 114, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 114, "else" + line 413, "pan.___", state 117, "(1)" + line 413, "pan.___", state 118, "(1)" + line 413, "pan.___", state 118, "(1)" + line 417, "pan.___", state 126, "(1)" + line 417, "pan.___", state 127, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 127, "else" + line 417, "pan.___", state 130, "(1)" + line 417, "pan.___", state 131, "(1)" + line 417, "pan.___", state 131, "(1)" + line 415, "pan.___", state 136, "((i<2))" + line 415, "pan.___", state 136, "((i>=2))" + line 422, "pan.___", state 140, "(1)" + line 422, "pan.___", state 140, "(1)" + line 250, "pan.___", state 149, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 158, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 171, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 211, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 225, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 243, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 257, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 276, "(1)" + line 408, "pan.___", state 289, "(1)" + line 413, "pan.___", state 306, "(1)" + line 417, "pan.___", state 319, "(1)" + line 391, "pan.___", state 356, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 374, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 388, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 420, "(1)" + line 413, "pan.___", state 437, "(1)" + line 417, "pan.___", state 450, "(1)" + line 391, "pan.___", state 494, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 512, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 526, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 558, "(1)" + line 413, "pan.___", state 575, "(1)" + line 417, "pan.___", state 588, "(1)" + line 391, "pan.___", state 623, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 641, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 655, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 687, "(1)" + line 413, "pan.___", state 704, "(1)" + line 417, "pan.___", state 717, "(1)" + line 391, "pan.___", state 754, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 772, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 786, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 818, "(1)" + line 413, "pan.___", state 835, "(1)" + line 417, "pan.___", state 848, "(1)" + line 250, "pan.___", state 903, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 912, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 927, "(1)" + line 262, "pan.___", state 934, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 950, "(1)" + line 231, "pan.___", state 958, "(1)" + line 235, "pan.___", state 970, "(1)" + line 239, "pan.___", state 978, "(1)" + line 250, "pan.___", state 1009, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1018, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1031, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1040, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1056, "(1)" + line 231, "pan.___", state 1064, "(1)" + line 235, "pan.___", state 1076, "(1)" + line 239, "pan.___", state 1084, "(1)" + line 254, "pan.___", state 1110, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1123, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1132, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1148, "(1)" + line 231, "pan.___", state 1156, "(1)" + line 235, "pan.___", state 1168, "(1)" + line 239, "pan.___", state 1176, "(1)" + line 250, "pan.___", state 1207, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1216, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1229, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1238, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1254, "(1)" + line 231, "pan.___", state 1262, "(1)" + line 235, "pan.___", state 1274, "(1)" + line 239, "pan.___", state 1282, "(1)" + line 254, "pan.___", state 1308, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1321, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1330, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1346, "(1)" + line 231, "pan.___", state 1354, "(1)" + line 235, "pan.___", state 1366, "(1)" + line 239, "pan.___", state 1374, "(1)" + line 250, "pan.___", state 1405, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1414, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1427, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1436, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1452, "(1)" + line 231, "pan.___", state 1460, "(1)" + line 235, "pan.___", state 1472, "(1)" + line 239, "pan.___", state 1480, "(1)" + line 254, "pan.___", state 1506, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1519, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1528, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1544, "(1)" + line 231, "pan.___", state 1552, "(1)" + line 235, "pan.___", state 1564, "(1)" + line 239, "pan.___", state 1572, "(1)" + line 250, "pan.___", state 1603, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1612, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1625, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1634, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1650, "(1)" + line 231, "pan.___", state 1658, "(1)" + line 235, "pan.___", state 1670, "(1)" + line 239, "pan.___", state 1678, "(1)" + line 1191, "pan.___", state 1694, "-end-" + (128 of 1694 states) +unreached in proctype :init: + line 1202, "pan.___", state 9, "((j<2))" + line 1202, "pan.___", state 9, "((j>=2))" + line 1203, "pan.___", state 20, "((j<2))" + line 1203, "pan.___", state 20, "((j>=2))" + line 1208, "pan.___", state 33, "((j<2))" + line 1208, "pan.___", state 33, "((j>=2))" + line 1206, "pan.___", state 43, "((i<1))" + line 1206, "pan.___", state 43, "((i>=1))" + line 1216, "pan.___", state 54, "((j<2))" + line 1216, "pan.___", state 54, "((j>=2))" + line 1220, "pan.___", state 67, "((j<2))" + line 1220, "pan.___", state 67, "((j>=2))" + (6 of 78 states) +unreached in proctype :never: + line 1250, "pan.___", state 8, "-end-" + (1 of 8 states) + +pan: elapsed time 3.75e+03 seconds +pan: rate 2403.4695 states/second +pan: avg transition delay 1.2642e-06 usec +cp .input.spin urcu_free_no_rmb.spin.input +cp .input.spin.trail urcu_free_no_rmb.spin.input.trail +make[1]: Leaving directory `/home/compudj/doc/userspace-rcu/formal-model/urcu-controldataflow' diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_rmb.spin.input b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_rmb.spin.input new file mode 100644 index 0000000..c36940f --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_rmb.spin.input @@ -0,0 +1,1227 @@ +#define NO_RMB + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* We choose to ignore writer's non-progress caused from the + * reader ignoring the writer's mb() requests */ +#ifdef WRITER_PROGRESS +progress_writer_from_reader: +#endif + break; + od; +} + +#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: +#define PROGRESS_LABEL(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; \ + /* \ + * 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) \ + do \ + :: (reader_barrier[i] == 1) -> skip; \ + :: (reader_barrier[i] == 0) -> break; \ + od; \ + i++; \ + :: i >= NR_READERS -> \ + break \ + od; \ + smp_mb(i, j); \ +} + +#else + +#define smp_mb_send(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + :: 1 -> skip; + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_rmb.spin.input.trail b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_rmb.spin.input.trail new file mode 100644 index 0000000..abd4423 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_rmb.spin.input.trail @@ -0,0 +1,1609 @@ +-2:3:-2 +-4:-4:-4 +1:0:4812 +2:3:4732 +3:3:4735 +4:3:4735 +5:3:4738 +6:3:4746 +7:3:4746 +8:3:4749 +9:3:4755 +10:3:4759 +11:3:4759 +12:3:4762 +13:3:4772 +14:3:4780 +15:3:4780 +16:3:4783 +17:3:4789 +18:3:4793 +19:3:4793 +20:3:4796 +21:3:4802 +22:3:4806 +23:3:4807 +24:0:4812 +25:3:4809 +26:0:4812 +27:2:3040 +28:0:4812 +29:2:3046 +30:0:4812 +31:2:3047 +32:0:4812 +33:2:3049 +34:0:4812 +35:2:3050 +36:0:4812 +37:2:3051 +38:2:3052 +39:2:3056 +40:2:3057 +41:2:3065 +42:2:3066 +43:2:3070 +44:2:3071 +45:2:3079 +46:2:3084 +47:2:3088 +48:2:3089 +49:2:3097 +50:2:3098 +51:2:3102 +52:2:3103 +53:2:3097 +54:2:3098 +55:2:3102 +56:2:3103 +57:2:3111 +58:2:3116 +59:2:3117 +60:2:3128 +61:2:3129 +62:2:3130 +63:2:3141 +64:2:3146 +65:2:3147 +66:2:3158 +67:2:3159 +68:2:3160 +69:2:3158 +70:2:3159 +71:2:3160 +72:2:3171 +73:2:3179 +74:0:4812 +75:2:3050 +76:0:4812 +77:2:3183 +78:2:3187 +79:2:3188 +80:2:3192 +81:2:3196 +82:2:3197 +83:2:3201 +84:2:3209 +85:2:3210 +86:2:3214 +87:2:3218 +88:2:3219 +89:2:3214 +90:2:3215 +91:2:3223 +92:0:4812 +93:2:3050 +94:0:4812 +95:2:3231 +96:2:3232 +97:2:3233 +98:0:4812 +99:2:3050 +100:0:4812 +101:2:3238 +102:0:4812 +103:2:3941 +104:2:3942 +105:2:3946 +106:2:3950 +107:2:3951 +108:2:3955 +109:2:3960 +110:2:3968 +111:2:3972 +112:2:3973 +113:2:3968 +114:2:3972 +115:2:3973 +116:2:3977 +117:2:3984 +118:2:3991 +119:2:3992 +120:2:3999 +121:2:4004 +122:2:4011 +123:2:4012 +124:2:4011 +125:2:4012 +126:2:4019 +127:2:4023 +128:0:4812 +129:2:4028 +130:0:4812 +131:2:4029 +132:0:4812 +133:2:4030 +134:0:4812 +135:2:4031 +136:0:4812 +137:1:2 +138:0:4812 +139:2:4032 +140:0:4812 +141:1:8 +142:0:4812 +143:1:9 +144:0:4812 +145:2:4031 +146:0:4812 +147:1:10 +148:0:4812 +149:2:4032 +150:0:4812 +151:1:11 +152:0:4812 +153:2:4031 +154:0:4812 +155:1:12 +156:0:4812 +157:2:4032 +158:0:4812 +159:1:13 +160:0:4812 +161:2:4031 +162:0:4812 +163:1:14 +164:0:4812 +165:2:4032 +166:0:4812 +167:1:15 +168:0:4812 +169:1:16 +170:0:4812 +171:2:4031 +172:0:4812 +173:1:17 +174:0:4812 +175:2:4032 +176:0:4812 +177:1:28 +178:0:4812 +179:2:4031 +180:0:4812 +181:1:32 +182:1:33 +183:1:37 +184:1:41 +185:1:42 +186:1:46 +187:1:54 +188:1:55 +189:1:59 +190:1:63 +191:1:64 +192:1:59 +193:1:63 +194:1:64 +195:1:68 +196:1:75 +197:1:82 +198:1:83 +199:1:90 +200:1:95 +201:1:102 +202:1:103 +203:1:102 +204:1:103 +205:1:110 +206:1:114 +207:0:4812 +208:2:4032 +209:0:4812 +210:1:119 +211:0:4812 +212:2:4033 +213:0:4812 +214:2:4038 +215:0:4812 +216:2:4039 +217:0:4812 +218:2:4047 +219:2:4048 +220:2:4052 +221:2:4056 +222:2:4057 +223:2:4061 +224:2:4069 +225:2:4070 +226:2:4074 +227:2:4078 +228:2:4079 +229:2:4074 +230:2:4078 +231:2:4079 +232:2:4083 +233:2:4090 +234:2:4097 +235:2:4098 +236:2:4105 +237:2:4110 +238:2:4117 +239:2:4118 +240:2:4117 +241:2:4118 +242:2:4125 +243:2:4129 +244:0:4812 +245:2:3240 +246:2:3922 +247:0:4812 +248:2:3050 +249:0:4812 +250:2:3241 +251:0:4812 +252:2:3050 +253:0:4812 +254:2:3244 +255:2:3245 +256:2:3249 +257:2:3250 +258:2:3258 +259:2:3259 +260:2:3263 +261:2:3264 +262:2:3272 +263:2:3277 +264:2:3281 +265:2:3282 +266:2:3290 +267:2:3291 +268:2:3295 +269:2:3296 +270:2:3290 +271:2:3291 +272:2:3295 +273:2:3296 +274:2:3304 +275:2:3309 +276:2:3310 +277:2:3321 +278:2:3322 +279:2:3323 +280:2:3334 +281:2:3339 +282:2:3340 +283:2:3351 +284:2:3352 +285:2:3353 +286:2:3351 +287:2:3352 +288:2:3353 +289:2:3364 +290:2:3371 +291:0:4812 +292:2:3050 +293:0:4812 +294:2:3375 +295:2:3376 +296:2:3377 +297:2:3389 +298:2:3390 +299:2:3394 +300:2:3395 +301:2:3403 +302:2:3408 +303:2:3412 +304:2:3413 +305:2:3421 +306:2:3422 +307:2:3426 +308:2:3427 +309:2:3421 +310:2:3422 +311:2:3426 +312:2:3427 +313:2:3435 +314:2:3440 +315:2:3441 +316:2:3452 +317:2:3453 +318:2:3454 +319:2:3465 +320:2:3470 +321:2:3471 +322:2:3482 +323:2:3483 +324:2:3484 +325:2:3482 +326:2:3483 +327:2:3484 +328:2:3495 +329:2:3506 +330:2:3507 +331:0:4812 +332:2:3050 +333:0:4812 +334:2:3513 +335:2:3514 +336:2:3518 +337:2:3519 +338:2:3527 +339:2:3528 +340:2:3532 +341:2:3533 +342:2:3541 +343:2:3546 +344:2:3550 +345:2:3551 +346:2:3559 +347:2:3560 +348:2:3564 +349:2:3565 +350:2:3559 +351:2:3560 +352:2:3564 +353:2:3565 +354:2:3573 +355:2:3578 +356:2:3579 +357:2:3590 +358:2:3591 +359:2:3592 +360:2:3603 +361:2:3608 +362:2:3609 +363:2:3620 +364:2:3621 +365:2:3622 +366:2:3620 +367:2:3621 +368:2:3622 +369:2:3633 +370:0:4812 +371:2:3050 +372:0:4812 +373:2:3642 +374:2:3643 +375:2:3647 +376:2:3648 +377:2:3656 +378:2:3657 +379:2:3661 +380:2:3662 +381:2:3670 +382:2:3675 +383:2:3679 +384:2:3680 +385:2:3688 +386:2:3689 +387:2:3693 +388:2:3694 +389:2:3688 +390:2:3689 +391:2:3693 +392:2:3694 +393:2:3702 +394:2:3707 +395:2:3708 +396:2:3719 +397:2:3720 +398:2:3721 +399:2:3732 +400:2:3737 +401:2:3738 +402:2:3749 +403:2:3750 +404:2:3751 +405:2:3749 +406:2:3750 +407:2:3751 +408:2:3762 +409:2:3769 +410:0:4812 +411:2:3050 +412:0:4812 +413:2:3773 +414:2:3774 +415:2:3775 +416:2:3787 +417:2:3788 +418:2:3792 +419:2:3793 +420:2:3801 +421:2:3806 +422:2:3810 +423:2:3811 +424:2:3819 +425:2:3820 +426:2:3824 +427:2:3825 +428:2:3819 +429:2:3820 +430:2:3824 +431:2:3825 +432:2:3833 +433:2:3838 +434:2:3839 +435:2:3850 +436:2:3851 +437:2:3852 +438:2:3863 +439:2:3868 +440:2:3869 +441:2:3880 +442:2:3881 +443:2:3882 +444:2:3880 +445:2:3881 +446:2:3882 +447:2:3893 +448:2:3903 +449:2:3904 +450:0:4812 +451:2:3050 +452:0:4812 +453:2:3910 +454:0:4812 +455:2:4535 +456:2:4536 +457:2:4540 +458:2:4544 +459:2:4545 +460:2:4549 +461:2:4557 +462:2:4558 +463:2:4562 +464:2:4566 +465:2:4567 +466:2:4562 +467:2:4566 +468:2:4567 +469:2:4571 +470:2:4578 +471:2:4585 +472:2:4586 +473:2:4593 +474:2:4598 +475:2:4605 +476:2:4606 +477:2:4605 +478:2:4606 +479:2:4613 +480:2:4617 +481:0:4812 +482:2:4622 +483:0:4812 +484:2:4623 +485:0:4812 +486:2:4624 +487:0:4812 +488:2:4625 +489:0:4812 +490:1:28 +491:0:4812 +492:2:4626 +493:0:4812 +494:1:32 +495:1:33 +496:1:37 +497:1:41 +498:1:42 +499:1:46 +500:1:54 +501:1:55 +502:1:59 +503:1:63 +504:1:64 +505:1:59 +506:1:63 +507:1:64 +508:1:68 +509:1:75 +510:1:82 +511:1:83 +512:1:90 +513:1:95 +514:1:102 +515:1:103 +516:1:102 +517:1:103 +518:1:110 +519:1:114 +520:0:4812 +521:2:4625 +522:0:4812 +523:1:119 +524:0:4812 +525:2:4626 +526:0:4812 +527:2:4627 +528:0:4812 +529:2:4632 +530:0:4812 +531:2:4633 +532:0:4812 +533:2:4641 +534:2:4642 +535:2:4646 +536:2:4650 +537:2:4651 +538:2:4655 +539:2:4663 +540:2:4664 +541:2:4668 +542:2:4672 +543:2:4673 +544:2:4668 +545:2:4672 +546:2:4673 +547:2:4677 +548:2:4684 +549:2:4691 +550:2:4692 +551:2:4699 +552:2:4704 +553:2:4711 +554:2:4712 +555:2:4711 +556:2:4712 +557:2:4719 +558:2:4723 +559:0:4812 +560:2:3912 +561:2:3922 +562:0:4812 +563:2:3050 +564:0:4812 +565:2:3913 +566:2:3914 +567:0:4812 +568:2:3050 +569:0:4812 +570:2:3918 +571:0:4812 +572:2:3926 +573:0:4812 +574:2:3047 +575:0:4812 +576:2:3049 +577:0:4812 +578:2:3050 +579:0:4812 +580:2:3051 +581:2:3052 +582:2:3056 +583:2:3057 +584:2:3065 +585:2:3066 +586:2:3070 +587:2:3071 +588:2:3079 +589:2:3084 +590:2:3088 +591:2:3089 +592:2:3097 +593:2:3098 +594:2:3099 +595:2:3097 +596:2:3098 +597:2:3102 +598:2:3103 +599:2:3111 +600:2:3116 +601:2:3117 +602:2:3128 +603:2:3129 +604:2:3130 +605:2:3141 +606:2:3146 +607:2:3147 +608:2:3158 +609:2:3159 +610:2:3160 +611:2:3158 +612:2:3159 +613:2:3160 +614:2:3171 +615:2:3179 +616:0:4812 +617:2:3050 +618:0:4812 +619:2:3183 +620:2:3187 +621:2:3188 +622:2:3192 +623:2:3196 +624:2:3197 +625:2:3201 +626:2:3209 +627:2:3210 +628:2:3214 +629:2:3215 +630:2:3214 +631:2:3218 +632:2:3219 +633:2:3223 +634:0:4812 +635:2:3050 +636:0:4812 +637:2:3231 +638:2:3232 +639:2:3233 +640:0:4812 +641:2:3050 +642:0:4812 +643:2:3238 +644:0:4812 +645:2:3941 +646:2:3942 +647:2:3946 +648:2:3950 +649:2:3951 +650:2:3955 +651:2:3960 +652:2:3968 +653:2:3972 +654:2:3973 +655:2:3968 +656:2:3972 +657:2:3973 +658:2:3977 +659:2:3984 +660:2:3991 +661:2:3992 +662:2:3999 +663:2:4004 +664:2:4011 +665:2:4012 +666:2:4011 +667:2:4012 +668:2:4019 +669:2:4023 +670:0:4812 +671:2:4028 +672:0:4812 +673:2:4029 +674:0:4812 +675:2:4030 +676:0:4812 +677:2:4031 +678:0:4812 +679:1:28 +680:0:4812 +681:2:4032 +682:0:4812 +683:1:32 +684:1:33 +685:1:37 +686:1:41 +687:1:42 +688:1:46 +689:1:54 +690:1:55 +691:1:59 +692:1:63 +693:1:64 +694:1:59 +695:1:63 +696:1:64 +697:1:68 +698:1:75 +699:1:82 +700:1:83 +701:1:90 +702:1:95 +703:1:102 +704:1:103 +705:1:102 +706:1:103 +707:1:110 +708:1:114 +709:0:4812 +710:2:4031 +711:0:4812 +712:1:119 +713:0:4812 +714:2:4032 +715:0:4812 +716:2:4033 +717:0:4812 +718:2:4038 +719:0:4812 +720:2:4039 +721:0:4812 +722:2:4047 +723:2:4048 +724:2:4052 +725:2:4056 +726:2:4057 +727:2:4061 +728:2:4069 +729:2:4070 +730:2:4074 +731:2:4078 +732:2:4079 +733:2:4074 +734:2:4078 +735:2:4079 +736:2:4083 +737:2:4090 +738:2:4097 +739:2:4098 +740:2:4105 +741:2:4110 +742:2:4117 +743:2:4118 +744:2:4117 +745:2:4118 +746:2:4125 +747:2:4129 +748:0:4812 +749:2:3240 +750:2:3922 +751:0:4812 +752:2:3050 +753:0:4812 +754:2:3241 +755:0:4812 +756:2:3050 +757:0:4812 +758:2:3244 +759:2:3245 +760:2:3249 +761:2:3250 +762:2:3258 +763:2:3259 +764:2:3263 +765:2:3264 +766:2:3272 +767:2:3277 +768:2:3281 +769:2:3282 +770:2:3290 +771:2:3291 +772:2:3295 +773:2:3296 +774:2:3290 +775:2:3291 +776:2:3295 +777:2:3296 +778:2:3304 +779:2:3309 +780:2:3310 +781:2:3321 +782:2:3322 +783:2:3323 +784:2:3334 +785:2:3339 +786:2:3340 +787:2:3351 +788:2:3352 +789:2:3353 +790:2:3351 +791:2:3352 +792:2:3353 +793:2:3364 +794:2:3371 +795:0:4812 +796:2:3050 +797:0:4812 +798:2:3375 +799:2:3376 +800:2:3377 +801:2:3389 +802:2:3390 +803:2:3394 +804:2:3395 +805:2:3403 +806:2:3408 +807:2:3412 +808:2:3413 +809:2:3421 +810:2:3422 +811:2:3426 +812:2:3427 +813:2:3421 +814:2:3422 +815:2:3426 +816:2:3427 +817:2:3435 +818:2:3440 +819:2:3441 +820:2:3452 +821:2:3453 +822:2:3454 +823:2:3465 +824:2:3470 +825:2:3471 +826:2:3482 +827:2:3483 +828:2:3484 +829:2:3482 +830:2:3483 +831:2:3484 +832:2:3495 +833:2:3506 +834:2:3507 +835:0:4812 +836:2:3050 +837:0:4812 +838:2:3513 +839:2:3514 +840:2:3518 +841:2:3519 +842:2:3527 +843:2:3528 +844:2:3532 +845:2:3533 +846:2:3541 +847:2:3546 +848:2:3550 +849:2:3551 +850:2:3559 +851:2:3560 +852:2:3564 +853:2:3565 +854:2:3559 +855:2:3560 +856:2:3564 +857:2:3565 +858:2:3573 +859:2:3578 +860:2:3579 +861:2:3590 +862:2:3591 +863:2:3592 +864:2:3603 +865:2:3608 +866:2:3609 +867:2:3620 +868:2:3621 +869:2:3622 +870:2:3620 +871:2:3621 +872:2:3622 +873:2:3633 +874:0:4812 +875:2:3050 +876:0:4812 +877:2:3642 +878:2:3643 +879:2:3647 +880:2:3648 +881:2:3656 +882:2:3657 +883:2:3661 +884:2:3662 +885:2:3670 +886:2:3675 +887:2:3679 +888:2:3680 +889:2:3688 +890:2:3689 +891:2:3693 +892:2:3694 +893:2:3688 +894:2:3689 +895:2:3693 +896:2:3694 +897:2:3702 +898:2:3707 +899:2:3708 +900:2:3719 +901:2:3720 +902:2:3721 +903:2:3732 +904:2:3737 +905:2:3738 +906:2:3749 +907:2:3750 +908:2:3751 +909:2:3749 +910:2:3750 +911:2:3751 +912:2:3762 +913:2:3769 +914:0:4812 +915:2:3050 +916:0:4812 +917:2:3773 +918:2:3774 +919:2:3775 +920:2:3787 +921:2:3788 +922:2:3792 +923:2:3793 +924:2:3801 +925:2:3806 +926:2:3810 +927:2:3811 +928:2:3819 +929:2:3820 +930:2:3824 +931:2:3825 +932:2:3819 +933:2:3820 +934:2:3824 +935:2:3825 +936:2:3833 +937:2:3838 +938:2:3839 +939:2:3850 +940:2:3851 +941:2:3852 +942:2:3863 +943:2:3868 +944:2:3869 +945:2:3880 +946:2:3881 +947:2:3882 +948:2:3880 +949:2:3881 +950:2:3882 +951:2:3893 +952:2:3903 +953:2:3904 +954:0:4812 +955:2:3050 +956:0:4812 +957:2:3910 +958:0:4812 +959:2:4535 +960:2:4536 +961:2:4540 +962:2:4544 +963:2:4545 +964:2:4549 +965:2:4557 +966:2:4558 +967:2:4562 +968:2:4566 +969:2:4567 +970:2:4562 +971:2:4566 +972:2:4567 +973:2:4571 +974:2:4578 +975:2:4585 +976:2:4586 +977:2:4593 +978:2:4598 +979:2:4605 +980:2:4606 +981:2:4605 +982:2:4606 +983:2:4613 +984:2:4617 +985:0:4812 +986:2:4622 +987:0:4812 +988:2:4623 +989:0:4812 +990:2:4624 +991:0:4812 +992:2:4625 +993:0:4812 +994:1:28 +995:0:4812 +996:2:4626 +997:0:4812 +998:1:32 +999:1:33 +1000:1:37 +1001:1:41 +1002:1:42 +1003:1:46 +1004:1:54 +1005:1:55 +1006:1:59 +1007:1:63 +1008:1:64 +1009:1:59 +1010:1:63 +1011:1:64 +1012:1:68 +1013:1:75 +1014:1:82 +1015:1:83 +1016:1:90 +1017:1:95 +1018:1:102 +1019:1:103 +1020:1:102 +1021:1:103 +1022:1:110 +1023:1:114 +1024:0:4812 +1025:2:4625 +1026:0:4812 +1027:1:119 +1028:0:4812 +1029:2:4626 +1030:0:4812 +1031:2:4627 +1032:0:4812 +1033:2:4632 +1034:0:4812 +1035:2:4633 +1036:0:4812 +1037:2:4641 +1038:2:4642 +1039:2:4646 +1040:2:4650 +1041:2:4651 +1042:2:4655 +1043:2:4663 +1044:2:4664 +1045:2:4668 +1046:2:4672 +1047:2:4673 +1048:2:4668 +1049:2:4672 +1050:2:4673 +1051:2:4677 +1052:2:4684 +1053:2:4691 +1054:2:4692 +1055:2:4699 +1056:2:4704 +1057:2:4711 +1058:2:4712 +1059:2:4711 +1060:2:4712 +1061:2:4719 +1062:2:4723 +1063:0:4812 +1064:2:3912 +1065:2:3922 +1066:0:4812 +1067:2:3050 +1068:0:4812 +1069:2:3913 +1070:2:3914 +1071:0:4812 +1072:2:3050 +1073:0:4812 +1074:2:3918 +1075:0:4812 +1076:2:3926 +1077:0:4812 +1078:2:3047 +1079:0:4812 +1080:2:3049 +1081:0:4812 +1082:2:3050 +1083:0:4812 +1084:2:3051 +1085:2:3052 +1086:2:3056 +1087:2:3057 +1088:2:3065 +1089:2:3066 +1090:2:3070 +1091:2:3071 +1092:2:3079 +1093:2:3084 +1094:2:3088 +1095:2:3089 +1096:2:3097 +1097:2:3098 +1098:2:3102 +1099:2:3103 +1100:2:3097 +1101:2:3098 +1102:2:3099 +1103:2:3111 +1104:2:3116 +1105:2:3117 +1106:2:3128 +1107:2:3129 +1108:2:3130 +1109:2:3141 +1110:2:3146 +1111:2:3147 +1112:2:3158 +1113:2:3159 +1114:2:3160 +1115:2:3158 +1116:2:3159 +1117:2:3160 +1118:2:3171 +1119:2:3179 +1120:0:4812 +1121:2:3050 +1122:0:4812 +1123:1:120 +1124:0:4812 +1125:1:19 +1126:0:4812 +1127:1:127 +1128:1:128 +1129:1:132 +1130:1:133 +1131:1:141 +1132:1:142 +1133:1:146 +1134:1:147 +1135:1:155 +1136:1:160 +1137:1:164 +1138:1:165 +1139:1:173 +1140:1:174 +1141:1:178 +1142:1:179 +1143:1:173 +1144:1:174 +1145:1:178 +1146:1:179 +1147:1:187 +1148:1:192 +1149:1:193 +1150:1:204 +1151:1:205 +1152:1:206 +1153:1:217 +1154:1:222 +1155:1:223 +1156:1:234 +1157:1:235 +1158:1:236 +1159:1:234 +1160:1:235 +1161:1:236 +1162:1:247 +1163:0:4812 +1164:1:15 +1165:0:4812 +1166:1:16 +1167:0:4812 +1168:2:3183 +1169:2:3187 +1170:2:3188 +1171:2:3192 +1172:2:3196 +1173:2:3197 +1174:2:3201 +1175:2:3209 +1176:2:3210 +1177:2:3214 +1178:2:3218 +1179:2:3219 +1180:2:3214 +1181:2:3215 +1182:2:3223 +1183:0:4812 +1184:2:3050 +1185:0:4812 +1186:2:3231 +1187:2:3232 +1188:2:3233 +1189:0:4812 +1190:2:3050 +1191:0:4812 +1192:2:3238 +1193:0:4812 +1194:2:3941 +1195:2:3942 +1196:2:3946 +1197:2:3950 +1198:2:3951 +1199:2:3955 +1200:2:3960 +1201:2:3968 +1202:2:3972 +1203:2:3973 +1204:2:3968 +1205:2:3972 +1206:2:3973 +1207:2:3977 +1208:2:3984 +1209:2:3991 +1210:2:3992 +1211:2:3999 +1212:2:4004 +1213:2:4011 +1214:2:4012 +1215:2:4011 +1216:2:4012 +1217:2:4019 +1218:2:4023 +1219:0:4812 +1220:2:4028 +1221:0:4812 +1222:2:4029 +1223:0:4812 +1224:2:4030 +1225:0:4812 +1226:2:4031 +1227:0:4812 +1228:1:17 +1229:0:4812 +1230:2:4032 +1231:0:4812 +1232:1:120 +1233:0:4812 +1234:2:4031 +1235:0:4812 +1236:1:19 +1237:0:4812 +1238:2:4032 +1239:0:4812 +1240:1:256 +1241:1:257 +1242:0:4812 +1243:1:15 +1244:0:4812 +1245:1:16 +1246:0:4812 +1247:2:4031 +1248:0:4812 +1249:1:17 +1250:0:4812 +1251:2:4032 +1252:0:4812 +1253:1:120 +1254:0:4812 +1255:2:4031 +1256:0:4812 +1257:1:19 +1258:0:4812 +1259:2:4032 +1260:0:4812 +1261:1:263 +1262:1:264 +1263:1:268 +1264:1:269 +1265:1:277 +1266:1:278 +1267:1:282 +1268:1:283 +1269:1:291 +1270:1:296 +1271:1:300 +1272:1:301 +1273:1:309 +1274:1:310 +1275:1:314 +1276:1:315 +1277:1:309 +1278:1:310 +1279:1:314 +1280:1:315 +1281:1:323 +1282:1:328 +1283:1:329 +1284:1:340 +1285:1:341 +1286:1:342 +1287:1:353 +1288:1:358 +1289:1:359 +1290:1:370 +1291:1:371 +1292:1:372 +1293:1:370 +1294:1:378 +1295:1:379 +1296:1:383 +1297:0:4812 +1298:1:15 +1299:0:4812 +1300:1:16 +1301:0:4812 +1302:2:4031 +1303:0:4812 +1304:1:17 +1305:0:4812 +1306:2:4032 +1307:0:4812 +1308:1:120 +1309:0:4812 +1310:2:4031 +1311:0:4812 +1312:1:19 +1313:0:4812 +1314:2:4032 +1315:0:4812 +1316:1:392 +1317:1:393 +1318:1:397 +1319:1:398 +1320:1:406 +1321:1:407 +1322:1:411 +1323:1:412 +1324:1:420 +1325:1:425 +1326:1:429 +1327:1:430 +1328:1:438 +1329:1:439 +1330:1:443 +1331:1:444 +1332:1:438 +1333:1:439 +1334:1:443 +1335:1:444 +1336:1:452 +1337:1:457 +1338:1:458 +1339:1:469 +1340:1:470 +1341:1:471 +1342:1:482 +1343:1:487 +1344:1:488 +1345:1:499 +1346:1:500 +1347:1:501 +1348:1:499 +1349:1:507 +1350:1:508 +1351:1:512 +1352:1:519 +1353:0:4812 +1354:1:15 +1355:0:4812 +1356:1:16 +1357:0:4812 +1358:2:4031 +1359:0:4812 +1360:1:17 +1361:0:4812 +1362:2:4032 +1363:0:4812 +1364:1:120 +1365:0:4812 +1366:2:4031 +1367:0:4812 +1368:1:19 +1369:0:4812 +1370:2:4032 +1371:0:4812 +1372:1:657 +1373:1:658 +1374:1:662 +1375:1:663 +1376:1:671 +1377:1:672 +1378:1:673 +1379:1:685 +1380:1:690 +1381:1:694 +1382:1:695 +1383:1:703 +1384:1:704 +1385:1:708 +1386:1:709 +1387:1:703 +1388:1:704 +1389:1:708 +1390:1:709 +1391:1:717 +1392:1:722 +1393:1:723 +1394:1:734 +1395:1:735 +1396:1:736 +1397:1:747 +1398:1:752 +1399:1:753 +1400:1:764 +1401:1:765 +1402:1:766 +1403:1:764 +1404:1:772 +1405:1:773 +1406:1:777 +1407:0:4812 +1408:1:15 +1409:0:4812 +1410:1:16 +1411:0:4812 +1412:2:4031 +1413:0:4812 +1414:1:17 +1415:0:4812 +1416:2:4032 +1417:0:4812 +1418:1:120 +1419:0:4812 +1420:2:4031 +1421:0:4812 +1422:1:19 +1423:0:4812 +1424:2:4032 +1425:0:4812 +1426:1:786 +1427:1:789 +1428:1:790 +1429:0:4812 +1430:1:15 +1431:0:4812 +1432:1:16 +1433:0:4812 +1434:2:4031 +1435:0:4812 +1436:1:17 +1437:0:4812 +1438:2:4032 +1439:0:4812 +1440:1:120 +1441:0:4812 +1442:2:4031 +1443:0:4812 +1444:1:19 +1445:0:4812 +1446:2:4032 +1447:0:4812 +1448:1:1053 +1449:1:1054 +1450:1:1058 +1451:1:1059 +1452:1:1067 +1453:1:1068 +1454:1:1072 +1455:1:1073 +1456:1:1081 +1457:1:1086 +1458:1:1090 +1459:1:1091 +1460:1:1099 +1461:1:1100 +1462:1:1104 +1463:1:1105 +1464:1:1099 +1465:1:1100 +1466:1:1104 +1467:1:1105 +1468:1:1113 +1469:1:1118 +1470:1:1119 +1471:1:1130 +1472:1:1131 +1473:1:1132 +1474:1:1143 +1475:1:1148 +1476:1:1149 +1477:1:1160 +1478:1:1161 +1479:1:1162 +1480:1:1160 +1481:1:1168 +1482:1:1169 +1483:1:1173 +1484:1:1180 +1485:1:1184 +1486:0:4812 +1487:1:15 +1488:0:4812 +1489:1:16 +1490:0:4812 +1491:2:4031 +1492:0:4812 +1493:1:17 +1494:0:4812 +1495:2:4032 +1496:0:4812 +1497:1:120 +1498:0:4812 +1499:2:4031 +1500:0:4812 +1501:1:19 +1502:0:4812 +1503:2:4032 +1504:0:4812 +1505:1:1185 +1506:1:1186 +1507:1:1190 +1508:1:1191 +1509:1:1199 +1510:1:1200 +1511:1:1201 +1512:1:1213 +1513:1:1218 +1514:1:1222 +1515:1:1223 +1516:1:1231 +1517:1:1232 +1518:1:1236 +1519:1:1237 +1520:1:1231 +1521:1:1232 +1522:1:1236 +1523:1:1237 +1524:1:1245 +1525:1:1250 +1526:1:1251 +1527:1:1262 +1528:1:1263 +1529:1:1264 +1530:1:1275 +1531:1:1280 +1532:1:1281 +1533:1:1292 +1534:1:1293 +1535:1:1294 +1536:1:1292 +1537:1:1300 +1538:1:1301 +1539:1:1305 +1540:0:4812 +1541:1:15 +1542:0:4812 +1543:1:16 +1544:0:4812 +1545:2:4031 +1546:0:4812 +1547:1:17 +1548:0:4812 +1549:2:4032 +1550:0:4812 +1551:1:120 +1552:0:4812 +1553:2:4031 +1554:0:4812 +1555:1:19 +1556:0:4812 +1557:2:4032 +1558:0:4812 +1559:1:1314 +1560:0:4812 +1561:2:4031 +1562:0:4812 +1563:1:2778 +1564:1:2782 +1565:1:2783 +1566:1:2791 +1567:1:2792 +1568:1:2796 +1569:1:2797 +1570:1:2805 +1571:1:2810 +1572:1:2814 +1573:1:2815 +1574:1:2823 +1575:1:2824 +1576:1:2828 +1577:1:2829 +1578:1:2823 +1579:1:2824 +1580:1:2828 +1581:1:2829 +1582:1:2837 +1583:1:2842 +1584:1:2843 +1585:1:2854 +1586:1:2855 +1587:1:2856 +1588:1:2867 +1589:1:2872 +1590:1:2873 +1591:1:2884 +1592:1:2885 +1593:1:2886 +1594:1:2884 +1595:1:2892 +1596:1:2893 +1597:1:2897 +1598:1:2901 +1599:0:4812 +1600:2:4032 +1601:0:4812 +1602:1:1316 +1603:1:1317 +1604:0:4810 +1605:1:15 +1606:0:4816 +1607:1:1637 diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_wmb.define b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_wmb.define new file mode 100644 index 0000000..710f29d --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_wmb.define @@ -0,0 +1 @@ +#define NO_WMB diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_wmb.log b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_wmb.log new file mode 100644 index 0000000..e829e4b --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_wmb.log @@ -0,0 +1,613 @@ +make[1]: Entering directory `/home/compudj/doc/userspace-rcu/formal-model/urcu-controldataflow' +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define >> pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_free.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_free_no_wmb.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1245) +Depth= 8041 States= 1e+06 Transitions= 1.63e+08 Memory= 550.432 t= 203 R= 5e+03 +Depth= 9655 States= 2e+06 Transitions= 3.34e+08 Memory= 634.318 t= 424 R= 5e+03 +Depth= 9655 States= 3e+06 Transitions= 5.11e+08 Memory= 718.303 t= 654 R= 5e+03 +pan: resizing hashtable to -w22.. done +Depth= 9655 States= 4e+06 Transitions= 6.76e+08 Memory= 833.311 t= 861 R= 5e+03 +Depth= 9655 States= 5e+06 Transitions= 9e+08 Memory= 917.295 t= 1.15e+03 R= 4e+03 +Depth= 9655 States= 6e+06 Transitions= 1.34e+09 Memory= 1001.279 t= 1.71e+03 R= 3e+03 +Depth= 9655 States= 7e+06 Transitions= 1.71e+09 Memory= 1085.264 t= 2.2e+03 R= 3e+03 +Depth= 9655 States= 8e+06 Transitions= 2.07e+09 Memory= 1169.151 t= 2.68e+03 R= 3e+03 +Depth= 9655 States= 9e+06 Transitions= 2.39e+09 Memory= 1253.135 t= 3.11e+03 R= 3e+03 +pan: resizing hashtable to -w24.. done +Depth= 9655 States= 1e+07 Transitions= 2.56e+09 Memory= 1461.115 t= 3.32e+03 R= 3e+03 +Depth= 9655 States= 1.1e+07 Transitions= 2.73e+09 Memory= 1545.100 t= 3.53e+03 R= 3e+03 +Depth= 9655 States= 1.2e+07 Transitions= 2.93e+09 Memory= 1629.084 t= 3.78e+03 R= 3e+03 +Depth= 9655 States= 1.3e+07 Transitions= 3.09e+09 Memory= 1713.068 t= 3.99e+03 R= 3e+03 +Depth= 9655 States= 1.4e+07 Transitions= 3.27e+09 Memory= 1797.053 t= 4.22e+03 R= 3e+03 +Depth= 9655 States= 1.5e+07 Transitions= 3.7e+09 Memory= 1881.037 t= 4.77e+03 R= 3e+03 +Depth= 9655 States= 1.6e+07 Transitions= 4.11e+09 Memory= 1964.924 t= 5.32e+03 R= 3e+03 +Depth= 9655 States= 1.7e+07 Transitions= 4.42e+09 Memory= 2048.908 t= 5.72e+03 R= 3e+03 +Depth= 9655 States= 1.8e+07 Transitions= 4.62e+09 Memory= 2132.893 t= 5.98e+03 R= 3e+03 +Depth= 9655 States= 1.9e+07 Transitions= 4.92e+09 Memory= 2216.877 t= 6.35e+03 R= 3e+03 +Depth= 9655 States= 2e+07 Transitions= 5.24e+09 Memory= 2300.861 t= 6.77e+03 R= 3e+03 +Depth= 9655 States= 2.1e+07 Transitions= 5.94e+09 Memory= 2384.846 t= 7.68e+03 R= 3e+03 +Depth= 9655 States= 2.2e+07 Transitions= 6.65e+09 Memory= 2468.830 t= 8.63e+03 R= 3e+03 +Depth= 9655 States= 2.3e+07 Transitions= 7.1e+09 Memory= 2552.717 t= 9.22e+03 R= 2e+03 +Depth= 9655 States= 2.4e+07 Transitions= 7.54e+09 Memory= 2636.701 t= 9.8e+03 R= 2e+03 +Depth= 9655 States= 2.5e+07 Transitions= 7.74e+09 Memory= 2720.686 t= 1.01e+04 R= 2e+03 +Depth= 9655 States= 2.6e+07 Transitions= 8.03e+09 Memory= 2804.670 t= 1.04e+04 R= 2e+03 +Depth= 9655 States= 2.7e+07 Transitions= 8.4e+09 Memory= 2888.654 t= 1.09e+04 R= 2e+03 +Depth= 9655 States= 2.8e+07 Transitions= 9.12e+09 Memory= 2972.639 t= 1.19e+04 R= 2e+03 +Depth= 9655 States= 2.9e+07 Transitions= 9.83e+09 Memory= 3056.526 t= 1.29e+04 R= 2e+03 +Depth= 9655 States= 3e+07 Transitions= 1.02e+10 Memory= 3140.510 t= 1.33e+04 R= 2e+03 +Depth= 9655 States= 3.1e+07 Transitions= 1.04e+10 Memory= 3224.494 t= 1.36e+04 R= 2e+03 +Depth= 9655 States= 3.2e+07 Transitions= 1.08e+10 Memory= 3308.479 t= 1.42e+04 R= 2e+03 +Depth= 9655 States= 3.3e+07 Transitions= 1.12e+10 Memory= 3392.463 t= 1.48e+04 R= 2e+03 +Depth= 9655 States= 3.4e+07 Transitions= 1.17e+10 Memory= 3476.447 t= 1.54e+04 R= 2e+03 +pan: resizing hashtable to -w26.. done +Depth= 9655 States= 3.5e+07 Transitions= 1.2e+10 Memory= 4056.416 t= 1.58e+04 R= 2e+03 +Depth= 9693 States= 3.6e+07 Transitions= 1.24e+10 Memory= 4140.401 t= 1.62e+04 R= 2e+03 +Depth= 9693 States= 3.7e+07 Transitions= 1.26e+10 Memory= 4224.385 t= 1.65e+04 R= 2e+03 +Depth= 9693 States= 3.8e+07 Transitions= 1.29e+10 Memory= 4308.369 t= 1.69e+04 R= 2e+03 +Depth= 9693 States= 3.9e+07 Transitions= 1.31e+10 Memory= 4392.354 t= 1.72e+04 R= 2e+03 +Depth= 9693 States= 4e+07 Transitions= 1.34e+10 Memory= 4476.338 t= 1.75e+04 R= 2e+03 +Depth= 9693 States= 4.1e+07 Transitions= 1.36e+10 Memory= 4560.225 t= 1.79e+04 R= 2e+03 +Depth= 9693 States= 4.2e+07 Transitions= 1.39e+10 Memory= 4644.209 t= 1.82e+04 R= 2e+03 +Depth= 9693 States= 4.3e+07 Transitions= 1.41e+10 Memory= 4728.193 t= 1.85e+04 R= 2e+03 +Depth= 9693 States= 4.4e+07 Transitions= 1.44e+10 Memory= 4812.178 t= 1.88e+04 R= 2e+03 +Depth= 9693 States= 4.5e+07 Transitions= 1.47e+10 Memory= 4896.162 t= 1.92e+04 R= 2e+03 +Depth= 9693 States= 4.6e+07 Transitions= 1.49e+10 Memory= 4980.147 t= 1.95e+04 R= 2e+03 +Depth= 9693 States= 4.7e+07 Transitions= 1.51e+10 Memory= 5064.131 t= 1.98e+04 R= 2e+03 +Depth= 9693 States= 4.8e+07 Transitions= 1.54e+10 Memory= 5148.018 t= 2.02e+04 R= 2e+03 +Depth= 9693 States= 4.9e+07 Transitions= 1.56e+10 Memory= 5232.002 t= 2.05e+04 R= 2e+03 +Depth= 9693 States= 5e+07 Transitions= 1.59e+10 Memory= 5315.986 t= 2.07e+04 R= 2e+03 +Depth= 9693 States= 5.1e+07 Transitions= 1.61e+10 Memory= 5399.971 t= 2.11e+04 R= 2e+03 +Depth= 9693 States= 5.2e+07 Transitions= 1.65e+10 Memory= 5483.955 t= 2.16e+04 R= 2e+03 +Depth= 9693 States= 5.3e+07 Transitions= 1.69e+10 Memory= 5567.940 t= 2.22e+04 R= 2e+03 +Depth= 9693 States= 5.4e+07 Transitions= 1.73e+10 Memory= 5651.826 t= 2.26e+04 R= 2e+03 +Depth= 9693 States= 5.5e+07 Transitions= 1.78e+10 Memory= 5735.811 t= 2.33e+04 R= 2e+03 +Depth= 9693 States= 5.6e+07 Transitions= 1.82e+10 Memory= 5819.795 t= 2.37e+04 R= 2e+03 +Depth= 9693 States= 5.7e+07 Transitions= 1.86e+10 Memory= 5903.779 t= 2.42e+04 R= 2e+03 +Depth= 9693 States= 5.8e+07 Transitions= 1.87e+10 Memory= 5987.764 t= 2.44e+04 R= 2e+03 +Depth= 9693 States= 5.9e+07 Transitions= 1.89e+10 Memory= 6071.748 t= 2.46e+04 R= 2e+03 +Depth= 9693 States= 6e+07 Transitions= 1.91e+10 Memory= 6155.733 t= 2.49e+04 R= 2e+03 +Depth= 9693 States= 6.1e+07 Transitions= 1.92e+10 Memory= 6239.619 t= 2.51e+04 R= 2e+03 +Depth= 9693 States= 6.2e+07 Transitions= 1.95e+10 Memory= 6323.604 t= 2.54e+04 R= 2e+03 +Depth= 9693 States= 6.3e+07 Transitions= 1.99e+10 Memory= 6407.588 t= 2.6e+04 R= 2e+03 +Depth= 9693 States= 6.4e+07 Transitions= 2.03e+10 Memory= 6491.572 t= 2.64e+04 R= 2e+03 +pan: claim violated! (at depth 1464) +pan: wrote .input.spin.trail + +(Spin Version 5.1.7 -- 23 December 2008) +Warning: Search not completed + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness disabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 9693, errors: 1 + 64034146 states, stored +2.0218243e+10 states, matched +2.0282277e+10 transitions (= stored+matched) +1.1654922e+11 atomic steps +hash conflicts: 1.2215901e+10 (resolved) + +Stats on memory usage (in Megabytes): + 7083.856 equivalent memory usage for states (stored*(State-vector + overhead)) + 5527.722 actual memory usage for states (compression: 78.03%) + state-vector as stored = 63 byte + 28 byte overhead + 512.000 memory used for hash table (-w26) + 457.764 memory used for DFS stack (-m10000000) + 3.082 memory lost to fragmentation + 6494.404 total actual memory usage + +unreached in proctype urcu_reader + line 250, "pan.___", state 32, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 54, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 63, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 79, "(1)" + line 231, "pan.___", state 87, "(1)" + line 235, "pan.___", state 99, "(1)" + line 239, "pan.___", state 107, "(1)" + line 387, "pan.___", state 132, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 164, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 178, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 197, "(1)" + line 413, "pan.___", state 227, "(1)" + line 417, "pan.___", state 240, "(1)" + line 663, "pan.___", state 261, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 387, "pan.___", state 268, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 300, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 314, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 333, "(1)" + line 413, "pan.___", state 363, "(1)" + line 417, "pan.___", state 376, "(1)" + line 387, "pan.___", state 397, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 429, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 443, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 462, "(1)" + line 413, "pan.___", state 492, "(1)" + line 417, "pan.___", state 505, "(1)" + line 387, "pan.___", state 528, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 530, "(1)" + line 387, "pan.___", state 531, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 531, "else" + line 387, "pan.___", state 534, "(1)" + line 391, "pan.___", state 542, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 544, "(1)" + line 391, "pan.___", state 545, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 545, "else" + line 391, "pan.___", state 548, "(1)" + line 391, "pan.___", state 549, "(1)" + line 391, "pan.___", state 549, "(1)" + line 389, "pan.___", state 554, "((i<1))" + line 389, "pan.___", state 554, "((i>=1))" + line 396, "pan.___", state 560, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 562, "(1)" + line 396, "pan.___", state 563, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 563, "else" + line 396, "pan.___", state 566, "(1)" + line 396, "pan.___", state 567, "(1)" + line 396, "pan.___", state 567, "(1)" + line 400, "pan.___", state 574, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 576, "(1)" + line 400, "pan.___", state 577, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 577, "else" + line 400, "pan.___", state 580, "(1)" + line 400, "pan.___", state 581, "(1)" + line 400, "pan.___", state 581, "(1)" + line 398, "pan.___", state 586, "((i<2))" + line 398, "pan.___", state 586, "((i>=2))" + line 404, "pan.___", state 593, "(1)" + line 404, "pan.___", state 594, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 594, "else" + line 404, "pan.___", state 597, "(1)" + line 404, "pan.___", state 598, "(1)" + line 404, "pan.___", state 598, "(1)" + line 408, "pan.___", state 606, "(1)" + line 408, "pan.___", state 607, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 607, "else" + line 408, "pan.___", state 610, "(1)" + line 408, "pan.___", state 611, "(1)" + line 408, "pan.___", state 611, "(1)" + line 406, "pan.___", state 616, "((i<1))" + line 406, "pan.___", state 616, "((i>=1))" + line 413, "pan.___", state 623, "(1)" + line 413, "pan.___", state 624, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 624, "else" + line 413, "pan.___", state 627, "(1)" + line 413, "pan.___", state 628, "(1)" + line 413, "pan.___", state 628, "(1)" + line 417, "pan.___", state 636, "(1)" + line 417, "pan.___", state 637, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 637, "else" + line 417, "pan.___", state 640, "(1)" + line 417, "pan.___", state 641, "(1)" + line 417, "pan.___", state 641, "(1)" + line 415, "pan.___", state 646, "((i<2))" + line 415, "pan.___", state 646, "((i>=2))" + line 422, "pan.___", state 650, "(1)" + line 422, "pan.___", state 650, "(1)" + line 663, "pan.___", state 653, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 663, "pan.___", state 654, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 663, "pan.___", state 655, "(1)" + line 387, "pan.___", state 662, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 694, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 708, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 727, "(1)" + line 413, "pan.___", state 757, "(1)" + line 417, "pan.___", state 770, "(1)" + line 387, "pan.___", state 798, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 800, "(1)" + line 387, "pan.___", state 801, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 801, "else" + line 387, "pan.___", state 804, "(1)" + line 391, "pan.___", state 812, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 814, "(1)" + line 391, "pan.___", state 815, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 815, "else" + line 391, "pan.___", state 818, "(1)" + line 391, "pan.___", state 819, "(1)" + line 391, "pan.___", state 819, "(1)" + line 389, "pan.___", state 824, "((i<1))" + line 389, "pan.___", state 824, "((i>=1))" + line 396, "pan.___", state 830, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 832, "(1)" + line 396, "pan.___", state 833, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 833, "else" + line 396, "pan.___", state 836, "(1)" + line 396, "pan.___", state 837, "(1)" + line 396, "pan.___", state 837, "(1)" + line 400, "pan.___", state 844, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 846, "(1)" + line 400, "pan.___", state 847, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 847, "else" + line 400, "pan.___", state 850, "(1)" + line 400, "pan.___", state 851, "(1)" + line 400, "pan.___", state 851, "(1)" + line 398, "pan.___", state 856, "((i<2))" + line 398, "pan.___", state 856, "((i>=2))" + line 404, "pan.___", state 863, "(1)" + line 404, "pan.___", state 864, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 864, "else" + line 404, "pan.___", state 867, "(1)" + line 404, "pan.___", state 868, "(1)" + line 404, "pan.___", state 868, "(1)" + line 408, "pan.___", state 876, "(1)" + line 408, "pan.___", state 877, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 877, "else" + line 408, "pan.___", state 880, "(1)" + line 408, "pan.___", state 881, "(1)" + line 408, "pan.___", state 881, "(1)" + line 406, "pan.___", state 886, "((i<1))" + line 406, "pan.___", state 886, "((i>=1))" + line 413, "pan.___", state 893, "(1)" + line 413, "pan.___", state 894, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 894, "else" + line 413, "pan.___", state 897, "(1)" + line 413, "pan.___", state 898, "(1)" + line 413, "pan.___", state 898, "(1)" + line 417, "pan.___", state 906, "(1)" + line 417, "pan.___", state 907, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 907, "else" + line 417, "pan.___", state 910, "(1)" + line 417, "pan.___", state 911, "(1)" + line 417, "pan.___", state 911, "(1)" + line 422, "pan.___", state 920, "(1)" + line 422, "pan.___", state 920, "(1)" + line 387, "pan.___", state 927, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 929, "(1)" + line 387, "pan.___", state 930, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 930, "else" + line 387, "pan.___", state 933, "(1)" + line 391, "pan.___", state 941, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 943, "(1)" + line 391, "pan.___", state 944, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 944, "else" + line 391, "pan.___", state 947, "(1)" + line 391, "pan.___", state 948, "(1)" + line 391, "pan.___", state 948, "(1)" + line 389, "pan.___", state 953, "((i<1))" + line 389, "pan.___", state 953, "((i>=1))" + line 396, "pan.___", state 959, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 961, "(1)" + line 396, "pan.___", state 962, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 962, "else" + line 396, "pan.___", state 965, "(1)" + line 396, "pan.___", state 966, "(1)" + line 396, "pan.___", state 966, "(1)" + line 400, "pan.___", state 973, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 975, "(1)" + line 400, "pan.___", state 976, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 976, "else" + line 400, "pan.___", state 979, "(1)" + line 400, "pan.___", state 980, "(1)" + line 400, "pan.___", state 980, "(1)" + line 398, "pan.___", state 985, "((i<2))" + line 398, "pan.___", state 985, "((i>=2))" + line 404, "pan.___", state 992, "(1)" + line 404, "pan.___", state 993, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 993, "else" + line 404, "pan.___", state 996, "(1)" + line 404, "pan.___", state 997, "(1)" + line 404, "pan.___", state 997, "(1)" + line 408, "pan.___", state 1005, "(1)" + line 408, "pan.___", state 1006, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 1006, "else" + line 408, "pan.___", state 1009, "(1)" + line 408, "pan.___", state 1010, "(1)" + line 408, "pan.___", state 1010, "(1)" + line 406, "pan.___", state 1015, "((i<1))" + line 406, "pan.___", state 1015, "((i>=1))" + line 413, "pan.___", state 1022, "(1)" + line 413, "pan.___", state 1023, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 1023, "else" + line 413, "pan.___", state 1026, "(1)" + line 413, "pan.___", state 1027, "(1)" + line 413, "pan.___", state 1027, "(1)" + line 417, "pan.___", state 1035, "(1)" + line 417, "pan.___", state 1036, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 1036, "else" + line 417, "pan.___", state 1039, "(1)" + line 417, "pan.___", state 1040, "(1)" + line 417, "pan.___", state 1040, "(1)" + line 415, "pan.___", state 1045, "((i<2))" + line 415, "pan.___", state 1045, "((i>=2))" + line 422, "pan.___", state 1049, "(1)" + line 422, "pan.___", state 1049, "(1)" + line 671, "pan.___", state 1053, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 387, "pan.___", state 1058, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1090, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1104, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1123, "(1)" + line 413, "pan.___", state 1153, "(1)" + line 417, "pan.___", state 1166, "(1)" + line 387, "pan.___", state 1190, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1222, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1236, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1255, "(1)" + line 413, "pan.___", state 1285, "(1)" + line 417, "pan.___", state 1298, "(1)" + line 387, "pan.___", state 1323, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1355, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1369, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1388, "(1)" + line 413, "pan.___", state 1418, "(1)" + line 417, "pan.___", state 1431, "(1)" + line 387, "pan.___", state 1452, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1484, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1498, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1517, "(1)" + line 413, "pan.___", state 1547, "(1)" + line 417, "pan.___", state 1560, "(1)" + line 387, "pan.___", state 1586, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1618, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1632, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1651, "(1)" + line 413, "pan.___", state 1681, "(1)" + line 417, "pan.___", state 1694, "(1)" + line 387, "pan.___", state 1715, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1747, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1761, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1780, "(1)" + line 413, "pan.___", state 1810, "(1)" + line 417, "pan.___", state 1823, "(1)" + line 387, "pan.___", state 1847, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1879, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1893, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1912, "(1)" + line 413, "pan.___", state 1942, "(1)" + line 417, "pan.___", state 1955, "(1)" + line 710, "pan.___", state 1976, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 387, "pan.___", state 1983, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2015, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2029, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2048, "(1)" + line 413, "pan.___", state 2078, "(1)" + line 417, "pan.___", state 2091, "(1)" + line 387, "pan.___", state 2112, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2144, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2158, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2177, "(1)" + line 413, "pan.___", state 2207, "(1)" + line 417, "pan.___", state 2220, "(1)" + line 387, "pan.___", state 2243, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 2245, "(1)" + line 387, "pan.___", state 2246, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 2246, "else" + line 387, "pan.___", state 2249, "(1)" + line 391, "pan.___", state 2257, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 2259, "(1)" + line 391, "pan.___", state 2260, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 2260, "else" + line 391, "pan.___", state 2263, "(1)" + line 391, "pan.___", state 2264, "(1)" + line 391, "pan.___", state 2264, "(1)" + line 389, "pan.___", state 2269, "((i<1))" + line 389, "pan.___", state 2269, "((i>=1))" + line 396, "pan.___", state 2275, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2277, "(1)" + line 396, "pan.___", state 2278, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 2278, "else" + line 396, "pan.___", state 2281, "(1)" + line 396, "pan.___", state 2282, "(1)" + line 396, "pan.___", state 2282, "(1)" + line 400, "pan.___", state 2289, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2291, "(1)" + line 400, "pan.___", state 2292, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 2292, "else" + line 400, "pan.___", state 2295, "(1)" + line 400, "pan.___", state 2296, "(1)" + line 400, "pan.___", state 2296, "(1)" + line 398, "pan.___", state 2301, "((i<2))" + line 398, "pan.___", state 2301, "((i>=2))" + line 404, "pan.___", state 2308, "(1)" + line 404, "pan.___", state 2309, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 2309, "else" + line 404, "pan.___", state 2312, "(1)" + line 404, "pan.___", state 2313, "(1)" + line 404, "pan.___", state 2313, "(1)" + line 408, "pan.___", state 2321, "(1)" + line 408, "pan.___", state 2322, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 2322, "else" + line 408, "pan.___", state 2325, "(1)" + line 408, "pan.___", state 2326, "(1)" + line 408, "pan.___", state 2326, "(1)" + line 406, "pan.___", state 2331, "((i<1))" + line 406, "pan.___", state 2331, "((i>=1))" + line 413, "pan.___", state 2338, "(1)" + line 413, "pan.___", state 2339, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 2339, "else" + line 413, "pan.___", state 2342, "(1)" + line 413, "pan.___", state 2343, "(1)" + line 413, "pan.___", state 2343, "(1)" + line 417, "pan.___", state 2351, "(1)" + line 417, "pan.___", state 2352, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 2352, "else" + line 417, "pan.___", state 2355, "(1)" + line 417, "pan.___", state 2356, "(1)" + line 417, "pan.___", state 2356, "(1)" + line 415, "pan.___", state 2361, "((i<2))" + line 415, "pan.___", state 2361, "((i>=2))" + line 422, "pan.___", state 2365, "(1)" + line 422, "pan.___", state 2365, "(1)" + line 710, "pan.___", state 2368, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 710, "pan.___", state 2369, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 710, "pan.___", state 2370, "(1)" + line 387, "pan.___", state 2377, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2409, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2423, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2442, "(1)" + line 413, "pan.___", state 2472, "(1)" + line 417, "pan.___", state 2485, "(1)" + line 387, "pan.___", state 2512, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2544, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2558, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2577, "(1)" + line 413, "pan.___", state 2607, "(1)" + line 417, "pan.___", state 2620, "(1)" + line 387, "pan.___", state 2641, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2673, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2687, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2706, "(1)" + line 413, "pan.___", state 2736, "(1)" + line 417, "pan.___", state 2749, "(1)" + line 227, "pan.___", state 2782, "(1)" + line 235, "pan.___", state 2802, "(1)" + line 239, "pan.___", state 2810, "(1)" + line 227, "pan.___", state 2825, "(1)" + line 235, "pan.___", state 2845, "(1)" + line 239, "pan.___", state 2853, "(1)" + line 870, "pan.___", state 2870, "-end-" + (278 of 2870 states) +unreached in proctype urcu_writer + line 387, "pan.___", state 19, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 33, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 84, "(1)" + line 408, "pan.___", state 97, "(1)" + line 250, "pan.___", state 150, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 152, "(1)" + line 254, "pan.___", state 159, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 161, "(1)" + line 254, "pan.___", state 162, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 162, "else" + line 252, "pan.___", state 167, "((i<1))" + line 252, "pan.___", state 167, "((i>=1))" + line 258, "pan.___", state 172, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 174, "(1)" + line 258, "pan.___", state 175, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 175, "else" + line 262, "pan.___", state 181, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 183, "(1)" + line 262, "pan.___", state 184, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 184, "else" + line 267, "pan.___", state 193, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 267, "pan.___", state 193, "else" + line 387, "pan.___", state 212, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 226, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 244, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 258, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 277, "(1)" + line 408, "pan.___", state 290, "(1)" + line 413, "pan.___", state 307, "(1)" + line 417, "pan.___", state 320, "(1)" + line 391, "pan.___", state 357, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 375, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 389, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 421, "(1)" + line 413, "pan.___", state 438, "(1)" + line 417, "pan.___", state 451, "(1)" + line 391, "pan.___", state 495, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 513, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 527, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 559, "(1)" + line 413, "pan.___", state 576, "(1)" + line 417, "pan.___", state 589, "(1)" + line 391, "pan.___", state 624, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 642, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 656, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 688, "(1)" + line 413, "pan.___", state 705, "(1)" + line 417, "pan.___", state 718, "(1)" + line 391, "pan.___", state 755, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 773, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 787, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 819, "(1)" + line 413, "pan.___", state 836, "(1)" + line 417, "pan.___", state 849, "(1)" + line 250, "pan.___", state 904, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 913, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 227, "pan.___", state 951, "(1)" + line 231, "pan.___", state 959, "(1)" + line 235, "pan.___", state 971, "(1)" + line 239, "pan.___", state 979, "(1)" + line 250, "pan.___", state 1010, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1019, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1032, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1041, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1057, "(1)" + line 231, "pan.___", state 1065, "(1)" + line 235, "pan.___", state 1077, "(1)" + line 239, "pan.___", state 1085, "(1)" + line 254, "pan.___", state 1111, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1124, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1133, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1149, "(1)" + line 231, "pan.___", state 1157, "(1)" + line 235, "pan.___", state 1169, "(1)" + line 239, "pan.___", state 1177, "(1)" + line 250, "pan.___", state 1208, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1217, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1230, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1239, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1255, "(1)" + line 231, "pan.___", state 1263, "(1)" + line 235, "pan.___", state 1275, "(1)" + line 239, "pan.___", state 1283, "(1)" + line 254, "pan.___", state 1309, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1322, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1331, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1347, "(1)" + line 231, "pan.___", state 1355, "(1)" + line 235, "pan.___", state 1367, "(1)" + line 239, "pan.___", state 1375, "(1)" + line 250, "pan.___", state 1406, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1415, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1428, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1437, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1453, "(1)" + line 231, "pan.___", state 1461, "(1)" + line 235, "pan.___", state 1473, "(1)" + line 239, "pan.___", state 1481, "(1)" + line 254, "pan.___", state 1507, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1520, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1529, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1545, "(1)" + line 231, "pan.___", state 1553, "(1)" + line 235, "pan.___", state 1565, "(1)" + line 239, "pan.___", state 1573, "(1)" + line 250, "pan.___", state 1604, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1613, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1626, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1635, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1651, "(1)" + line 231, "pan.___", state 1659, "(1)" + line 235, "pan.___", state 1671, "(1)" + line 239, "pan.___", state 1679, "(1)" + line 1191, "pan.___", state 1695, "-end-" + (109 of 1695 states) +unreached in proctype :init: + line 1202, "pan.___", state 9, "((j<2))" + line 1202, "pan.___", state 9, "((j>=2))" + line 1203, "pan.___", state 20, "((j<2))" + line 1203, "pan.___", state 20, "((j>=2))" + line 1208, "pan.___", state 33, "((j<2))" + line 1208, "pan.___", state 33, "((j>=2))" + line 1206, "pan.___", state 43, "((i<1))" + line 1206, "pan.___", state 43, "((i>=1))" + line 1216, "pan.___", state 54, "((j<2))" + line 1216, "pan.___", state 54, "((j>=2))" + line 1220, "pan.___", state 67, "((j<2))" + line 1220, "pan.___", state 67, "((j>=2))" + (6 of 78 states) +unreached in proctype :never: + line 1250, "pan.___", state 8, "-end-" + (1 of 8 states) + +pan: elapsed time 2.64e+04 seconds +pan: rate 2423.5502 states/second +pan: avg transition delay 1.3027e-06 usec +cp .input.spin urcu_free_no_wmb.spin.input +cp .input.spin.trail urcu_free_no_wmb.spin.input.trail +make[1]: Leaving directory `/home/compudj/doc/userspace-rcu/formal-model/urcu-controldataflow' diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_wmb.spin.input b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_wmb.spin.input new file mode 100644 index 0000000..f4c0ace --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_wmb.spin.input @@ -0,0 +1,1227 @@ +#define NO_WMB + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* We choose to ignore writer's non-progress caused from the + * reader ignoring the writer's mb() requests */ +#ifdef WRITER_PROGRESS +progress_writer_from_reader: +#endif + break; + od; +} + +#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: +#define PROGRESS_LABEL(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; \ + /* \ + * 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) \ + do \ + :: (reader_barrier[i] == 1) -> skip; \ + :: (reader_barrier[i] == 0) -> break; \ + od; \ + i++; \ + :: i >= NR_READERS -> \ + break \ + od; \ + smp_mb(i, j); \ +} + +#else + +#define smp_mb_send(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + :: 1 -> skip; + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_wmb.spin.input.trail b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_wmb.spin.input.trail new file mode 100644 index 0000000..befcb5f --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_no_wmb.spin.input.trail @@ -0,0 +1,1467 @@ +-2:3:-2 +-4:-4:-4 +1:0:4645 +2:3:4565 +3:3:4568 +4:3:4568 +5:3:4571 +6:3:4579 +7:3:4579 +8:3:4582 +9:3:4588 +10:3:4592 +11:3:4592 +12:3:4595 +13:3:4605 +14:3:4613 +15:3:4613 +16:3:4616 +17:3:4622 +18:3:4626 +19:3:4626 +20:3:4629 +21:3:4635 +22:3:4639 +23:3:4640 +24:0:4645 +25:3:4642 +26:0:4645 +27:2:2872 +28:0:4645 +29:2:2878 +30:0:4645 +31:2:2879 +32:0:4645 +33:2:2881 +34:0:4645 +35:2:2882 +36:0:4645 +37:2:2883 +38:0:4645 +39:2:2884 +40:2:2885 +41:2:2889 +42:2:2890 +43:2:2898 +44:2:2899 +45:2:2903 +46:2:2904 +47:2:2912 +48:2:2917 +49:2:2921 +50:2:2922 +51:2:2930 +52:2:2931 +53:2:2935 +54:2:2936 +55:2:2930 +56:2:2931 +57:2:2935 +58:2:2936 +59:2:2944 +60:2:2949 +61:2:2950 +62:2:2961 +63:2:2962 +64:2:2963 +65:2:2974 +66:2:2979 +67:2:2980 +68:2:2991 +69:2:2992 +70:2:2993 +71:2:2991 +72:2:2992 +73:2:2993 +74:2:3004 +75:2:3012 +76:0:4645 +77:2:2883 +78:0:4645 +79:2:3064 +80:2:3065 +81:2:3066 +82:0:4645 +83:2:2883 +84:0:4645 +85:2:3071 +86:0:4645 +87:2:3774 +88:2:3775 +89:2:3779 +90:2:3783 +91:2:3784 +92:2:3788 +93:2:3793 +94:2:3801 +95:2:3805 +96:2:3806 +97:2:3801 +98:2:3802 +99:2:3810 +100:2:3817 +101:2:3824 +102:2:3825 +103:2:3832 +104:2:3837 +105:2:3844 +106:2:3845 +107:2:3844 +108:2:3845 +109:2:3852 +110:2:3856 +111:0:4645 +112:2:3861 +113:0:4645 +114:2:3862 +115:0:4645 +116:2:3863 +117:0:4645 +118:2:3864 +119:0:4645 +120:1:2 +121:0:4645 +122:2:3865 +123:0:4645 +124:1:8 +125:0:4645 +126:1:9 +127:0:4645 +128:2:3864 +129:0:4645 +130:1:10 +131:0:4645 +132:2:3865 +133:0:4645 +134:1:11 +135:0:4645 +136:2:3864 +137:0:4645 +138:1:12 +139:0:4645 +140:2:3865 +141:0:4645 +142:1:13 +143:0:4645 +144:2:3864 +145:0:4645 +146:1:14 +147:0:4645 +148:2:3865 +149:0:4645 +150:1:15 +151:0:4645 +152:1:16 +153:0:4645 +154:2:3864 +155:0:4645 +156:1:17 +157:0:4645 +158:2:3865 +159:0:4645 +160:1:28 +161:0:4645 +162:2:3864 +163:0:4645 +164:1:32 +165:1:33 +166:1:37 +167:1:41 +168:1:42 +169:1:46 +170:1:54 +171:1:55 +172:1:59 +173:1:63 +174:1:64 +175:1:59 +176:1:63 +177:1:64 +178:1:68 +179:1:75 +180:1:82 +181:1:83 +182:1:90 +183:1:95 +184:1:102 +185:1:103 +186:1:102 +187:1:103 +188:1:110 +189:1:114 +190:0:4645 +191:2:3865 +192:0:4645 +193:1:119 +194:0:4645 +195:2:3866 +196:0:4645 +197:2:3871 +198:0:4645 +199:2:3872 +200:0:4645 +201:2:3880 +202:2:3881 +203:2:3885 +204:2:3889 +205:2:3890 +206:2:3894 +207:2:3902 +208:2:3903 +209:2:3907 +210:2:3911 +211:2:3912 +212:2:3907 +213:2:3911 +214:2:3912 +215:2:3916 +216:2:3923 +217:2:3930 +218:2:3931 +219:2:3938 +220:2:3943 +221:2:3950 +222:2:3951 +223:2:3950 +224:2:3951 +225:2:3958 +226:2:3962 +227:0:4645 +228:2:3073 +229:2:3755 +230:0:4645 +231:2:2883 +232:0:4645 +233:2:3074 +234:0:4645 +235:2:2883 +236:0:4645 +237:2:3077 +238:2:3078 +239:2:3082 +240:2:3083 +241:2:3091 +242:2:3092 +243:2:3096 +244:2:3097 +245:2:3105 +246:2:3110 +247:2:3114 +248:2:3115 +249:2:3123 +250:2:3124 +251:2:3128 +252:2:3129 +253:2:3123 +254:2:3124 +255:2:3128 +256:2:3129 +257:2:3137 +258:2:3142 +259:2:3143 +260:2:3154 +261:2:3155 +262:2:3156 +263:2:3167 +264:2:3172 +265:2:3173 +266:2:3184 +267:2:3185 +268:2:3186 +269:2:3184 +270:2:3185 +271:2:3186 +272:2:3197 +273:2:3204 +274:0:4645 +275:2:2883 +276:0:4645 +277:2:3208 +278:2:3209 +279:2:3210 +280:2:3222 +281:2:3223 +282:2:3227 +283:2:3228 +284:2:3236 +285:2:3241 +286:2:3245 +287:2:3246 +288:2:3254 +289:2:3255 +290:2:3259 +291:2:3260 +292:2:3254 +293:2:3255 +294:2:3259 +295:2:3260 +296:2:3268 +297:2:3273 +298:2:3274 +299:2:3285 +300:2:3286 +301:2:3287 +302:2:3298 +303:2:3303 +304:2:3304 +305:2:3315 +306:2:3316 +307:2:3317 +308:2:3315 +309:2:3316 +310:2:3317 +311:2:3328 +312:2:3339 +313:2:3340 +314:0:4645 +315:2:2883 +316:0:4645 +317:2:3346 +318:2:3347 +319:2:3351 +320:2:3352 +321:2:3360 +322:2:3361 +323:2:3365 +324:2:3366 +325:2:3374 +326:2:3379 +327:2:3383 +328:2:3384 +329:2:3392 +330:2:3393 +331:2:3397 +332:2:3398 +333:2:3392 +334:2:3393 +335:2:3397 +336:2:3398 +337:2:3406 +338:2:3411 +339:2:3412 +340:2:3423 +341:2:3424 +342:2:3425 +343:2:3436 +344:2:3441 +345:2:3442 +346:2:3453 +347:2:3454 +348:2:3455 +349:2:3453 +350:2:3454 +351:2:3455 +352:2:3466 +353:0:4645 +354:2:2883 +355:0:4645 +356:2:3475 +357:2:3476 +358:2:3480 +359:2:3481 +360:2:3489 +361:2:3490 +362:2:3494 +363:2:3495 +364:2:3503 +365:2:3508 +366:2:3512 +367:2:3513 +368:2:3521 +369:2:3522 +370:2:3526 +371:2:3527 +372:2:3521 +373:2:3522 +374:2:3526 +375:2:3527 +376:2:3535 +377:2:3540 +378:2:3541 +379:2:3552 +380:2:3553 +381:2:3554 +382:2:3565 +383:2:3570 +384:2:3571 +385:2:3582 +386:2:3583 +387:2:3584 +388:2:3582 +389:2:3583 +390:2:3584 +391:2:3595 +392:2:3602 +393:0:4645 +394:2:2883 +395:0:4645 +396:2:3606 +397:2:3607 +398:2:3608 +399:2:3620 +400:2:3621 +401:2:3625 +402:2:3626 +403:2:3634 +404:2:3639 +405:2:3643 +406:2:3644 +407:2:3652 +408:2:3653 +409:2:3657 +410:2:3658 +411:2:3652 +412:2:3653 +413:2:3657 +414:2:3658 +415:2:3666 +416:2:3671 +417:2:3672 +418:2:3683 +419:2:3684 +420:2:3685 +421:2:3696 +422:2:3701 +423:2:3702 +424:2:3713 +425:2:3714 +426:2:3715 +427:2:3713 +428:2:3714 +429:2:3715 +430:2:3726 +431:2:3736 +432:2:3737 +433:0:4645 +434:2:2883 +435:0:4645 +436:2:3743 +437:0:4645 +438:2:4368 +439:2:4369 +440:2:4373 +441:2:4377 +442:2:4378 +443:2:4382 +444:2:4390 +445:2:4391 +446:2:4395 +447:2:4399 +448:2:4400 +449:2:4395 +450:2:4399 +451:2:4400 +452:2:4404 +453:2:4411 +454:2:4418 +455:2:4419 +456:2:4426 +457:2:4431 +458:2:4438 +459:2:4439 +460:2:4438 +461:2:4439 +462:2:4446 +463:2:4450 +464:0:4645 +465:2:4455 +466:0:4645 +467:2:4456 +468:0:4645 +469:2:4457 +470:0:4645 +471:2:4458 +472:0:4645 +473:1:28 +474:0:4645 +475:2:4459 +476:0:4645 +477:1:32 +478:1:33 +479:1:37 +480:1:41 +481:1:42 +482:1:46 +483:1:54 +484:1:55 +485:1:59 +486:1:63 +487:1:64 +488:1:59 +489:1:63 +490:1:64 +491:1:68 +492:1:75 +493:1:82 +494:1:83 +495:1:90 +496:1:95 +497:1:102 +498:1:103 +499:1:102 +500:1:103 +501:1:110 +502:1:114 +503:0:4645 +504:2:4458 +505:0:4645 +506:1:119 +507:0:4645 +508:2:4459 +509:0:4645 +510:2:4460 +511:0:4645 +512:2:4465 +513:0:4645 +514:2:4466 +515:0:4645 +516:2:4474 +517:2:4475 +518:2:4479 +519:2:4483 +520:2:4484 +521:2:4488 +522:2:4496 +523:2:4497 +524:2:4501 +525:2:4505 +526:2:4506 +527:2:4501 +528:2:4505 +529:2:4506 +530:2:4510 +531:2:4517 +532:2:4524 +533:2:4525 +534:2:4532 +535:2:4537 +536:2:4544 +537:2:4545 +538:2:4544 +539:2:4545 +540:2:4552 +541:2:4556 +542:0:4645 +543:2:3745 +544:2:3755 +545:0:4645 +546:2:2883 +547:0:4645 +548:2:3746 +549:2:3747 +550:0:4645 +551:2:2883 +552:0:4645 +553:2:3751 +554:0:4645 +555:2:3759 +556:0:4645 +557:2:2879 +558:0:4645 +559:2:2881 +560:0:4645 +561:2:2882 +562:0:4645 +563:2:2883 +564:0:4645 +565:2:3064 +566:2:3065 +567:2:3066 +568:0:4645 +569:2:2883 +570:0:4645 +571:2:2884 +572:2:2885 +573:2:2889 +574:2:2890 +575:2:2898 +576:2:2899 +577:2:2903 +578:2:2904 +579:2:2912 +580:2:2917 +581:2:2918 +582:2:2930 +583:2:2931 +584:2:2932 +585:2:2930 +586:2:2931 +587:2:2935 +588:2:2936 +589:2:2944 +590:2:2949 +591:2:2950 +592:2:2961 +593:2:2962 +594:2:2963 +595:2:2974 +596:2:2979 +597:2:2980 +598:2:2991 +599:2:2992 +600:2:2993 +601:2:2991 +602:2:2992 +603:2:2993 +604:2:3004 +605:2:3012 +606:0:4645 +607:2:2883 +608:0:4645 +609:2:3071 +610:0:4645 +611:2:3774 +612:2:3775 +613:2:3779 +614:2:3783 +615:2:3784 +616:2:3788 +617:2:3796 +618:2:3797 +619:2:3801 +620:2:3802 +621:2:3801 +622:2:3805 +623:2:3806 +624:2:3810 +625:2:3817 +626:2:3824 +627:2:3825 +628:2:3832 +629:2:3837 +630:2:3844 +631:2:3845 +632:2:3844 +633:2:3845 +634:2:3852 +635:2:3856 +636:0:4645 +637:2:3861 +638:0:4645 +639:2:3862 +640:0:4645 +641:2:3863 +642:0:4645 +643:2:3864 +644:0:4645 +645:1:28 +646:0:4645 +647:2:3865 +648:0:4645 +649:1:32 +650:1:33 +651:1:37 +652:1:41 +653:1:42 +654:1:46 +655:1:54 +656:1:55 +657:1:59 +658:1:63 +659:1:64 +660:1:59 +661:1:63 +662:1:64 +663:1:68 +664:1:75 +665:1:82 +666:1:83 +667:1:90 +668:1:95 +669:1:102 +670:1:103 +671:1:102 +672:1:103 +673:1:110 +674:1:114 +675:0:4645 +676:2:3864 +677:0:4645 +678:1:119 +679:0:4645 +680:2:3865 +681:0:4645 +682:2:3866 +683:0:4645 +684:2:3871 +685:0:4645 +686:2:3872 +687:0:4645 +688:2:3880 +689:2:3881 +690:2:3885 +691:2:3889 +692:2:3890 +693:2:3894 +694:2:3902 +695:2:3903 +696:2:3907 +697:2:3911 +698:2:3912 +699:2:3907 +700:2:3911 +701:2:3912 +702:2:3916 +703:2:3923 +704:2:3930 +705:2:3931 +706:2:3938 +707:2:3943 +708:2:3950 +709:2:3951 +710:2:3950 +711:2:3951 +712:2:3958 +713:2:3962 +714:0:4645 +715:2:3073 +716:2:3755 +717:0:4645 +718:2:2883 +719:0:4645 +720:2:3074 +721:0:4645 +722:2:2883 +723:0:4645 +724:2:3077 +725:2:3078 +726:2:3082 +727:2:3083 +728:2:3091 +729:2:3092 +730:2:3096 +731:2:3097 +732:2:3105 +733:2:3110 +734:2:3114 +735:2:3115 +736:2:3123 +737:2:3124 +738:2:3128 +739:2:3129 +740:2:3123 +741:2:3124 +742:2:3128 +743:2:3129 +744:2:3137 +745:2:3142 +746:2:3143 +747:2:3154 +748:2:3155 +749:2:3156 +750:2:3167 +751:2:3172 +752:2:3173 +753:2:3184 +754:2:3185 +755:2:3186 +756:2:3184 +757:2:3185 +758:2:3186 +759:2:3197 +760:2:3204 +761:0:4645 +762:2:2883 +763:0:4645 +764:2:3208 +765:2:3209 +766:2:3210 +767:2:3222 +768:2:3223 +769:2:3227 +770:2:3228 +771:2:3236 +772:2:3241 +773:2:3245 +774:2:3246 +775:2:3254 +776:2:3255 +777:2:3259 +778:2:3260 +779:2:3254 +780:2:3255 +781:2:3259 +782:2:3260 +783:2:3268 +784:2:3273 +785:2:3274 +786:2:3285 +787:2:3286 +788:2:3287 +789:2:3298 +790:2:3303 +791:2:3304 +792:2:3315 +793:2:3316 +794:2:3317 +795:2:3315 +796:2:3316 +797:2:3317 +798:2:3328 +799:2:3339 +800:2:3340 +801:0:4645 +802:2:2883 +803:0:4645 +804:2:3346 +805:2:3347 +806:2:3351 +807:2:3352 +808:2:3360 +809:2:3361 +810:2:3365 +811:2:3366 +812:2:3374 +813:2:3379 +814:2:3383 +815:2:3384 +816:2:3392 +817:2:3393 +818:2:3397 +819:2:3398 +820:2:3392 +821:2:3393 +822:2:3397 +823:2:3398 +824:2:3406 +825:2:3411 +826:2:3412 +827:2:3423 +828:2:3424 +829:2:3425 +830:2:3436 +831:2:3441 +832:2:3442 +833:2:3453 +834:2:3454 +835:2:3455 +836:2:3453 +837:2:3454 +838:2:3455 +839:2:3466 +840:0:4645 +841:2:2883 +842:0:4645 +843:2:3475 +844:2:3476 +845:2:3480 +846:2:3481 +847:2:3489 +848:2:3490 +849:2:3494 +850:2:3495 +851:2:3503 +852:2:3508 +853:2:3512 +854:2:3513 +855:2:3521 +856:2:3522 +857:2:3526 +858:2:3527 +859:2:3521 +860:2:3522 +861:2:3526 +862:2:3527 +863:2:3535 +864:2:3540 +865:2:3541 +866:2:3552 +867:2:3553 +868:2:3554 +869:2:3565 +870:2:3570 +871:2:3571 +872:2:3582 +873:2:3583 +874:2:3584 +875:2:3582 +876:2:3583 +877:2:3584 +878:2:3595 +879:2:3602 +880:0:4645 +881:2:2883 +882:0:4645 +883:2:3606 +884:2:3607 +885:2:3608 +886:2:3620 +887:2:3621 +888:2:3625 +889:2:3626 +890:2:3634 +891:2:3639 +892:2:3643 +893:2:3644 +894:2:3652 +895:2:3653 +896:2:3657 +897:2:3658 +898:2:3652 +899:2:3653 +900:2:3657 +901:2:3658 +902:2:3666 +903:2:3671 +904:2:3672 +905:2:3683 +906:2:3684 +907:2:3685 +908:2:3696 +909:2:3701 +910:2:3702 +911:2:3713 +912:2:3714 +913:2:3715 +914:2:3713 +915:2:3714 +916:2:3715 +917:2:3726 +918:2:3736 +919:2:3737 +920:0:4645 +921:2:2883 +922:0:4645 +923:2:3743 +924:0:4645 +925:2:4368 +926:2:4369 +927:2:4373 +928:2:4377 +929:2:4378 +930:2:4382 +931:2:4390 +932:2:4391 +933:2:4395 +934:2:4399 +935:2:4400 +936:2:4395 +937:2:4399 +938:2:4400 +939:2:4404 +940:2:4411 +941:2:4418 +942:2:4419 +943:2:4426 +944:2:4431 +945:2:4438 +946:2:4439 +947:2:4438 +948:2:4439 +949:2:4446 +950:2:4450 +951:0:4645 +952:2:4455 +953:0:4645 +954:2:4456 +955:0:4645 +956:2:4457 +957:0:4645 +958:2:4458 +959:0:4645 +960:1:28 +961:0:4645 +962:2:4459 +963:0:4645 +964:1:32 +965:1:33 +966:1:37 +967:1:41 +968:1:42 +969:1:46 +970:1:54 +971:1:55 +972:1:59 +973:1:63 +974:1:64 +975:1:59 +976:1:63 +977:1:64 +978:1:68 +979:1:75 +980:1:82 +981:1:83 +982:1:90 +983:1:95 +984:1:102 +985:1:103 +986:1:102 +987:1:103 +988:1:110 +989:1:114 +990:0:4645 +991:2:4458 +992:0:4645 +993:1:119 +994:0:4645 +995:2:4459 +996:0:4645 +997:2:4460 +998:0:4645 +999:2:4465 +1000:0:4645 +1001:2:4466 +1002:0:4645 +1003:2:4474 +1004:2:4475 +1005:2:4479 +1006:2:4483 +1007:2:4484 +1008:2:4488 +1009:2:4496 +1010:2:4497 +1011:2:4501 +1012:2:4505 +1013:2:4506 +1014:2:4501 +1015:2:4505 +1016:2:4506 +1017:2:4510 +1018:2:4517 +1019:2:4524 +1020:2:4525 +1021:2:4532 +1022:2:4537 +1023:2:4544 +1024:2:4545 +1025:2:4544 +1026:2:4545 +1027:2:4552 +1028:2:4556 +1029:0:4645 +1030:2:3745 +1031:2:3755 +1032:0:4645 +1033:2:2883 +1034:0:4645 +1035:2:3746 +1036:2:3747 +1037:0:4645 +1038:2:2883 +1039:0:4645 +1040:2:3751 +1041:0:4645 +1042:2:3759 +1043:0:4645 +1044:2:2879 +1045:0:4645 +1046:2:2881 +1047:0:4645 +1048:2:2882 +1049:0:4645 +1050:2:2883 +1051:0:4645 +1052:2:2884 +1053:2:2885 +1054:2:2889 +1055:2:2890 +1056:2:2898 +1057:2:2899 +1058:2:2903 +1059:2:2904 +1060:2:2912 +1061:2:2917 +1062:2:2921 +1063:2:2922 +1064:2:2930 +1065:2:2931 +1066:2:2935 +1067:2:2936 +1068:2:2930 +1069:2:2931 +1070:2:2932 +1071:2:2944 +1072:2:2949 +1073:2:2950 +1074:2:2961 +1075:2:2962 +1076:2:2963 +1077:2:2974 +1078:2:2979 +1079:2:2980 +1080:2:2991 +1081:2:2992 +1082:2:2993 +1083:2:2991 +1084:2:2992 +1085:2:2993 +1086:2:3004 +1087:2:3012 +1088:0:4645 +1089:2:2883 +1090:0:4645 +1091:2:3064 +1092:2:3065 +1093:2:3066 +1094:0:4645 +1095:2:2883 +1096:0:4645 +1097:2:3071 +1098:0:4645 +1099:1:120 +1100:0:4645 +1101:1:19 +1102:0:4645 +1103:1:127 +1104:1:128 +1105:1:132 +1106:1:133 +1107:1:141 +1108:1:142 +1109:1:146 +1110:1:147 +1111:1:155 +1112:1:160 +1113:1:164 +1114:1:165 +1115:1:173 +1116:1:174 +1117:1:178 +1118:1:179 +1119:1:173 +1120:1:174 +1121:1:178 +1122:1:179 +1123:1:187 +1124:1:192 +1125:1:193 +1126:1:204 +1127:1:205 +1128:1:206 +1129:1:217 +1130:1:222 +1131:1:223 +1132:1:234 +1133:1:235 +1134:1:236 +1135:1:234 +1136:1:235 +1137:1:236 +1138:1:247 +1139:0:4645 +1140:1:15 +1141:0:4645 +1142:1:16 +1143:0:4645 +1144:1:17 +1145:0:4645 +1146:1:120 +1147:0:4645 +1148:1:19 +1149:0:4645 +1150:1:256 +1151:1:257 +1152:0:4645 +1153:1:15 +1154:0:4645 +1155:1:16 +1156:0:4645 +1157:1:17 +1158:0:4645 +1159:1:120 +1160:0:4645 +1161:1:19 +1162:0:4645 +1163:1:263 +1164:1:264 +1165:1:268 +1166:1:269 +1167:1:277 +1168:1:278 +1169:1:282 +1170:1:283 +1171:1:291 +1172:1:296 +1173:1:300 +1174:1:301 +1175:1:309 +1176:1:310 +1177:1:314 +1178:1:315 +1179:1:309 +1180:1:310 +1181:1:314 +1182:1:315 +1183:1:323 +1184:1:328 +1185:1:329 +1186:1:340 +1187:1:341 +1188:1:342 +1189:1:353 +1190:1:358 +1191:1:359 +1192:1:370 +1193:1:371 +1194:1:372 +1195:1:370 +1196:1:371 +1197:1:372 +1198:1:383 +1199:0:4645 +1200:1:15 +1201:0:4645 +1202:1:16 +1203:0:4645 +1204:1:17 +1205:0:4645 +1206:1:120 +1207:0:4645 +1208:1:19 +1209:0:4645 +1210:1:392 +1211:1:393 +1212:1:397 +1213:1:398 +1214:1:406 +1215:1:407 +1216:1:411 +1217:1:412 +1218:1:420 +1219:1:425 +1220:1:429 +1221:1:430 +1222:1:438 +1223:1:439 +1224:1:443 +1225:1:444 +1226:1:438 +1227:1:439 +1228:1:443 +1229:1:444 +1230:1:452 +1231:1:457 +1232:1:458 +1233:1:469 +1234:1:470 +1235:1:471 +1236:1:482 +1237:1:487 +1238:1:488 +1239:1:499 +1240:1:500 +1241:1:501 +1242:1:499 +1243:1:500 +1244:1:501 +1245:1:512 +1246:1:519 +1247:0:4645 +1248:1:15 +1249:0:4645 +1250:1:16 +1251:0:4645 +1252:1:17 +1253:0:4645 +1254:1:120 +1255:0:4645 +1256:1:19 +1257:0:4645 +1258:1:657 +1259:1:658 +1260:1:662 +1261:1:663 +1262:1:671 +1263:1:672 +1264:1:673 +1265:1:685 +1266:1:690 +1267:1:694 +1268:1:695 +1269:1:703 +1270:1:704 +1271:1:708 +1272:1:709 +1273:1:703 +1274:1:704 +1275:1:708 +1276:1:709 +1277:1:717 +1278:1:722 +1279:1:723 +1280:1:734 +1281:1:735 +1282:1:736 +1283:1:747 +1284:1:752 +1285:1:753 +1286:1:764 +1287:1:765 +1288:1:766 +1289:1:764 +1290:1:765 +1291:1:766 +1292:1:777 +1293:0:4645 +1294:1:15 +1295:0:4645 +1296:1:16 +1297:0:4645 +1298:1:17 +1299:0:4645 +1300:1:120 +1301:0:4645 +1302:1:19 +1303:0:4645 +1304:1:786 +1305:1:789 +1306:1:790 +1307:0:4645 +1308:1:15 +1309:0:4645 +1310:1:16 +1311:0:4645 +1312:1:17 +1313:0:4645 +1314:1:120 +1315:0:4645 +1316:1:19 +1317:0:4645 +1318:1:1053 +1319:1:1054 +1320:1:1058 +1321:1:1059 +1322:1:1067 +1323:1:1068 +1324:1:1072 +1325:1:1073 +1326:1:1081 +1327:1:1086 +1328:1:1090 +1329:1:1091 +1330:1:1099 +1331:1:1100 +1332:1:1104 +1333:1:1105 +1334:1:1099 +1335:1:1100 +1336:1:1104 +1337:1:1105 +1338:1:1113 +1339:1:1118 +1340:1:1119 +1341:1:1130 +1342:1:1131 +1343:1:1132 +1344:1:1143 +1345:1:1148 +1346:1:1149 +1347:1:1160 +1348:1:1161 +1349:1:1162 +1350:1:1160 +1351:1:1161 +1352:1:1162 +1353:1:1173 +1354:1:1180 +1355:1:1184 +1356:0:4645 +1357:1:15 +1358:0:4645 +1359:1:16 +1360:0:4645 +1361:1:17 +1362:0:4645 +1363:1:120 +1364:0:4645 +1365:1:19 +1366:0:4645 +1367:1:1185 +1368:1:1186 +1369:1:1190 +1370:1:1191 +1371:1:1199 +1372:1:1200 +1373:1:1201 +1374:1:1213 +1375:1:1218 +1376:1:1222 +1377:1:1223 +1378:1:1231 +1379:1:1232 +1380:1:1236 +1381:1:1237 +1382:1:1231 +1383:1:1232 +1384:1:1236 +1385:1:1237 +1386:1:1245 +1387:1:1250 +1388:1:1251 +1389:1:1262 +1390:1:1263 +1391:1:1264 +1392:1:1275 +1393:1:1280 +1394:1:1281 +1395:1:1292 +1396:1:1293 +1397:1:1294 +1398:1:1292 +1399:1:1293 +1400:1:1294 +1401:1:1305 +1402:0:4645 +1403:1:15 +1404:0:4645 +1405:1:16 +1406:0:4645 +1407:1:17 +1408:0:4645 +1409:1:120 +1410:0:4645 +1411:1:19 +1412:0:4645 +1413:1:1314 +1414:0:4645 +1415:1:2778 +1416:1:2785 +1417:1:2786 +1418:1:2793 +1419:1:2798 +1420:1:2805 +1421:1:2806 +1422:1:2805 +1423:1:2806 +1424:1:2813 +1425:1:2817 +1426:0:4645 +1427:2:3774 +1428:2:3775 +1429:2:3779 +1430:2:3783 +1431:2:3784 +1432:2:3788 +1433:2:3793 +1434:2:3801 +1435:2:3805 +1436:2:3806 +1437:2:3801 +1438:2:3802 +1439:2:3810 +1440:2:3817 +1441:2:3824 +1442:2:3825 +1443:2:3832 +1444:2:3837 +1445:2:3844 +1446:2:3845 +1447:2:3844 +1448:2:3845 +1449:2:3852 +1450:2:3856 +1451:0:4645 +1452:2:3861 +1453:0:4645 +1454:2:3862 +1455:0:4645 +1456:2:3863 +1457:0:4645 +1458:2:3864 +1459:0:4645 +1460:1:1316 +1461:1:1317 +1462:0:4643 +1463:2:3865 +1464:0:4649 +1465:1:2475 diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_single_flip.define b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_single_flip.define new file mode 100644 index 0000000..5e642ef --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_single_flip.define @@ -0,0 +1 @@ +#define SINGLE_FLIP diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_single_flip.log b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_single_flip.log new file mode 100644 index 0000000..4f60a26 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_single_flip.log @@ -0,0 +1,783 @@ +make[1]: Entering directory `/home/compudj/doc/userspace-rcu/formal-model/urcu-controldataflow' +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define >> pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_free.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_free_single_flip.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1245) +Depth= 9313 States= 1e+06 Transitions= 1.5e+08 Memory= 550.432 t= 185 R= 5e+03 +Depth= 9313 States= 2e+06 Transitions= 3.71e+08 Memory= 634.318 t= 475 R= 4e+03 +Depth= 9313 States= 3e+06 Transitions= 6.52e+08 Memory= 718.303 t= 847 R= 4e+03 +pan: resizing hashtable to -w22.. done +Depth= 9313 States= 4e+06 Transitions= 8.49e+08 Memory= 833.311 t= 1.09e+03 R= 4e+03 +Depth= 9313 States= 5e+06 Transitions= 1.02e+09 Memory= 917.295 t= 1.3e+03 R= 4e+03 +Depth= 9313 States= 6e+06 Transitions= 1.18e+09 Memory= 1001.279 t= 1.51e+03 R= 4e+03 +Depth= 9313 States= 7e+06 Transitions= 1.44e+09 Memory= 1085.264 t= 1.86e+03 R= 4e+03 +Depth= 9313 States= 8e+06 Transitions= 1.69e+09 Memory= 1169.151 t= 2.17e+03 R= 4e+03 +Depth= 9313 States= 9e+06 Transitions= 1.87e+09 Memory= 1253.135 t= 2.42e+03 R= 4e+03 +pan: resizing hashtable to -w24.. done +Depth= 9313 States= 1e+07 Transitions= 2.08e+09 Memory= 1461.115 t= 2.68e+03 R= 4e+03 +Depth= 9313 States= 1.1e+07 Transitions= 2.38e+09 Memory= 1545.100 t= 3.06e+03 R= 4e+03 +Depth= 9530 States= 1.2e+07 Transitions= 2.6e+09 Memory= 1629.084 t= 3.35e+03 R= 4e+03 +Depth= 9530 States= 1.3e+07 Transitions= 2.85e+09 Memory= 1713.068 t= 3.67e+03 R= 4e+03 +Depth= 9530 States= 1.4e+07 Transitions= 3.06e+09 Memory= 1797.053 t= 3.93e+03 R= 4e+03 +Depth= 9530 States= 1.5e+07 Transitions= 3.32e+09 Memory= 1881.037 t= 4.28e+03 R= 4e+03 +Depth= 9530 States= 1.6e+07 Transitions= 3.52e+09 Memory= 1964.924 t= 4.54e+03 R= 4e+03 +Depth= 9530 States= 1.7e+07 Transitions= 3.85e+09 Memory= 2048.908 t= 4.96e+03 R= 3e+03 +Depth= 9530 States= 1.8e+07 Transitions= 4.15e+09 Memory= 2132.893 t= 5.34e+03 R= 3e+03 +Depth= 9530 States= 1.9e+07 Transitions= 4.35e+09 Memory= 2216.877 t= 5.58e+03 R= 3e+03 +Depth= 9530 States= 2e+07 Transitions= 4.59e+09 Memory= 2300.861 t= 5.89e+03 R= 3e+03 +Depth= 9530 States= 2.1e+07 Transitions= 4.83e+09 Memory= 2384.846 t= 6.21e+03 R= 3e+03 +Depth= 9530 States= 2.2e+07 Transitions= 5.07e+09 Memory= 2468.830 t= 6.52e+03 R= 3e+03 +Depth= 9530 States= 2.3e+07 Transitions= 5.31e+09 Memory= 2552.717 t= 6.83e+03 R= 3e+03 +Depth= 9530 States= 2.4e+07 Transitions= 5.5e+09 Memory= 2636.701 t= 7.08e+03 R= 3e+03 +pan: claim violated! (at depth 1365) +pan: wrote .input.spin.trail + +(Spin Version 5.1.7 -- 23 December 2008) +Warning: Search not completed + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness disabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 9530, errors: 1 + 24603269 states, stored +5.6549664e+09 states, matched +5.6795697e+09 transitions (= stored+matched) +3.17715e+10 atomic steps +hash conflicts: 3.9132393e+09 (resolved) + +Stats on memory usage (in Megabytes): + 2721.767 equivalent memory usage for states (stored*(State-vector + overhead)) + 2102.819 actual memory usage for states (compression: 77.26%) + state-vector as stored = 62 byte + 28 byte overhead + 128.000 memory used for hash table (-w24) + 457.764 memory used for DFS stack (-m10000000) + 1.198 memory lost to fragmentation + 2687.385 total actual memory usage + +unreached in proctype urcu_reader + line 250, "pan.___", state 32, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 54, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 63, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 79, "(1)" + line 231, "pan.___", state 87, "(1)" + line 235, "pan.___", state 99, "(1)" + line 239, "pan.___", state 107, "(1)" + line 387, "pan.___", state 132, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 164, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 178, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 197, "(1)" + line 413, "pan.___", state 227, "(1)" + line 417, "pan.___", state 240, "(1)" + line 663, "pan.___", state 261, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 387, "pan.___", state 268, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 300, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 314, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 333, "(1)" + line 413, "pan.___", state 363, "(1)" + line 417, "pan.___", state 376, "(1)" + line 387, "pan.___", state 397, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 429, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 443, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 462, "(1)" + line 413, "pan.___", state 492, "(1)" + line 417, "pan.___", state 505, "(1)" + line 387, "pan.___", state 528, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 530, "(1)" + line 387, "pan.___", state 531, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 531, "else" + line 387, "pan.___", state 534, "(1)" + line 391, "pan.___", state 542, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 544, "(1)" + line 391, "pan.___", state 545, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 545, "else" + line 391, "pan.___", state 548, "(1)" + line 391, "pan.___", state 549, "(1)" + line 391, "pan.___", state 549, "(1)" + line 389, "pan.___", state 554, "((i<1))" + line 389, "pan.___", state 554, "((i>=1))" + line 396, "pan.___", state 560, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 562, "(1)" + line 396, "pan.___", state 563, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 563, "else" + line 396, "pan.___", state 566, "(1)" + line 396, "pan.___", state 567, "(1)" + line 396, "pan.___", state 567, "(1)" + line 400, "pan.___", state 574, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 576, "(1)" + line 400, "pan.___", state 577, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 577, "else" + line 400, "pan.___", state 580, "(1)" + line 400, "pan.___", state 581, "(1)" + line 400, "pan.___", state 581, "(1)" + line 398, "pan.___", state 586, "((i<2))" + line 398, "pan.___", state 586, "((i>=2))" + line 404, "pan.___", state 593, "(1)" + line 404, "pan.___", state 594, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 594, "else" + line 404, "pan.___", state 597, "(1)" + line 404, "pan.___", state 598, "(1)" + line 404, "pan.___", state 598, "(1)" + line 408, "pan.___", state 606, "(1)" + line 408, "pan.___", state 607, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 607, "else" + line 408, "pan.___", state 610, "(1)" + line 408, "pan.___", state 611, "(1)" + line 408, "pan.___", state 611, "(1)" + line 406, "pan.___", state 616, "((i<1))" + line 406, "pan.___", state 616, "((i>=1))" + line 413, "pan.___", state 623, "(1)" + line 413, "pan.___", state 624, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 624, "else" + line 413, "pan.___", state 627, "(1)" + line 413, "pan.___", state 628, "(1)" + line 413, "pan.___", state 628, "(1)" + line 417, "pan.___", state 636, "(1)" + line 417, "pan.___", state 637, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 637, "else" + line 417, "pan.___", state 640, "(1)" + line 417, "pan.___", state 641, "(1)" + line 417, "pan.___", state 641, "(1)" + line 415, "pan.___", state 646, "((i<2))" + line 415, "pan.___", state 646, "((i>=2))" + line 422, "pan.___", state 650, "(1)" + line 422, "pan.___", state 650, "(1)" + line 663, "pan.___", state 653, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 663, "pan.___", state 654, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 663, "pan.___", state 655, "(1)" + line 387, "pan.___", state 662, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 694, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 708, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 727, "(1)" + line 413, "pan.___", state 757, "(1)" + line 417, "pan.___", state 770, "(1)" + line 387, "pan.___", state 798, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 800, "(1)" + line 387, "pan.___", state 801, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 801, "else" + line 387, "pan.___", state 804, "(1)" + line 391, "pan.___", state 812, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 814, "(1)" + line 391, "pan.___", state 815, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 815, "else" + line 391, "pan.___", state 818, "(1)" + line 391, "pan.___", state 819, "(1)" + line 391, "pan.___", state 819, "(1)" + line 389, "pan.___", state 824, "((i<1))" + line 389, "pan.___", state 824, "((i>=1))" + line 396, "pan.___", state 830, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 832, "(1)" + line 396, "pan.___", state 833, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 833, "else" + line 396, "pan.___", state 836, "(1)" + line 396, "pan.___", state 837, "(1)" + line 396, "pan.___", state 837, "(1)" + line 400, "pan.___", state 844, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 846, "(1)" + line 400, "pan.___", state 847, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 847, "else" + line 400, "pan.___", state 850, "(1)" + line 400, "pan.___", state 851, "(1)" + line 400, "pan.___", state 851, "(1)" + line 398, "pan.___", state 856, "((i<2))" + line 398, "pan.___", state 856, "((i>=2))" + line 404, "pan.___", state 863, "(1)" + line 404, "pan.___", state 864, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 864, "else" + line 404, "pan.___", state 867, "(1)" + line 404, "pan.___", state 868, "(1)" + line 404, "pan.___", state 868, "(1)" + line 408, "pan.___", state 876, "(1)" + line 408, "pan.___", state 877, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 877, "else" + line 408, "pan.___", state 880, "(1)" + line 408, "pan.___", state 881, "(1)" + line 408, "pan.___", state 881, "(1)" + line 406, "pan.___", state 886, "((i<1))" + line 406, "pan.___", state 886, "((i>=1))" + line 413, "pan.___", state 893, "(1)" + line 413, "pan.___", state 894, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 894, "else" + line 413, "pan.___", state 897, "(1)" + line 413, "pan.___", state 898, "(1)" + line 413, "pan.___", state 898, "(1)" + line 417, "pan.___", state 906, "(1)" + line 417, "pan.___", state 907, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 907, "else" + line 417, "pan.___", state 910, "(1)" + line 417, "pan.___", state 911, "(1)" + line 417, "pan.___", state 911, "(1)" + line 422, "pan.___", state 920, "(1)" + line 422, "pan.___", state 920, "(1)" + line 387, "pan.___", state 927, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 929, "(1)" + line 387, "pan.___", state 930, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 930, "else" + line 387, "pan.___", state 933, "(1)" + line 391, "pan.___", state 941, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 943, "(1)" + line 391, "pan.___", state 944, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 944, "else" + line 391, "pan.___", state 947, "(1)" + line 391, "pan.___", state 948, "(1)" + line 391, "pan.___", state 948, "(1)" + line 389, "pan.___", state 953, "((i<1))" + line 389, "pan.___", state 953, "((i>=1))" + line 396, "pan.___", state 959, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 961, "(1)" + line 396, "pan.___", state 962, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 962, "else" + line 396, "pan.___", state 965, "(1)" + line 396, "pan.___", state 966, "(1)" + line 396, "pan.___", state 966, "(1)" + line 400, "pan.___", state 973, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 975, "(1)" + line 400, "pan.___", state 976, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 976, "else" + line 400, "pan.___", state 979, "(1)" + line 400, "pan.___", state 980, "(1)" + line 400, "pan.___", state 980, "(1)" + line 398, "pan.___", state 985, "((i<2))" + line 398, "pan.___", state 985, "((i>=2))" + line 404, "pan.___", state 992, "(1)" + line 404, "pan.___", state 993, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 993, "else" + line 404, "pan.___", state 996, "(1)" + line 404, "pan.___", state 997, "(1)" + line 404, "pan.___", state 997, "(1)" + line 408, "pan.___", state 1005, "(1)" + line 408, "pan.___", state 1006, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 1006, "else" + line 408, "pan.___", state 1009, "(1)" + line 408, "pan.___", state 1010, "(1)" + line 408, "pan.___", state 1010, "(1)" + line 406, "pan.___", state 1015, "((i<1))" + line 406, "pan.___", state 1015, "((i>=1))" + line 413, "pan.___", state 1022, "(1)" + line 413, "pan.___", state 1023, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 1023, "else" + line 413, "pan.___", state 1026, "(1)" + line 413, "pan.___", state 1027, "(1)" + line 413, "pan.___", state 1027, "(1)" + line 417, "pan.___", state 1035, "(1)" + line 417, "pan.___", state 1036, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 1036, "else" + line 417, "pan.___", state 1039, "(1)" + line 417, "pan.___", state 1040, "(1)" + line 417, "pan.___", state 1040, "(1)" + line 415, "pan.___", state 1045, "((i<2))" + line 415, "pan.___", state 1045, "((i>=2))" + line 422, "pan.___", state 1049, "(1)" + line 422, "pan.___", state 1049, "(1)" + line 671, "pan.___", state 1053, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 387, "pan.___", state 1058, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1090, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1104, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1123, "(1)" + line 413, "pan.___", state 1153, "(1)" + line 417, "pan.___", state 1166, "(1)" + line 387, "pan.___", state 1190, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1222, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1236, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1255, "(1)" + line 413, "pan.___", state 1285, "(1)" + line 417, "pan.___", state 1298, "(1)" + line 387, "pan.___", state 1323, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1355, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1369, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1388, "(1)" + line 413, "pan.___", state 1418, "(1)" + line 417, "pan.___", state 1431, "(1)" + line 387, "pan.___", state 1452, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1484, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1498, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1517, "(1)" + line 413, "pan.___", state 1547, "(1)" + line 417, "pan.___", state 1560, "(1)" + line 387, "pan.___", state 1586, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1618, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1632, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1651, "(1)" + line 413, "pan.___", state 1681, "(1)" + line 417, "pan.___", state 1694, "(1)" + line 387, "pan.___", state 1715, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1747, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1761, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1780, "(1)" + line 413, "pan.___", state 1810, "(1)" + line 417, "pan.___", state 1823, "(1)" + line 387, "pan.___", state 1847, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1879, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1893, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1912, "(1)" + line 413, "pan.___", state 1942, "(1)" + line 417, "pan.___", state 1955, "(1)" + line 710, "pan.___", state 1976, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 387, "pan.___", state 1983, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2015, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2029, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2048, "(1)" + line 413, "pan.___", state 2078, "(1)" + line 417, "pan.___", state 2091, "(1)" + line 387, "pan.___", state 2112, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2144, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2158, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2177, "(1)" + line 413, "pan.___", state 2207, "(1)" + line 417, "pan.___", state 2220, "(1)" + line 387, "pan.___", state 2243, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 2245, "(1)" + line 387, "pan.___", state 2246, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 2246, "else" + line 387, "pan.___", state 2249, "(1)" + line 391, "pan.___", state 2257, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 2259, "(1)" + line 391, "pan.___", state 2260, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 2260, "else" + line 391, "pan.___", state 2263, "(1)" + line 391, "pan.___", state 2264, "(1)" + line 391, "pan.___", state 2264, "(1)" + line 389, "pan.___", state 2269, "((i<1))" + line 389, "pan.___", state 2269, "((i>=1))" + line 396, "pan.___", state 2275, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2277, "(1)" + line 396, "pan.___", state 2278, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 2278, "else" + line 396, "pan.___", state 2281, "(1)" + line 396, "pan.___", state 2282, "(1)" + line 396, "pan.___", state 2282, "(1)" + line 400, "pan.___", state 2289, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2291, "(1)" + line 400, "pan.___", state 2292, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 2292, "else" + line 400, "pan.___", state 2295, "(1)" + line 400, "pan.___", state 2296, "(1)" + line 400, "pan.___", state 2296, "(1)" + line 398, "pan.___", state 2301, "((i<2))" + line 398, "pan.___", state 2301, "((i>=2))" + line 404, "pan.___", state 2308, "(1)" + line 404, "pan.___", state 2309, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 2309, "else" + line 404, "pan.___", state 2312, "(1)" + line 404, "pan.___", state 2313, "(1)" + line 404, "pan.___", state 2313, "(1)" + line 408, "pan.___", state 2321, "(1)" + line 408, "pan.___", state 2322, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 2322, "else" + line 408, "pan.___", state 2325, "(1)" + line 408, "pan.___", state 2326, "(1)" + line 408, "pan.___", state 2326, "(1)" + line 406, "pan.___", state 2331, "((i<1))" + line 406, "pan.___", state 2331, "((i>=1))" + line 413, "pan.___", state 2338, "(1)" + line 413, "pan.___", state 2339, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 2339, "else" + line 413, "pan.___", state 2342, "(1)" + line 413, "pan.___", state 2343, "(1)" + line 413, "pan.___", state 2343, "(1)" + line 417, "pan.___", state 2351, "(1)" + line 417, "pan.___", state 2352, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 2352, "else" + line 417, "pan.___", state 2355, "(1)" + line 417, "pan.___", state 2356, "(1)" + line 417, "pan.___", state 2356, "(1)" + line 415, "pan.___", state 2361, "((i<2))" + line 415, "pan.___", state 2361, "((i>=2))" + line 422, "pan.___", state 2365, "(1)" + line 422, "pan.___", state 2365, "(1)" + line 710, "pan.___", state 2368, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 710, "pan.___", state 2369, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 710, "pan.___", state 2370, "(1)" + line 387, "pan.___", state 2377, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2409, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2423, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2442, "(1)" + line 413, "pan.___", state 2472, "(1)" + line 417, "pan.___", state 2485, "(1)" + line 387, "pan.___", state 2512, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2544, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2558, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2577, "(1)" + line 413, "pan.___", state 2607, "(1)" + line 417, "pan.___", state 2620, "(1)" + line 387, "pan.___", state 2641, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2673, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2687, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2706, "(1)" + line 413, "pan.___", state 2736, "(1)" + line 417, "pan.___", state 2749, "(1)" + line 227, "pan.___", state 2782, "(1)" + line 235, "pan.___", state 2802, "(1)" + line 239, "pan.___", state 2810, "(1)" + line 227, "pan.___", state 2825, "(1)" + line 235, "pan.___", state 2845, "(1)" + line 239, "pan.___", state 2853, "(1)" + line 870, "pan.___", state 2870, "-end-" + (278 of 2870 states) +unreached in proctype urcu_writer + line 387, "pan.___", state 22, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 36, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 54, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 87, "(1)" + line 408, "pan.___", state 100, "(1)" + line 413, "pan.___", state 117, "(1)" + line 250, "pan.___", state 153, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 162, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 175, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 215, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 229, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 247, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 261, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 280, "(1)" + line 408, "pan.___", state 293, "(1)" + line 413, "pan.___", state 310, "(1)" + line 417, "pan.___", state 323, "(1)" + line 391, "pan.___", state 360, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 378, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 392, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 424, "(1)" + line 413, "pan.___", state 441, "(1)" + line 417, "pan.___", state 454, "(1)" + line 387, "pan.___", state 483, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 485, "(1)" + line 387, "pan.___", state 486, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 486, "else" + line 387, "pan.___", state 489, "(1)" + line 391, "pan.___", state 497, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 499, "(1)" + line 391, "pan.___", state 500, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 500, "else" + line 391, "pan.___", state 503, "(1)" + line 391, "pan.___", state 504, "(1)" + line 391, "pan.___", state 504, "(1)" + line 389, "pan.___", state 509, "((i<1))" + line 389, "pan.___", state 509, "((i>=1))" + line 396, "pan.___", state 515, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 517, "(1)" + line 396, "pan.___", state 518, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 518, "else" + line 396, "pan.___", state 521, "(1)" + line 396, "pan.___", state 522, "(1)" + line 396, "pan.___", state 522, "(1)" + line 400, "pan.___", state 529, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 531, "(1)" + line 400, "pan.___", state 532, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 532, "else" + line 400, "pan.___", state 535, "(1)" + line 400, "pan.___", state 536, "(1)" + line 400, "pan.___", state 536, "(1)" + line 398, "pan.___", state 541, "((i<2))" + line 398, "pan.___", state 541, "((i>=2))" + line 404, "pan.___", state 548, "(1)" + line 404, "pan.___", state 549, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 549, "else" + line 404, "pan.___", state 552, "(1)" + line 404, "pan.___", state 553, "(1)" + line 404, "pan.___", state 553, "(1)" + line 408, "pan.___", state 561, "(1)" + line 408, "pan.___", state 562, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 562, "else" + line 408, "pan.___", state 565, "(1)" + line 408, "pan.___", state 566, "(1)" + line 408, "pan.___", state 566, "(1)" + line 406, "pan.___", state 571, "((i<1))" + line 406, "pan.___", state 571, "((i>=1))" + line 413, "pan.___", state 578, "(1)" + line 413, "pan.___", state 579, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 579, "else" + line 413, "pan.___", state 582, "(1)" + line 413, "pan.___", state 583, "(1)" + line 413, "pan.___", state 583, "(1)" + line 417, "pan.___", state 591, "(1)" + line 417, "pan.___", state 592, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 592, "else" + line 417, "pan.___", state 595, "(1)" + line 417, "pan.___", state 596, "(1)" + line 417, "pan.___", state 596, "(1)" + line 422, "pan.___", state 605, "(1)" + line 422, "pan.___", state 605, "(1)" + line 387, "pan.___", state 612, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 614, "(1)" + line 387, "pan.___", state 615, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 615, "else" + line 387, "pan.___", state 618, "(1)" + line 391, "pan.___", state 626, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 628, "(1)" + line 391, "pan.___", state 629, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 629, "else" + line 391, "pan.___", state 632, "(1)" + line 391, "pan.___", state 633, "(1)" + line 391, "pan.___", state 633, "(1)" + line 389, "pan.___", state 638, "((i<1))" + line 389, "pan.___", state 638, "((i>=1))" + line 396, "pan.___", state 644, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 646, "(1)" + line 396, "pan.___", state 647, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 647, "else" + line 396, "pan.___", state 650, "(1)" + line 396, "pan.___", state 651, "(1)" + line 396, "pan.___", state 651, "(1)" + line 400, "pan.___", state 658, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 660, "(1)" + line 400, "pan.___", state 661, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 661, "else" + line 400, "pan.___", state 664, "(1)" + line 400, "pan.___", state 665, "(1)" + line 400, "pan.___", state 665, "(1)" + line 398, "pan.___", state 670, "((i<2))" + line 398, "pan.___", state 670, "((i>=2))" + line 404, "pan.___", state 677, "(1)" + line 404, "pan.___", state 678, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 678, "else" + line 404, "pan.___", state 681, "(1)" + line 404, "pan.___", state 682, "(1)" + line 404, "pan.___", state 682, "(1)" + line 408, "pan.___", state 690, "(1)" + line 408, "pan.___", state 691, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 691, "else" + line 408, "pan.___", state 694, "(1)" + line 408, "pan.___", state 695, "(1)" + line 408, "pan.___", state 695, "(1)" + line 406, "pan.___", state 700, "((i<1))" + line 406, "pan.___", state 700, "((i>=1))" + line 413, "pan.___", state 707, "(1)" + line 413, "pan.___", state 708, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 708, "else" + line 413, "pan.___", state 711, "(1)" + line 413, "pan.___", state 712, "(1)" + line 413, "pan.___", state 712, "(1)" + line 417, "pan.___", state 720, "(1)" + line 417, "pan.___", state 721, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 721, "else" + line 417, "pan.___", state 724, "(1)" + line 417, "pan.___", state 725, "(1)" + line 417, "pan.___", state 725, "(1)" + line 415, "pan.___", state 730, "((i<2))" + line 415, "pan.___", state 730, "((i>=2))" + line 422, "pan.___", state 734, "(1)" + line 422, "pan.___", state 734, "(1)" + line 1078, "pan.___", state 738, "_proc_urcu_writer = (_proc_urcu_writer|(1<<10))" + line 387, "pan.___", state 743, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 745, "(1)" + line 387, "pan.___", state 746, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 746, "else" + line 387, "pan.___", state 749, "(1)" + line 391, "pan.___", state 757, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 759, "(1)" + line 391, "pan.___", state 760, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 760, "else" + line 391, "pan.___", state 763, "(1)" + line 391, "pan.___", state 764, "(1)" + line 391, "pan.___", state 764, "(1)" + line 389, "pan.___", state 769, "((i<1))" + line 389, "pan.___", state 769, "((i>=1))" + line 396, "pan.___", state 775, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 777, "(1)" + line 396, "pan.___", state 778, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 778, "else" + line 396, "pan.___", state 781, "(1)" + line 396, "pan.___", state 782, "(1)" + line 396, "pan.___", state 782, "(1)" + line 400, "pan.___", state 789, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 791, "(1)" + line 400, "pan.___", state 792, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 792, "else" + line 400, "pan.___", state 795, "(1)" + line 400, "pan.___", state 796, "(1)" + line 400, "pan.___", state 796, "(1)" + line 398, "pan.___", state 801, "((i<2))" + line 398, "pan.___", state 801, "((i>=2))" + line 404, "pan.___", state 808, "(1)" + line 404, "pan.___", state 809, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 809, "else" + line 404, "pan.___", state 812, "(1)" + line 404, "pan.___", state 813, "(1)" + line 404, "pan.___", state 813, "(1)" + line 408, "pan.___", state 821, "(1)" + line 408, "pan.___", state 822, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 822, "else" + line 408, "pan.___", state 825, "(1)" + line 408, "pan.___", state 826, "(1)" + line 408, "pan.___", state 826, "(1)" + line 406, "pan.___", state 831, "((i<1))" + line 406, "pan.___", state 831, "((i>=1))" + line 413, "pan.___", state 838, "(1)" + line 413, "pan.___", state 839, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 839, "else" + line 413, "pan.___", state 842, "(1)" + line 413, "pan.___", state 843, "(1)" + line 413, "pan.___", state 843, "(1)" + line 417, "pan.___", state 851, "(1)" + line 417, "pan.___", state 852, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 852, "else" + line 417, "pan.___", state 855, "(1)" + line 417, "pan.___", state 856, "(1)" + line 417, "pan.___", state 856, "(1)" + line 415, "pan.___", state 861, "((i<2))" + line 415, "pan.___", state 861, "((i>=2))" + line 422, "pan.___", state 865, "(1)" + line 422, "pan.___", state 865, "(1)" + line 1093, "pan.___", state 870, "_proc_urcu_writer = (_proc_urcu_writer|(1<<11))" + line 1088, "pan.___", state 871, "(((tmp2&((1<<7)-1))&&((tmp2^0)&(1<<7))))" + line 1088, "pan.___", state 871, "else" + line 1113, "pan.___", state 875, "_proc_urcu_writer = (_proc_urcu_writer&~(((1<<12)|(1<<11))))" + line 250, "pan.___", state 906, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 915, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 930, "(1)" + line 262, "pan.___", state 937, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 953, "(1)" + line 231, "pan.___", state 961, "(1)" + line 235, "pan.___", state 973, "(1)" + line 239, "pan.___", state 981, "(1)" + line 250, "pan.___", state 1012, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1021, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1034, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1043, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1059, "(1)" + line 231, "pan.___", state 1067, "(1)" + line 235, "pan.___", state 1079, "(1)" + line 239, "pan.___", state 1087, "(1)" + line 254, "pan.___", state 1113, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1126, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1135, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1151, "(1)" + line 231, "pan.___", state 1159, "(1)" + line 235, "pan.___", state 1171, "(1)" + line 239, "pan.___", state 1179, "(1)" + line 250, "pan.___", state 1210, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1219, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1232, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1241, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1257, "(1)" + line 231, "pan.___", state 1265, "(1)" + line 235, "pan.___", state 1277, "(1)" + line 239, "pan.___", state 1285, "(1)" + line 250, "pan.___", state 1302, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1304, "(1)" + line 254, "pan.___", state 1311, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1313, "(1)" + line 254, "pan.___", state 1314, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1314, "else" + line 252, "pan.___", state 1319, "((i<1))" + line 252, "pan.___", state 1319, "((i>=1))" + line 258, "pan.___", state 1324, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1326, "(1)" + line 258, "pan.___", state 1327, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1327, "else" + line 262, "pan.___", state 1333, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1335, "(1)" + line 262, "pan.___", state 1336, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1336, "else" + line 260, "pan.___", state 1341, "((i<2))" + line 260, "pan.___", state 1341, "((i>=2))" + line 227, "pan.___", state 1349, "(1)" + line 231, "pan.___", state 1357, "(1)" + line 231, "pan.___", state 1358, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1358, "else" + line 229, "pan.___", state 1363, "((i<1))" + line 229, "pan.___", state 1363, "((i>=1))" + line 235, "pan.___", state 1369, "(1)" + line 235, "pan.___", state 1370, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1370, "else" + line 239, "pan.___", state 1377, "(1)" + line 239, "pan.___", state 1378, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1378, "else" + line 244, "pan.___", state 1387, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1387, "else" + line 1183, "pan.___", state 1390, "i = 0" + line 1183, "pan.___", state 1392, "reader_barrier = 1" + line 1183, "pan.___", state 1403, "((i<1))" + line 1183, "pan.___", state 1403, "((i>=1))" + line 250, "pan.___", state 1408, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1410, "(1)" + line 254, "pan.___", state 1417, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1419, "(1)" + line 254, "pan.___", state 1420, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1420, "else" + line 252, "pan.___", state 1425, "((i<1))" + line 252, "pan.___", state 1425, "((i>=1))" + line 258, "pan.___", state 1430, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1432, "(1)" + line 258, "pan.___", state 1433, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1433, "else" + line 262, "pan.___", state 1439, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1441, "(1)" + line 262, "pan.___", state 1442, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1442, "else" + line 260, "pan.___", state 1447, "((i<2))" + line 260, "pan.___", state 1447, "((i>=2))" + line 227, "pan.___", state 1455, "(1)" + line 231, "pan.___", state 1463, "(1)" + line 231, "pan.___", state 1464, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1464, "else" + line 229, "pan.___", state 1469, "((i<1))" + line 229, "pan.___", state 1469, "((i>=1))" + line 235, "pan.___", state 1475, "(1)" + line 235, "pan.___", state 1476, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1476, "else" + line 239, "pan.___", state 1483, "(1)" + line 239, "pan.___", state 1484, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1484, "else" + line 244, "pan.___", state 1493, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1493, "else" + line 277, "pan.___", state 1495, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 1495, "else" + line 1183, "pan.___", state 1496, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 1183, "pan.___", state 1496, "else" + line 254, "pan.___", state 1509, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1522, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1531, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1547, "(1)" + line 231, "pan.___", state 1555, "(1)" + line 235, "pan.___", state 1567, "(1)" + line 239, "pan.___", state 1575, "(1)" + line 250, "pan.___", state 1606, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1615, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1628, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1637, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1653, "(1)" + line 231, "pan.___", state 1661, "(1)" + line 235, "pan.___", state 1673, "(1)" + line 239, "pan.___", state 1681, "(1)" + line 1191, "pan.___", state 1697, "-end-" + (242 of 1697 states) +unreached in proctype :init: + line 1202, "pan.___", state 9, "((j<2))" + line 1202, "pan.___", state 9, "((j>=2))" + line 1203, "pan.___", state 20, "((j<2))" + line 1203, "pan.___", state 20, "((j>=2))" + line 1208, "pan.___", state 33, "((j<2))" + line 1208, "pan.___", state 33, "((j>=2))" + line 1206, "pan.___", state 43, "((i<1))" + line 1206, "pan.___", state 43, "((i>=1))" + line 1216, "pan.___", state 54, "((j<2))" + line 1216, "pan.___", state 54, "((j>=2))" + line 1220, "pan.___", state 67, "((j<2))" + line 1220, "pan.___", state 67, "((j>=2))" + (6 of 78 states) +unreached in proctype :never: + line 1250, "pan.___", state 8, "-end-" + (1 of 8 states) + +pan: elapsed time 7.32e+03 seconds +pan: rate 3363.2894 states/second +pan: avg transition delay 1.288e-06 usec +cp .input.spin urcu_free_single_flip.spin.input +cp .input.spin.trail urcu_free_single_flip.spin.input.trail +make[1]: Leaving directory `/home/compudj/doc/userspace-rcu/formal-model/urcu-controldataflow' diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_single_flip.spin.input b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_single_flip.spin.input new file mode 100644 index 0000000..4877d95 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_single_flip.spin.input @@ -0,0 +1,1227 @@ +#define SINGLE_FLIP + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* We choose to ignore writer's non-progress caused from the + * reader ignoring the writer's mb() requests */ +#ifdef WRITER_PROGRESS +progress_writer_from_reader: +#endif + break; + od; +} + +#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: +#define PROGRESS_LABEL(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; \ + /* \ + * 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) \ + do \ + :: (reader_barrier[i] == 1) -> skip; \ + :: (reader_barrier[i] == 0) -> break; \ + od; \ + i++; \ + :: i >= NR_READERS -> \ + break \ + od; \ + smp_mb(i, j); \ +} + +#else + +#define smp_mb_send(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + :: 1 -> skip; + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_single_flip.spin.input.trail b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_single_flip.spin.input.trail new file mode 100644 index 0000000..eaf1780 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_free_single_flip.spin.input.trail @@ -0,0 +1,1368 @@ +-2:3:-2 +-4:-4:-4 +1:0:4647 +2:3:4567 +3:3:4570 +4:3:4570 +5:3:4573 +6:3:4581 +7:3:4581 +8:3:4584 +9:3:4590 +10:3:4594 +11:3:4594 +12:3:4597 +13:3:4607 +14:3:4615 +15:3:4615 +16:3:4618 +17:3:4624 +18:3:4628 +19:3:4628 +20:3:4631 +21:3:4637 +22:3:4641 +23:3:4642 +24:0:4647 +25:3:4644 +26:0:4647 +27:2:2872 +28:0:4647 +29:2:2878 +30:0:4647 +31:2:2879 +32:0:4647 +33:2:2881 +34:0:4647 +35:2:2882 +36:0:4647 +37:2:2883 +38:0:4647 +39:2:2884 +40:0:4647 +41:2:2885 +42:0:4647 +43:2:2886 +44:0:4647 +45:2:2887 +46:2:2888 +47:2:2892 +48:2:2893 +49:2:2901 +50:2:2902 +51:2:2906 +52:2:2907 +53:2:2915 +54:2:2920 +55:2:2924 +56:2:2925 +57:2:2933 +58:2:2934 +59:2:2938 +60:2:2939 +61:2:2933 +62:2:2934 +63:2:2938 +64:2:2939 +65:2:2947 +66:2:2952 +67:2:2953 +68:2:2964 +69:2:2965 +70:2:2966 +71:2:2977 +72:2:2982 +73:2:2983 +74:2:2994 +75:2:2995 +76:2:2996 +77:2:2994 +78:2:2995 +79:2:2996 +80:2:3007 +81:2:3015 +82:0:4647 +83:2:2886 +84:0:4647 +85:2:3019 +86:2:3023 +87:2:3024 +88:2:3028 +89:2:3032 +90:2:3033 +91:2:3037 +92:2:3045 +93:2:3046 +94:2:3050 +95:2:3054 +96:2:3055 +97:2:3050 +98:2:3051 +99:2:3059 +100:0:4647 +101:2:2886 +102:0:4647 +103:2:3067 +104:2:3068 +105:2:3069 +106:0:4647 +107:2:2886 +108:0:4647 +109:2:3074 +110:0:4647 +111:2:3776 +112:2:3777 +113:2:3781 +114:2:3785 +115:2:3786 +116:2:3790 +117:2:3795 +118:2:3803 +119:2:3807 +120:2:3808 +121:2:3803 +122:2:3807 +123:2:3808 +124:2:3812 +125:2:3819 +126:2:3826 +127:2:3827 +128:2:3834 +129:2:3839 +130:2:3846 +131:2:3847 +132:2:3846 +133:2:3847 +134:2:3854 +135:2:3858 +136:0:4647 +137:2:3863 +138:0:4647 +139:2:3864 +140:0:4647 +141:2:3865 +142:0:4647 +143:2:3866 +144:0:4647 +145:1:2 +146:0:4647 +147:2:3867 +148:0:4647 +149:1:8 +150:0:4647 +151:1:9 +152:0:4647 +153:2:3866 +154:0:4647 +155:1:10 +156:0:4647 +157:2:3867 +158:0:4647 +159:1:11 +160:0:4647 +161:2:3866 +162:0:4647 +163:1:12 +164:0:4647 +165:2:3867 +166:0:4647 +167:1:13 +168:0:4647 +169:2:3866 +170:0:4647 +171:1:14 +172:0:4647 +173:2:3867 +174:0:4647 +175:1:15 +176:0:4647 +177:1:16 +178:0:4647 +179:2:3866 +180:0:4647 +181:1:17 +182:0:4647 +183:2:3867 +184:0:4647 +185:1:28 +186:0:4647 +187:2:3866 +188:0:4647 +189:1:32 +190:1:33 +191:1:37 +192:1:41 +193:1:42 +194:1:46 +195:1:54 +196:1:55 +197:1:59 +198:1:63 +199:1:64 +200:1:59 +201:1:63 +202:1:64 +203:1:68 +204:1:75 +205:1:82 +206:1:83 +207:1:90 +208:1:95 +209:1:102 +210:1:103 +211:1:102 +212:1:103 +213:1:110 +214:1:114 +215:0:4647 +216:2:3867 +217:0:4647 +218:1:119 +219:0:4647 +220:2:3868 +221:0:4647 +222:2:3873 +223:0:4647 +224:2:3874 +225:0:4647 +226:2:3882 +227:2:3883 +228:2:3887 +229:2:3891 +230:2:3892 +231:2:3896 +232:2:3904 +233:2:3905 +234:2:3909 +235:2:3913 +236:2:3914 +237:2:3909 +238:2:3913 +239:2:3914 +240:2:3918 +241:2:3925 +242:2:3932 +243:2:3933 +244:2:3940 +245:2:3945 +246:2:3952 +247:2:3953 +248:2:3952 +249:2:3953 +250:2:3960 +251:2:3964 +252:0:4647 +253:2:3076 +254:2:3757 +255:0:4647 +256:2:2886 +257:0:4647 +258:2:3077 +259:0:4647 +260:2:2886 +261:0:4647 +262:2:3080 +263:2:3081 +264:2:3085 +265:2:3086 +266:2:3094 +267:2:3095 +268:2:3099 +269:2:3100 +270:2:3108 +271:2:3113 +272:2:3117 +273:2:3118 +274:2:3126 +275:2:3127 +276:2:3131 +277:2:3132 +278:2:3126 +279:2:3127 +280:2:3131 +281:2:3132 +282:2:3140 +283:2:3145 +284:2:3146 +285:2:3157 +286:2:3158 +287:2:3159 +288:2:3170 +289:2:3175 +290:2:3176 +291:2:3187 +292:2:3188 +293:2:3189 +294:2:3187 +295:2:3188 +296:2:3189 +297:2:3200 +298:2:3207 +299:0:4647 +300:2:2886 +301:0:4647 +302:2:3211 +303:2:3212 +304:2:3213 +305:2:3225 +306:2:3226 +307:2:3230 +308:2:3231 +309:2:3239 +310:2:3244 +311:2:3248 +312:2:3249 +313:2:3257 +314:2:3258 +315:2:3262 +316:2:3263 +317:2:3257 +318:2:3258 +319:2:3262 +320:2:3263 +321:2:3271 +322:2:3276 +323:2:3277 +324:2:3288 +325:2:3289 +326:2:3290 +327:2:3301 +328:2:3306 +329:2:3307 +330:2:3318 +331:2:3319 +332:2:3320 +333:2:3318 +334:2:3319 +335:2:3320 +336:2:3331 +337:2:3341 +338:2:3342 +339:0:4647 +340:2:2886 +341:0:4647 +342:2:3745 +343:0:4647 +344:2:4370 +345:2:4371 +346:2:4375 +347:2:4379 +348:2:4380 +349:2:4384 +350:2:4392 +351:2:4393 +352:2:4397 +353:2:4401 +354:2:4402 +355:2:4397 +356:2:4401 +357:2:4402 +358:2:4406 +359:2:4413 +360:2:4420 +361:2:4421 +362:2:4428 +363:2:4433 +364:2:4440 +365:2:4441 +366:2:4440 +367:2:4441 +368:2:4448 +369:2:4452 +370:0:4647 +371:2:4457 +372:0:4647 +373:2:4458 +374:0:4647 +375:2:4459 +376:0:4647 +377:2:4460 +378:0:4647 +379:1:120 +380:0:4647 +381:2:4461 +382:0:4647 +383:1:19 +384:0:4647 +385:2:4460 +386:0:4647 +387:1:127 +388:1:128 +389:1:132 +390:1:133 +391:1:141 +392:1:142 +393:1:146 +394:1:147 +395:1:155 +396:1:160 +397:1:164 +398:1:165 +399:1:173 +400:1:174 +401:1:178 +402:1:179 +403:1:173 +404:1:174 +405:1:178 +406:1:179 +407:1:187 +408:1:199 +409:1:200 +410:1:204 +411:1:205 +412:1:206 +413:1:217 +414:1:222 +415:1:223 +416:1:234 +417:1:235 +418:1:236 +419:1:234 +420:1:235 +421:1:236 +422:1:247 +423:0:4647 +424:2:4461 +425:0:4647 +426:1:15 +427:0:4647 +428:1:16 +429:0:4647 +430:2:4460 +431:0:4647 +432:1:17 +433:0:4647 +434:2:4461 +435:0:4647 +436:1:120 +437:0:4647 +438:2:4460 +439:0:4647 +440:1:19 +441:0:4647 +442:2:4461 +443:0:4647 +444:1:256 +445:1:257 +446:0:4647 +447:1:15 +448:0:4647 +449:1:16 +450:0:4647 +451:2:4460 +452:0:4647 +453:1:17 +454:0:4647 +455:2:4461 +456:0:4647 +457:1:120 +458:0:4647 +459:2:4460 +460:0:4647 +461:1:19 +462:0:4647 +463:2:4461 +464:0:4647 +465:1:263 +466:1:264 +467:1:268 +468:1:269 +469:1:277 +470:1:278 +471:1:282 +472:1:283 +473:1:291 +474:1:296 +475:1:300 +476:1:301 +477:1:309 +478:1:310 +479:1:314 +480:1:315 +481:1:309 +482:1:310 +483:1:314 +484:1:315 +485:1:323 +486:1:335 +487:1:336 +488:1:340 +489:1:341 +490:1:342 +491:1:353 +492:1:358 +493:1:359 +494:1:370 +495:1:371 +496:1:372 +497:1:370 +498:1:371 +499:1:372 +500:1:383 +501:0:4647 +502:1:15 +503:0:4647 +504:1:16 +505:0:4647 +506:2:4460 +507:0:4647 +508:1:17 +509:0:4647 +510:2:4461 +511:0:4647 +512:1:28 +513:0:4647 +514:2:4460 +515:0:4647 +516:1:32 +517:1:33 +518:1:37 +519:1:41 +520:1:42 +521:1:46 +522:1:54 +523:1:55 +524:1:59 +525:1:63 +526:1:64 +527:1:59 +528:1:63 +529:1:64 +530:1:68 +531:1:75 +532:1:82 +533:1:83 +534:1:90 +535:1:95 +536:1:102 +537:1:103 +538:1:102 +539:1:103 +540:1:110 +541:1:114 +542:0:4647 +543:2:4461 +544:0:4647 +545:1:119 +546:0:4647 +547:2:4462 +548:0:4647 +549:2:4467 +550:0:4647 +551:2:4468 +552:0:4647 +553:2:4476 +554:2:4477 +555:2:4481 +556:2:4485 +557:2:4486 +558:2:4490 +559:2:4498 +560:2:4499 +561:2:4503 +562:2:4507 +563:2:4508 +564:2:4503 +565:2:4507 +566:2:4508 +567:2:4512 +568:2:4519 +569:2:4526 +570:2:4527 +571:2:4534 +572:2:4539 +573:2:4546 +574:2:4547 +575:2:4546 +576:2:4547 +577:2:4554 +578:2:4558 +579:0:4647 +580:2:3747 +581:2:3757 +582:0:4647 +583:2:2886 +584:0:4647 +585:2:3748 +586:2:3749 +587:0:4647 +588:2:2886 +589:0:4647 +590:2:3753 +591:0:4647 +592:2:3761 +593:0:4647 +594:2:2879 +595:0:4647 +596:2:2881 +597:0:4647 +598:2:2882 +599:0:4647 +600:2:2883 +601:0:4647 +602:2:2884 +603:0:4647 +604:2:2885 +605:0:4647 +606:2:2886 +607:0:4647 +608:2:2887 +609:2:2888 +610:2:2892 +611:2:2893 +612:2:2901 +613:2:2902 +614:2:2906 +615:2:2907 +616:2:2915 +617:2:2920 +618:2:2924 +619:2:2925 +620:2:2933 +621:2:2934 +622:2:2935 +623:2:2933 +624:2:2934 +625:2:2938 +626:2:2939 +627:2:2947 +628:2:2952 +629:2:2953 +630:2:2964 +631:2:2965 +632:2:2966 +633:2:2977 +634:2:2982 +635:2:2983 +636:2:2994 +637:2:2995 +638:2:2996 +639:2:2994 +640:2:2995 +641:2:2996 +642:2:3007 +643:2:3015 +644:0:4647 +645:2:2886 +646:0:4647 +647:2:3019 +648:2:3023 +649:2:3024 +650:2:3028 +651:2:3032 +652:2:3033 +653:2:3037 +654:2:3045 +655:2:3046 +656:2:3050 +657:2:3051 +658:2:3050 +659:2:3054 +660:2:3055 +661:2:3059 +662:0:4647 +663:2:2886 +664:0:4647 +665:2:3067 +666:2:3068 +667:2:3069 +668:0:4647 +669:2:2886 +670:0:4647 +671:2:3074 +672:0:4647 +673:2:3776 +674:2:3777 +675:2:3781 +676:2:3785 +677:2:3786 +678:2:3790 +679:2:3795 +680:2:3803 +681:2:3807 +682:2:3808 +683:2:3803 +684:2:3807 +685:2:3808 +686:2:3812 +687:2:3819 +688:2:3826 +689:2:3827 +690:2:3834 +691:2:3839 +692:2:3846 +693:2:3847 +694:2:3846 +695:2:3847 +696:2:3854 +697:2:3858 +698:0:4647 +699:2:3863 +700:0:4647 +701:2:3864 +702:0:4647 +703:2:3865 +704:0:4647 +705:2:3866 +706:0:4647 +707:1:120 +708:0:4647 +709:2:3867 +710:0:4647 +711:1:19 +712:0:4647 +713:2:3866 +714:0:4647 +715:1:392 +716:1:393 +717:1:397 +718:1:398 +719:1:406 +720:1:407 +721:1:411 +722:1:412 +723:1:420 +724:1:425 +725:1:429 +726:1:430 +727:1:438 +728:1:439 +729:1:443 +730:1:444 +731:1:438 +732:1:439 +733:1:443 +734:1:444 +735:1:452 +736:1:457 +737:1:458 +738:1:469 +739:1:470 +740:1:471 +741:1:482 +742:1:494 +743:1:495 +744:1:499 +745:1:500 +746:1:501 +747:1:499 +748:1:500 +749:1:501 +750:1:512 +751:1:519 +752:0:4647 +753:2:3867 +754:0:4647 +755:1:15 +756:0:4647 +757:1:16 +758:0:4647 +759:2:3866 +760:0:4647 +761:1:17 +762:0:4647 +763:2:3867 +764:0:4647 +765:1:120 +766:0:4647 +767:2:3866 +768:0:4647 +769:1:19 +770:0:4647 +771:2:3867 +772:0:4647 +773:1:657 +774:1:658 +775:1:662 +776:1:663 +777:1:671 +778:1:672 +779:1:673 +780:1:685 +781:1:690 +782:1:694 +783:1:695 +784:1:703 +785:1:704 +786:1:708 +787:1:709 +788:1:703 +789:1:704 +790:1:708 +791:1:709 +792:1:717 +793:1:722 +794:1:723 +795:1:734 +796:1:735 +797:1:736 +798:1:747 +799:1:759 +800:1:760 +801:1:764 +802:1:765 +803:1:766 +804:1:764 +805:1:765 +806:1:766 +807:1:777 +808:0:4647 +809:1:15 +810:0:4647 +811:1:16 +812:0:4647 +813:2:3866 +814:0:4647 +815:1:17 +816:0:4647 +817:2:3867 +818:0:4647 +819:1:120 +820:0:4647 +821:2:3866 +822:0:4647 +823:1:19 +824:0:4647 +825:2:3867 +826:0:4647 +827:1:786 +828:1:789 +829:1:790 +830:0:4647 +831:1:15 +832:0:4647 +833:1:16 +834:0:4647 +835:2:3866 +836:0:4647 +837:1:17 +838:0:4647 +839:2:3867 +840:0:4647 +841:1:120 +842:0:4647 +843:2:3866 +844:0:4647 +845:1:19 +846:0:4647 +847:2:3867 +848:0:4647 +849:1:1053 +850:1:1054 +851:1:1058 +852:1:1059 +853:1:1067 +854:1:1068 +855:1:1072 +856:1:1073 +857:1:1081 +858:1:1086 +859:1:1090 +860:1:1091 +861:1:1099 +862:1:1100 +863:1:1104 +864:1:1105 +865:1:1099 +866:1:1100 +867:1:1104 +868:1:1105 +869:1:1113 +870:1:1118 +871:1:1119 +872:1:1130 +873:1:1131 +874:1:1132 +875:1:1143 +876:1:1155 +877:1:1156 +878:1:1160 +879:1:1161 +880:1:1162 +881:1:1160 +882:1:1161 +883:1:1162 +884:1:1173 +885:1:1180 +886:1:1184 +887:0:4647 +888:1:15 +889:0:4647 +890:1:16 +891:0:4647 +892:2:3866 +893:0:4647 +894:1:17 +895:0:4647 +896:2:3867 +897:0:4647 +898:1:120 +899:0:4647 +900:2:3866 +901:0:4647 +902:1:19 +903:0:4647 +904:2:3867 +905:0:4647 +906:1:1185 +907:1:1186 +908:1:1190 +909:1:1191 +910:1:1199 +911:1:1200 +912:1:1201 +913:1:1213 +914:1:1218 +915:1:1222 +916:1:1223 +917:1:1231 +918:1:1232 +919:1:1236 +920:1:1237 +921:1:1231 +922:1:1232 +923:1:1236 +924:1:1237 +925:1:1245 +926:1:1250 +927:1:1251 +928:1:1262 +929:1:1263 +930:1:1264 +931:1:1275 +932:1:1287 +933:1:1288 +934:1:1292 +935:1:1293 +936:1:1294 +937:1:1292 +938:1:1293 +939:1:1294 +940:1:1305 +941:0:4647 +942:1:15 +943:0:4647 +944:1:16 +945:0:4647 +946:2:3866 +947:0:4647 +948:1:17 +949:0:4647 +950:2:3867 +951:0:4647 +952:1:28 +953:0:4647 +954:2:3866 +955:0:4647 +956:1:32 +957:1:33 +958:1:37 +959:1:41 +960:1:42 +961:1:46 +962:1:54 +963:1:55 +964:1:59 +965:1:63 +966:1:64 +967:1:59 +968:1:63 +969:1:64 +970:1:68 +971:1:75 +972:1:82 +973:1:83 +974:1:90 +975:1:95 +976:1:102 +977:1:103 +978:1:102 +979:1:103 +980:1:110 +981:1:114 +982:0:4647 +983:2:3867 +984:0:4647 +985:1:119 +986:0:4647 +987:2:3868 +988:0:4647 +989:2:3873 +990:0:4647 +991:2:3874 +992:0:4647 +993:2:3882 +994:2:3883 +995:2:3887 +996:2:3891 +997:2:3892 +998:2:3896 +999:2:3904 +1000:2:3905 +1001:2:3909 +1002:2:3913 +1003:2:3914 +1004:2:3909 +1005:2:3913 +1006:2:3914 +1007:2:3918 +1008:2:3925 +1009:2:3932 +1010:2:3933 +1011:2:3940 +1012:2:3945 +1013:2:3952 +1014:2:3953 +1015:2:3952 +1016:2:3953 +1017:2:3960 +1018:2:3964 +1019:0:4647 +1020:2:3076 +1021:2:3757 +1022:0:4647 +1023:2:2886 +1024:0:4647 +1025:2:3077 +1026:0:4647 +1027:2:2886 +1028:0:4647 +1029:2:3080 +1030:2:3081 +1031:2:3085 +1032:2:3086 +1033:2:3094 +1034:2:3095 +1035:2:3099 +1036:2:3100 +1037:2:3108 +1038:2:3113 +1039:2:3117 +1040:2:3118 +1041:2:3126 +1042:2:3127 +1043:2:3131 +1044:2:3132 +1045:2:3126 +1046:2:3127 +1047:2:3131 +1048:2:3132 +1049:2:3140 +1050:2:3145 +1051:2:3146 +1052:2:3157 +1053:2:3158 +1054:2:3159 +1055:2:3170 +1056:2:3175 +1057:2:3176 +1058:2:3187 +1059:2:3188 +1060:2:3189 +1061:2:3187 +1062:2:3188 +1063:2:3189 +1064:2:3200 +1065:2:3207 +1066:0:4647 +1067:2:2886 +1068:0:4647 +1069:2:3211 +1070:2:3212 +1071:2:3213 +1072:2:3225 +1073:2:3226 +1074:2:3230 +1075:2:3231 +1076:2:3239 +1077:2:3244 +1078:2:3248 +1079:2:3249 +1080:2:3257 +1081:2:3258 +1082:2:3262 +1083:2:3263 +1084:2:3257 +1085:2:3258 +1086:2:3262 +1087:2:3263 +1088:2:3271 +1089:2:3276 +1090:2:3277 +1091:2:3288 +1092:2:3289 +1093:2:3290 +1094:2:3301 +1095:2:3306 +1096:2:3307 +1097:2:3318 +1098:2:3319 +1099:2:3320 +1100:2:3318 +1101:2:3319 +1102:2:3320 +1103:2:3331 +1104:2:3341 +1105:2:3342 +1106:0:4647 +1107:2:2886 +1108:0:4647 +1109:2:3745 +1110:0:4647 +1111:2:4370 +1112:2:4371 +1113:2:4375 +1114:2:4379 +1115:2:4380 +1116:2:4384 +1117:2:4392 +1118:2:4393 +1119:2:4397 +1120:2:4401 +1121:2:4402 +1122:2:4397 +1123:2:4401 +1124:2:4402 +1125:2:4406 +1126:2:4413 +1127:2:4420 +1128:2:4421 +1129:2:4428 +1130:2:4433 +1131:2:4440 +1132:2:4441 +1133:2:4440 +1134:2:4441 +1135:2:4448 +1136:2:4452 +1137:0:4647 +1138:2:4457 +1139:0:4647 +1140:2:4458 +1141:0:4647 +1142:2:4459 +1143:0:4647 +1144:2:4460 +1145:0:4647 +1146:1:28 +1147:0:4647 +1148:2:4461 +1149:0:4647 +1150:1:32 +1151:1:33 +1152:1:37 +1153:1:41 +1154:1:42 +1155:1:46 +1156:1:54 +1157:1:55 +1158:1:59 +1159:1:63 +1160:1:64 +1161:1:59 +1162:1:63 +1163:1:64 +1164:1:68 +1165:1:75 +1166:1:82 +1167:1:83 +1168:1:90 +1169:1:95 +1170:1:102 +1171:1:103 +1172:1:102 +1173:1:103 +1174:1:110 +1175:1:114 +1176:0:4647 +1177:2:4460 +1178:0:4647 +1179:1:119 +1180:0:4647 +1181:2:4461 +1182:0:4647 +1183:2:4462 +1184:0:4647 +1185:2:4467 +1186:0:4647 +1187:2:4468 +1188:0:4647 +1189:2:4476 +1190:2:4477 +1191:2:4481 +1192:2:4485 +1193:2:4486 +1194:2:4490 +1195:2:4498 +1196:2:4499 +1197:2:4503 +1198:2:4507 +1199:2:4508 +1200:2:4503 +1201:2:4507 +1202:2:4508 +1203:2:4512 +1204:2:4519 +1205:2:4526 +1206:2:4527 +1207:2:4534 +1208:2:4539 +1209:2:4546 +1210:2:4547 +1211:2:4546 +1212:2:4547 +1213:2:4554 +1214:2:4558 +1215:0:4647 +1216:2:3747 +1217:2:3757 +1218:0:4647 +1219:2:2886 +1220:0:4647 +1221:2:3748 +1222:2:3749 +1223:0:4647 +1224:2:2886 +1225:0:4647 +1226:2:3753 +1227:0:4647 +1228:2:3761 +1229:0:4647 +1230:2:2879 +1231:0:4647 +1232:2:2881 +1233:0:4647 +1234:2:2882 +1235:0:4647 +1236:2:2883 +1237:0:4647 +1238:2:2884 +1239:0:4647 +1240:2:2885 +1241:0:4647 +1242:2:2886 +1243:0:4647 +1244:2:2887 +1245:2:2888 +1246:2:2892 +1247:2:2893 +1248:2:2901 +1249:2:2902 +1250:2:2906 +1251:2:2907 +1252:2:2915 +1253:2:2920 +1254:2:2924 +1255:2:2925 +1256:2:2933 +1257:2:2934 +1258:2:2938 +1259:2:2939 +1260:2:2933 +1261:2:2934 +1262:2:2935 +1263:2:2947 +1264:2:2952 +1265:2:2953 +1266:2:2964 +1267:2:2965 +1268:2:2966 +1269:2:2977 +1270:2:2982 +1271:2:2983 +1272:2:2994 +1273:2:2995 +1274:2:2996 +1275:2:2994 +1276:2:2995 +1277:2:2996 +1278:2:3007 +1279:2:3015 +1280:0:4647 +1281:2:2886 +1282:0:4647 +1283:1:120 +1284:0:4647 +1285:1:19 +1286:0:4647 +1287:1:1314 +1288:0:4647 +1289:1:2778 +1290:1:2785 +1291:1:2786 +1292:1:2793 +1293:1:2798 +1294:1:2805 +1295:1:2806 +1296:1:2805 +1297:1:2806 +1298:1:2813 +1299:1:2817 +1300:0:4647 +1301:2:3019 +1302:2:3023 +1303:2:3024 +1304:2:3028 +1305:2:3032 +1306:2:3033 +1307:2:3037 +1308:2:3045 +1309:2:3046 +1310:2:3050 +1311:2:3054 +1312:2:3055 +1313:2:3050 +1314:2:3051 +1315:2:3059 +1316:0:4647 +1317:2:2886 +1318:0:4647 +1319:2:3067 +1320:2:3068 +1321:2:3069 +1322:0:4647 +1323:2:2886 +1324:0:4647 +1325:2:3074 +1326:0:4647 +1327:2:3776 +1328:2:3777 +1329:2:3781 +1330:2:3785 +1331:2:3786 +1332:2:3790 +1333:2:3795 +1334:2:3803 +1335:2:3807 +1336:2:3808 +1337:2:3803 +1338:2:3807 +1339:2:3808 +1340:2:3812 +1341:2:3819 +1342:2:3826 +1343:2:3827 +1344:2:3834 +1345:2:3839 +1346:2:3846 +1347:2:3847 +1348:2:3846 +1349:2:3847 +1350:2:3854 +1351:2:3858 +1352:0:4647 +1353:2:3863 +1354:0:4647 +1355:2:3864 +1356:0:4647 +1357:2:3865 +1358:0:4647 +1359:2:3866 +1360:0:4647 +1361:1:1316 +1362:1:1317 +1363:0:4645 +1364:2:3867 +1365:0:4651 +1366:0:4647 diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress.ltl b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress.ltl new file mode 100644 index 0000000..8718641 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress.ltl @@ -0,0 +1 @@ +([] <> !np_) diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_reader.define b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_reader.define new file mode 100644 index 0000000..ff3f783 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_reader.define @@ -0,0 +1 @@ +#define READER_PROGRESS diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_reader.log b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_reader.log new file mode 100644 index 0000000..c7614b5 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_reader.log @@ -0,0 +1,1513 @@ +make[1]: Entering directory `/home/compudj/doc/userspace-rcu/formal-model/urcu-controldataflow' +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define > pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_progress.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_progress_reader.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -f -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1245) +depth 23: Claim reached state 9 (line 1250) +depth 145: Claim reached state 9 (line 1249) +pan: acceptance cycle (at depth 2922) +pan: wrote .input.spin.trail + +(Spin Version 5.1.7 -- 23 December 2008) +Warning: Search not completed + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness enabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 3023, errors: 1 + 604 states, stored (989 visited) + 16933 states, matched + 17922 transitions (= visited+matched) + 100982 atomic steps +hash conflicts: 1 (resolved) + +Stats on memory usage (in Megabytes): + 0.067 equivalent memory usage for states (stored*(State-vector + overhead)) + 0.718 actual memory usage for states (unsuccessful compression: 1075.20%) + state-vector as stored = 1219 byte + 28 byte overhead + 8.000 memory used for hash table (-w20) + 457.764 memory used for DFS stack (-m10000000) + 466.447 total actual memory usage + +unreached in proctype urcu_reader + line 250, "pan.___", state 32, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 41, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 252, "pan.___", state 49, "((i<1))" + line 252, "pan.___", state 49, "((i>=1))" + line 258, "pan.___", state 54, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 63, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 260, "pan.___", state 71, "((i<2))" + line 260, "pan.___", state 71, "((i>=2))" + line 227, "pan.___", state 79, "(1)" + line 231, "pan.___", state 87, "(1)" + line 231, "pan.___", state 88, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 88, "else" + line 229, "pan.___", state 93, "((i<1))" + line 229, "pan.___", state 93, "((i>=1))" + line 235, "pan.___", state 99, "(1)" + line 235, "pan.___", state 100, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 100, "else" + line 239, "pan.___", state 107, "(1)" + line 239, "pan.___", state 108, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 108, "else" + line 244, "pan.___", state 117, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 117, "else" + line 387, "pan.___", state 132, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 138, "(1)" + line 391, "pan.___", state 146, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 152, "(1)" + line 391, "pan.___", state 153, "(1)" + line 391, "pan.___", state 153, "(1)" + line 389, "pan.___", state 158, "((i<1))" + line 389, "pan.___", state 158, "((i>=1))" + line 396, "pan.___", state 164, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 170, "(1)" + line 396, "pan.___", state 171, "(1)" + line 396, "pan.___", state 171, "(1)" + line 400, "pan.___", state 178, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 184, "(1)" + line 400, "pan.___", state 185, "(1)" + line 400, "pan.___", state 185, "(1)" + line 398, "pan.___", state 190, "((i<2))" + line 398, "pan.___", state 190, "((i>=2))" + line 404, "pan.___", state 197, "(1)" + line 404, "pan.___", state 198, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 198, "else" + line 404, "pan.___", state 201, "(1)" + line 404, "pan.___", state 202, "(1)" + line 404, "pan.___", state 202, "(1)" + line 408, "pan.___", state 210, "(1)" + line 408, "pan.___", state 211, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 211, "else" + line 408, "pan.___", state 214, "(1)" + line 408, "pan.___", state 215, "(1)" + line 408, "pan.___", state 215, "(1)" + line 406, "pan.___", state 220, "((i<1))" + line 406, "pan.___", state 220, "((i>=1))" + line 413, "pan.___", state 227, "(1)" + line 413, "pan.___", state 228, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 228, "else" + line 413, "pan.___", state 231, "(1)" + line 413, "pan.___", state 232, "(1)" + line 413, "pan.___", state 232, "(1)" + line 417, "pan.___", state 240, "(1)" + line 417, "pan.___", state 241, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 241, "else" + line 417, "pan.___", state 244, "(1)" + line 417, "pan.___", state 245, "(1)" + line 417, "pan.___", state 245, "(1)" + line 422, "pan.___", state 254, "(1)" + line 422, "pan.___", state 254, "(1)" + line 663, "pan.___", state 261, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 663, "pan.___", state 262, "(!((tmp&((1<<7)-1))))" + line 663, "pan.___", state 262, "else" + line 387, "pan.___", state 268, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 274, "(1)" + line 391, "pan.___", state 282, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 288, "(1)" + line 391, "pan.___", state 289, "(1)" + line 391, "pan.___", state 289, "(1)" + line 389, "pan.___", state 294, "((i<1))" + line 389, "pan.___", state 294, "((i>=1))" + line 396, "pan.___", state 300, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 306, "(1)" + line 396, "pan.___", state 307, "(1)" + line 396, "pan.___", state 307, "(1)" + line 400, "pan.___", state 314, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 320, "(1)" + line 400, "pan.___", state 321, "(1)" + line 400, "pan.___", state 321, "(1)" + line 398, "pan.___", state 326, "((i<2))" + line 398, "pan.___", state 326, "((i>=2))" + line 404, "pan.___", state 333, "(1)" + line 404, "pan.___", state 334, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 334, "else" + line 404, "pan.___", state 337, "(1)" + line 404, "pan.___", state 338, "(1)" + line 404, "pan.___", state 338, "(1)" + line 408, "pan.___", state 346, "(1)" + line 408, "pan.___", state 347, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 347, "else" + line 408, "pan.___", state 350, "(1)" + line 408, "pan.___", state 351, "(1)" + line 408, "pan.___", state 351, "(1)" + line 406, "pan.___", state 356, "((i<1))" + line 406, "pan.___", state 356, "((i>=1))" + line 413, "pan.___", state 363, "(1)" + line 413, "pan.___", state 364, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 364, "else" + line 413, "pan.___", state 367, "(1)" + line 413, "pan.___", state 368, "(1)" + line 413, "pan.___", state 368, "(1)" + line 417, "pan.___", state 376, "(1)" + line 417, "pan.___", state 377, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 377, "else" + line 417, "pan.___", state 380, "(1)" + line 417, "pan.___", state 381, "(1)" + line 417, "pan.___", state 381, "(1)" + line 422, "pan.___", state 390, "(1)" + line 422, "pan.___", state 390, "(1)" + line 387, "pan.___", state 397, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 403, "(1)" + line 391, "pan.___", state 411, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 417, "(1)" + line 391, "pan.___", state 418, "(1)" + line 391, "pan.___", state 418, "(1)" + line 389, "pan.___", state 423, "((i<1))" + line 389, "pan.___", state 423, "((i>=1))" + line 396, "pan.___", state 429, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 435, "(1)" + line 396, "pan.___", state 436, "(1)" + line 396, "pan.___", state 436, "(1)" + line 400, "pan.___", state 443, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 449, "(1)" + line 400, "pan.___", state 450, "(1)" + line 400, "pan.___", state 450, "(1)" + line 398, "pan.___", state 455, "((i<2))" + line 398, "pan.___", state 455, "((i>=2))" + line 404, "pan.___", state 462, "(1)" + line 404, "pan.___", state 463, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 463, "else" + line 404, "pan.___", state 466, "(1)" + line 404, "pan.___", state 467, "(1)" + line 404, "pan.___", state 467, "(1)" + line 408, "pan.___", state 475, "(1)" + line 408, "pan.___", state 476, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 476, "else" + line 408, "pan.___", state 479, "(1)" + line 408, "pan.___", state 480, "(1)" + line 408, "pan.___", state 480, "(1)" + line 406, "pan.___", state 485, "((i<1))" + line 406, "pan.___", state 485, "((i>=1))" + line 413, "pan.___", state 492, "(1)" + line 413, "pan.___", state 493, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 493, "else" + line 413, "pan.___", state 496, "(1)" + line 413, "pan.___", state 497, "(1)" + line 413, "pan.___", state 497, "(1)" + line 417, "pan.___", state 505, "(1)" + line 417, "pan.___", state 506, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 506, "else" + line 417, "pan.___", state 509, "(1)" + line 417, "pan.___", state 510, "(1)" + line 417, "pan.___", state 510, "(1)" + line 415, "pan.___", state 515, "((i<2))" + line 415, "pan.___", state 515, "((i>=2))" + line 422, "pan.___", state 519, "(1)" + line 422, "pan.___", state 519, "(1)" + line 387, "pan.___", state 528, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 530, "(1)" + line 387, "pan.___", state 531, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 531, "else" + line 387, "pan.___", state 534, "(1)" + line 391, "pan.___", state 542, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 544, "(1)" + line 391, "pan.___", state 545, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 545, "else" + line 391, "pan.___", state 548, "(1)" + line 391, "pan.___", state 549, "(1)" + line 391, "pan.___", state 549, "(1)" + line 389, "pan.___", state 554, "((i<1))" + line 389, "pan.___", state 554, "((i>=1))" + line 396, "pan.___", state 560, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 562, "(1)" + line 396, "pan.___", state 563, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 563, "else" + line 396, "pan.___", state 566, "(1)" + line 396, "pan.___", state 567, "(1)" + line 396, "pan.___", state 567, "(1)" + line 400, "pan.___", state 574, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 576, "(1)" + line 400, "pan.___", state 577, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 577, "else" + line 400, "pan.___", state 580, "(1)" + line 400, "pan.___", state 581, "(1)" + line 400, "pan.___", state 581, "(1)" + line 398, "pan.___", state 586, "((i<2))" + line 398, "pan.___", state 586, "((i>=2))" + line 404, "pan.___", state 593, "(1)" + line 404, "pan.___", state 594, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 594, "else" + line 404, "pan.___", state 597, "(1)" + line 404, "pan.___", state 598, "(1)" + line 404, "pan.___", state 598, "(1)" + line 408, "pan.___", state 606, "(1)" + line 408, "pan.___", state 607, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 607, "else" + line 408, "pan.___", state 610, "(1)" + line 408, "pan.___", state 611, "(1)" + line 408, "pan.___", state 611, "(1)" + line 406, "pan.___", state 616, "((i<1))" + line 406, "pan.___", state 616, "((i>=1))" + line 413, "pan.___", state 623, "(1)" + line 413, "pan.___", state 624, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 624, "else" + line 413, "pan.___", state 627, "(1)" + line 413, "pan.___", state 628, "(1)" + line 413, "pan.___", state 628, "(1)" + line 417, "pan.___", state 636, "(1)" + line 417, "pan.___", state 637, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 637, "else" + line 417, "pan.___", state 640, "(1)" + line 417, "pan.___", state 641, "(1)" + line 417, "pan.___", state 641, "(1)" + line 415, "pan.___", state 646, "((i<2))" + line 415, "pan.___", state 646, "((i>=2))" + line 422, "pan.___", state 650, "(1)" + line 422, "pan.___", state 650, "(1)" + line 663, "pan.___", state 653, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 663, "pan.___", state 654, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 663, "pan.___", state 655, "(1)" + line 387, "pan.___", state 662, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 668, "(1)" + line 391, "pan.___", state 678, "(1)" + line 391, "pan.___", state 679, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 679, "else" + line 391, "pan.___", state 682, "(1)" + line 391, "pan.___", state 683, "(1)" + line 391, "pan.___", state 683, "(1)" + line 389, "pan.___", state 688, "((i<1))" + line 389, "pan.___", state 688, "((i>=1))" + line 396, "pan.___", state 694, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 700, "(1)" + line 396, "pan.___", state 701, "(1)" + line 396, "pan.___", state 701, "(1)" + line 400, "pan.___", state 708, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 714, "(1)" + line 400, "pan.___", state 715, "(1)" + line 400, "pan.___", state 715, "(1)" + line 398, "pan.___", state 720, "((i<2))" + line 398, "pan.___", state 720, "((i>=2))" + line 404, "pan.___", state 727, "(1)" + line 404, "pan.___", state 728, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 728, "else" + line 404, "pan.___", state 731, "(1)" + line 404, "pan.___", state 732, "(1)" + line 404, "pan.___", state 732, "(1)" + line 408, "pan.___", state 740, "(1)" + line 408, "pan.___", state 741, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 741, "else" + line 408, "pan.___", state 744, "(1)" + line 408, "pan.___", state 745, "(1)" + line 408, "pan.___", state 745, "(1)" + line 406, "pan.___", state 750, "((i<1))" + line 406, "pan.___", state 750, "((i>=1))" + line 413, "pan.___", state 757, "(1)" + line 413, "pan.___", state 758, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 758, "else" + line 413, "pan.___", state 761, "(1)" + line 413, "pan.___", state 762, "(1)" + line 413, "pan.___", state 762, "(1)" + line 417, "pan.___", state 770, "(1)" + line 417, "pan.___", state 771, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 771, "else" + line 417, "pan.___", state 774, "(1)" + line 417, "pan.___", state 775, "(1)" + line 417, "pan.___", state 775, "(1)" + line 422, "pan.___", state 784, "(1)" + line 422, "pan.___", state 784, "(1)" + line 387, "pan.___", state 798, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 800, "(1)" + line 387, "pan.___", state 801, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 801, "else" + line 387, "pan.___", state 804, "(1)" + line 391, "pan.___", state 812, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 814, "(1)" + line 391, "pan.___", state 815, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 815, "else" + line 391, "pan.___", state 818, "(1)" + line 391, "pan.___", state 819, "(1)" + line 391, "pan.___", state 819, "(1)" + line 389, "pan.___", state 824, "((i<1))" + line 389, "pan.___", state 824, "((i>=1))" + line 396, "pan.___", state 830, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 832, "(1)" + line 396, "pan.___", state 833, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 833, "else" + line 396, "pan.___", state 836, "(1)" + line 396, "pan.___", state 837, "(1)" + line 396, "pan.___", state 837, "(1)" + line 400, "pan.___", state 844, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 846, "(1)" + line 400, "pan.___", state 847, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 847, "else" + line 400, "pan.___", state 850, "(1)" + line 400, "pan.___", state 851, "(1)" + line 400, "pan.___", state 851, "(1)" + line 398, "pan.___", state 856, "((i<2))" + line 398, "pan.___", state 856, "((i>=2))" + line 404, "pan.___", state 863, "(1)" + line 404, "pan.___", state 864, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 864, "else" + line 404, "pan.___", state 867, "(1)" + line 404, "pan.___", state 868, "(1)" + line 404, "pan.___", state 868, "(1)" + line 408, "pan.___", state 876, "(1)" + line 408, "pan.___", state 877, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 877, "else" + line 408, "pan.___", state 880, "(1)" + line 408, "pan.___", state 881, "(1)" + line 408, "pan.___", state 881, "(1)" + line 406, "pan.___", state 886, "((i<1))" + line 406, "pan.___", state 886, "((i>=1))" + line 413, "pan.___", state 893, "(1)" + line 413, "pan.___", state 894, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 894, "else" + line 413, "pan.___", state 897, "(1)" + line 413, "pan.___", state 898, "(1)" + line 413, "pan.___", state 898, "(1)" + line 417, "pan.___", state 906, "(1)" + line 417, "pan.___", state 907, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 907, "else" + line 417, "pan.___", state 910, "(1)" + line 417, "pan.___", state 911, "(1)" + line 417, "pan.___", state 911, "(1)" + line 422, "pan.___", state 920, "(1)" + line 422, "pan.___", state 920, "(1)" + line 387, "pan.___", state 927, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 929, "(1)" + line 387, "pan.___", state 930, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 930, "else" + line 387, "pan.___", state 933, "(1)" + line 391, "pan.___", state 941, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 943, "(1)" + line 391, "pan.___", state 944, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 944, "else" + line 391, "pan.___", state 947, "(1)" + line 391, "pan.___", state 948, "(1)" + line 391, "pan.___", state 948, "(1)" + line 389, "pan.___", state 953, "((i<1))" + line 389, "pan.___", state 953, "((i>=1))" + line 396, "pan.___", state 959, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 961, "(1)" + line 396, "pan.___", state 962, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 962, "else" + line 396, "pan.___", state 965, "(1)" + line 396, "pan.___", state 966, "(1)" + line 396, "pan.___", state 966, "(1)" + line 400, "pan.___", state 973, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 975, "(1)" + line 400, "pan.___", state 976, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 976, "else" + line 400, "pan.___", state 979, "(1)" + line 400, "pan.___", state 980, "(1)" + line 400, "pan.___", state 980, "(1)" + line 398, "pan.___", state 985, "((i<2))" + line 398, "pan.___", state 985, "((i>=2))" + line 404, "pan.___", state 992, "(1)" + line 404, "pan.___", state 993, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 993, "else" + line 404, "pan.___", state 996, "(1)" + line 404, "pan.___", state 997, "(1)" + line 404, "pan.___", state 997, "(1)" + line 408, "pan.___", state 1005, "(1)" + line 408, "pan.___", state 1006, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 1006, "else" + line 408, "pan.___", state 1009, "(1)" + line 408, "pan.___", state 1010, "(1)" + line 408, "pan.___", state 1010, "(1)" + line 406, "pan.___", state 1015, "((i<1))" + line 406, "pan.___", state 1015, "((i>=1))" + line 413, "pan.___", state 1022, "(1)" + line 413, "pan.___", state 1023, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 1023, "else" + line 413, "pan.___", state 1026, "(1)" + line 413, "pan.___", state 1027, "(1)" + line 413, "pan.___", state 1027, "(1)" + line 417, "pan.___", state 1035, "(1)" + line 417, "pan.___", state 1036, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 1036, "else" + line 417, "pan.___", state 1039, "(1)" + line 417, "pan.___", state 1040, "(1)" + line 417, "pan.___", state 1040, "(1)" + line 415, "pan.___", state 1045, "((i<2))" + line 415, "pan.___", state 1045, "((i>=2))" + line 422, "pan.___", state 1049, "(1)" + line 422, "pan.___", state 1049, "(1)" + line 671, "pan.___", state 1053, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 387, "pan.___", state 1058, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 1064, "(1)" + line 391, "pan.___", state 1072, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 1078, "(1)" + line 391, "pan.___", state 1079, "(1)" + line 391, "pan.___", state 1079, "(1)" + line 389, "pan.___", state 1084, "((i<1))" + line 389, "pan.___", state 1084, "((i>=1))" + line 396, "pan.___", state 1090, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1096, "(1)" + line 396, "pan.___", state 1097, "(1)" + line 396, "pan.___", state 1097, "(1)" + line 400, "pan.___", state 1104, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1110, "(1)" + line 400, "pan.___", state 1111, "(1)" + line 400, "pan.___", state 1111, "(1)" + line 398, "pan.___", state 1116, "((i<2))" + line 398, "pan.___", state 1116, "((i>=2))" + line 404, "pan.___", state 1123, "(1)" + line 404, "pan.___", state 1124, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 1124, "else" + line 404, "pan.___", state 1127, "(1)" + line 404, "pan.___", state 1128, "(1)" + line 404, "pan.___", state 1128, "(1)" + line 408, "pan.___", state 1136, "(1)" + line 408, "pan.___", state 1137, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 1137, "else" + line 408, "pan.___", state 1140, "(1)" + line 408, "pan.___", state 1141, "(1)" + line 408, "pan.___", state 1141, "(1)" + line 406, "pan.___", state 1146, "((i<1))" + line 406, "pan.___", state 1146, "((i>=1))" + line 413, "pan.___", state 1153, "(1)" + line 413, "pan.___", state 1154, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 1154, "else" + line 413, "pan.___", state 1157, "(1)" + line 413, "pan.___", state 1158, "(1)" + line 413, "pan.___", state 1158, "(1)" + line 417, "pan.___", state 1166, "(1)" + line 417, "pan.___", state 1167, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 1167, "else" + line 417, "pan.___", state 1170, "(1)" + line 417, "pan.___", state 1171, "(1)" + line 417, "pan.___", state 1171, "(1)" + line 415, "pan.___", state 1176, "((i<2))" + line 415, "pan.___", state 1176, "((i>=2))" + line 422, "pan.___", state 1180, "(1)" + line 422, "pan.___", state 1180, "(1)" + line 387, "pan.___", state 1190, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 1196, "(1)" + line 391, "pan.___", state 1206, "(1)" + line 391, "pan.___", state 1207, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 1207, "else" + line 391, "pan.___", state 1210, "(1)" + line 391, "pan.___", state 1211, "(1)" + line 391, "pan.___", state 1211, "(1)" + line 389, "pan.___", state 1216, "((i<1))" + line 389, "pan.___", state 1216, "((i>=1))" + line 396, "pan.___", state 1222, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1228, "(1)" + line 396, "pan.___", state 1229, "(1)" + line 396, "pan.___", state 1229, "(1)" + line 400, "pan.___", state 1236, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1242, "(1)" + line 400, "pan.___", state 1243, "(1)" + line 400, "pan.___", state 1243, "(1)" + line 398, "pan.___", state 1248, "((i<2))" + line 398, "pan.___", state 1248, "((i>=2))" + line 404, "pan.___", state 1255, "(1)" + line 404, "pan.___", state 1256, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 1256, "else" + line 404, "pan.___", state 1259, "(1)" + line 404, "pan.___", state 1260, "(1)" + line 404, "pan.___", state 1260, "(1)" + line 408, "pan.___", state 1268, "(1)" + line 408, "pan.___", state 1269, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 1269, "else" + line 408, "pan.___", state 1272, "(1)" + line 408, "pan.___", state 1273, "(1)" + line 408, "pan.___", state 1273, "(1)" + line 406, "pan.___", state 1278, "((i<1))" + line 406, "pan.___", state 1278, "((i>=1))" + line 413, "pan.___", state 1285, "(1)" + line 413, "pan.___", state 1286, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 1286, "else" + line 413, "pan.___", state 1289, "(1)" + line 413, "pan.___", state 1290, "(1)" + line 413, "pan.___", state 1290, "(1)" + line 417, "pan.___", state 1298, "(1)" + line 417, "pan.___", state 1299, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 1299, "else" + line 417, "pan.___", state 1302, "(1)" + line 417, "pan.___", state 1303, "(1)" + line 417, "pan.___", state 1303, "(1)" + line 422, "pan.___", state 1312, "(1)" + line 422, "pan.___", state 1312, "(1)" + line 387, "pan.___", state 1323, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 1329, "(1)" + line 391, "pan.___", state 1337, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 1343, "(1)" + line 391, "pan.___", state 1344, "(1)" + line 391, "pan.___", state 1344, "(1)" + line 389, "pan.___", state 1349, "((i<1))" + line 389, "pan.___", state 1349, "((i>=1))" + line 396, "pan.___", state 1355, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1361, "(1)" + line 396, "pan.___", state 1362, "(1)" + line 396, "pan.___", state 1362, "(1)" + line 400, "pan.___", state 1369, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1375, "(1)" + line 400, "pan.___", state 1376, "(1)" + line 400, "pan.___", state 1376, "(1)" + line 398, "pan.___", state 1381, "((i<2))" + line 398, "pan.___", state 1381, "((i>=2))" + line 404, "pan.___", state 1388, "(1)" + line 404, "pan.___", state 1389, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 1389, "else" + line 404, "pan.___", state 1392, "(1)" + line 404, "pan.___", state 1393, "(1)" + line 404, "pan.___", state 1393, "(1)" + line 408, "pan.___", state 1401, "(1)" + line 408, "pan.___", state 1402, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 1402, "else" + line 408, "pan.___", state 1405, "(1)" + line 408, "pan.___", state 1406, "(1)" + line 408, "pan.___", state 1406, "(1)" + line 406, "pan.___", state 1411, "((i<1))" + line 406, "pan.___", state 1411, "((i>=1))" + line 413, "pan.___", state 1418, "(1)" + line 413, "pan.___", state 1419, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 1419, "else" + line 413, "pan.___", state 1422, "(1)" + line 413, "pan.___", state 1423, "(1)" + line 413, "pan.___", state 1423, "(1)" + line 417, "pan.___", state 1431, "(1)" + line 417, "pan.___", state 1432, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 1432, "else" + line 417, "pan.___", state 1435, "(1)" + line 417, "pan.___", state 1436, "(1)" + line 417, "pan.___", state 1436, "(1)" + line 422, "pan.___", state 1445, "(1)" + line 422, "pan.___", state 1445, "(1)" + line 387, "pan.___", state 1452, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 1458, "(1)" + line 391, "pan.___", state 1466, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 1472, "(1)" + line 391, "pan.___", state 1473, "(1)" + line 391, "pan.___", state 1473, "(1)" + line 389, "pan.___", state 1478, "((i<1))" + line 389, "pan.___", state 1478, "((i>=1))" + line 396, "pan.___", state 1484, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1490, "(1)" + line 396, "pan.___", state 1491, "(1)" + line 396, "pan.___", state 1491, "(1)" + line 400, "pan.___", state 1498, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1504, "(1)" + line 400, "pan.___", state 1505, "(1)" + line 400, "pan.___", state 1505, "(1)" + line 398, "pan.___", state 1510, "((i<2))" + line 398, "pan.___", state 1510, "((i>=2))" + line 404, "pan.___", state 1517, "(1)" + line 404, "pan.___", state 1518, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 1518, "else" + line 404, "pan.___", state 1521, "(1)" + line 404, "pan.___", state 1522, "(1)" + line 404, "pan.___", state 1522, "(1)" + line 408, "pan.___", state 1530, "(1)" + line 408, "pan.___", state 1531, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 1531, "else" + line 408, "pan.___", state 1534, "(1)" + line 408, "pan.___", state 1535, "(1)" + line 408, "pan.___", state 1535, "(1)" + line 406, "pan.___", state 1540, "((i<1))" + line 406, "pan.___", state 1540, "((i>=1))" + line 413, "pan.___", state 1547, "(1)" + line 413, "pan.___", state 1548, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 1548, "else" + line 413, "pan.___", state 1551, "(1)" + line 413, "pan.___", state 1552, "(1)" + line 413, "pan.___", state 1552, "(1)" + line 417, "pan.___", state 1560, "(1)" + line 417, "pan.___", state 1561, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 1561, "else" + line 417, "pan.___", state 1564, "(1)" + line 417, "pan.___", state 1565, "(1)" + line 417, "pan.___", state 1565, "(1)" + line 415, "pan.___", state 1570, "((i<2))" + line 415, "pan.___", state 1570, "((i>=2))" + line 422, "pan.___", state 1574, "(1)" + line 422, "pan.___", state 1574, "(1)" + line 387, "pan.___", state 1586, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 1592, "(1)" + line 391, "pan.___", state 1602, "(1)" + line 391, "pan.___", state 1603, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 1603, "else" + line 391, "pan.___", state 1606, "(1)" + line 391, "pan.___", state 1607, "(1)" + line 391, "pan.___", state 1607, "(1)" + line 389, "pan.___", state 1612, "((i<1))" + line 389, "pan.___", state 1612, "((i>=1))" + line 396, "pan.___", state 1618, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1624, "(1)" + line 396, "pan.___", state 1625, "(1)" + line 396, "pan.___", state 1625, "(1)" + line 400, "pan.___", state 1632, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1638, "(1)" + line 400, "pan.___", state 1639, "(1)" + line 400, "pan.___", state 1639, "(1)" + line 398, "pan.___", state 1644, "((i<2))" + line 398, "pan.___", state 1644, "((i>=2))" + line 404, "pan.___", state 1651, "(1)" + line 404, "pan.___", state 1652, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 1652, "else" + line 404, "pan.___", state 1655, "(1)" + line 404, "pan.___", state 1656, "(1)" + line 404, "pan.___", state 1656, "(1)" + line 408, "pan.___", state 1664, "(1)" + line 408, "pan.___", state 1665, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 1665, "else" + line 408, "pan.___", state 1668, "(1)" + line 408, "pan.___", state 1669, "(1)" + line 408, "pan.___", state 1669, "(1)" + line 406, "pan.___", state 1674, "((i<1))" + line 406, "pan.___", state 1674, "((i>=1))" + line 413, "pan.___", state 1681, "(1)" + line 413, "pan.___", state 1682, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 1682, "else" + line 413, "pan.___", state 1685, "(1)" + line 413, "pan.___", state 1686, "(1)" + line 413, "pan.___", state 1686, "(1)" + line 417, "pan.___", state 1694, "(1)" + line 417, "pan.___", state 1695, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 1695, "else" + line 417, "pan.___", state 1698, "(1)" + line 417, "pan.___", state 1699, "(1)" + line 417, "pan.___", state 1699, "(1)" + line 422, "pan.___", state 1708, "(1)" + line 422, "pan.___", state 1708, "(1)" + line 387, "pan.___", state 1715, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 1721, "(1)" + line 391, "pan.___", state 1729, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 1735, "(1)" + line 391, "pan.___", state 1736, "(1)" + line 391, "pan.___", state 1736, "(1)" + line 389, "pan.___", state 1741, "((i<1))" + line 389, "pan.___", state 1741, "((i>=1))" + line 396, "pan.___", state 1747, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1753, "(1)" + line 396, "pan.___", state 1754, "(1)" + line 396, "pan.___", state 1754, "(1)" + line 400, "pan.___", state 1761, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1767, "(1)" + line 400, "pan.___", state 1768, "(1)" + line 400, "pan.___", state 1768, "(1)" + line 398, "pan.___", state 1773, "((i<2))" + line 398, "pan.___", state 1773, "((i>=2))" + line 404, "pan.___", state 1780, "(1)" + line 404, "pan.___", state 1781, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 1781, "else" + line 404, "pan.___", state 1784, "(1)" + line 404, "pan.___", state 1785, "(1)" + line 404, "pan.___", state 1785, "(1)" + line 408, "pan.___", state 1793, "(1)" + line 408, "pan.___", state 1794, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 1794, "else" + line 408, "pan.___", state 1797, "(1)" + line 408, "pan.___", state 1798, "(1)" + line 408, "pan.___", state 1798, "(1)" + line 406, "pan.___", state 1803, "((i<1))" + line 406, "pan.___", state 1803, "((i>=1))" + line 413, "pan.___", state 1810, "(1)" + line 413, "pan.___", state 1811, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 1811, "else" + line 413, "pan.___", state 1814, "(1)" + line 413, "pan.___", state 1815, "(1)" + line 413, "pan.___", state 1815, "(1)" + line 417, "pan.___", state 1823, "(1)" + line 417, "pan.___", state 1824, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 1824, "else" + line 417, "pan.___", state 1827, "(1)" + line 417, "pan.___", state 1828, "(1)" + line 417, "pan.___", state 1828, "(1)" + line 415, "pan.___", state 1833, "((i<2))" + line 415, "pan.___", state 1833, "((i>=2))" + line 422, "pan.___", state 1837, "(1)" + line 422, "pan.___", state 1837, "(1)" + line 387, "pan.___", state 1847, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 1853, "(1)" + line 391, "pan.___", state 1863, "(1)" + line 391, "pan.___", state 1864, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 1864, "else" + line 391, "pan.___", state 1867, "(1)" + line 391, "pan.___", state 1868, "(1)" + line 391, "pan.___", state 1868, "(1)" + line 389, "pan.___", state 1873, "((i<1))" + line 389, "pan.___", state 1873, "((i>=1))" + line 396, "pan.___", state 1879, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1885, "(1)" + line 396, "pan.___", state 1886, "(1)" + line 396, "pan.___", state 1886, "(1)" + line 400, "pan.___", state 1893, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1899, "(1)" + line 400, "pan.___", state 1900, "(1)" + line 400, "pan.___", state 1900, "(1)" + line 398, "pan.___", state 1905, "((i<2))" + line 398, "pan.___", state 1905, "((i>=2))" + line 404, "pan.___", state 1912, "(1)" + line 404, "pan.___", state 1913, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 1913, "else" + line 404, "pan.___", state 1916, "(1)" + line 404, "pan.___", state 1917, "(1)" + line 404, "pan.___", state 1917, "(1)" + line 408, "pan.___", state 1925, "(1)" + line 408, "pan.___", state 1926, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 1926, "else" + line 408, "pan.___", state 1929, "(1)" + line 408, "pan.___", state 1930, "(1)" + line 408, "pan.___", state 1930, "(1)" + line 406, "pan.___", state 1935, "((i<1))" + line 406, "pan.___", state 1935, "((i>=1))" + line 413, "pan.___", state 1942, "(1)" + line 413, "pan.___", state 1943, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 1943, "else" + line 413, "pan.___", state 1946, "(1)" + line 413, "pan.___", state 1947, "(1)" + line 413, "pan.___", state 1947, "(1)" + line 417, "pan.___", state 1955, "(1)" + line 417, "pan.___", state 1956, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 1956, "else" + line 417, "pan.___", state 1959, "(1)" + line 417, "pan.___", state 1960, "(1)" + line 417, "pan.___", state 1960, "(1)" + line 422, "pan.___", state 1969, "(1)" + line 422, "pan.___", state 1969, "(1)" + line 710, "pan.___", state 1976, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 710, "pan.___", state 1977, "(!((tmp&((1<<7)-1))))" + line 710, "pan.___", state 1977, "else" + line 387, "pan.___", state 1983, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 1989, "(1)" + line 391, "pan.___", state 1997, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 2003, "(1)" + line 391, "pan.___", state 2004, "(1)" + line 391, "pan.___", state 2004, "(1)" + line 389, "pan.___", state 2009, "((i<1))" + line 389, "pan.___", state 2009, "((i>=1))" + line 396, "pan.___", state 2015, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2021, "(1)" + line 396, "pan.___", state 2022, "(1)" + line 396, "pan.___", state 2022, "(1)" + line 400, "pan.___", state 2029, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2035, "(1)" + line 400, "pan.___", state 2036, "(1)" + line 400, "pan.___", state 2036, "(1)" + line 398, "pan.___", state 2041, "((i<2))" + line 398, "pan.___", state 2041, "((i>=2))" + line 404, "pan.___", state 2048, "(1)" + line 404, "pan.___", state 2049, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 2049, "else" + line 404, "pan.___", state 2052, "(1)" + line 404, "pan.___", state 2053, "(1)" + line 404, "pan.___", state 2053, "(1)" + line 408, "pan.___", state 2061, "(1)" + line 408, "pan.___", state 2062, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 2062, "else" + line 408, "pan.___", state 2065, "(1)" + line 408, "pan.___", state 2066, "(1)" + line 408, "pan.___", state 2066, "(1)" + line 406, "pan.___", state 2071, "((i<1))" + line 406, "pan.___", state 2071, "((i>=1))" + line 413, "pan.___", state 2078, "(1)" + line 413, "pan.___", state 2079, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 2079, "else" + line 413, "pan.___", state 2082, "(1)" + line 413, "pan.___", state 2083, "(1)" + line 413, "pan.___", state 2083, "(1)" + line 417, "pan.___", state 2091, "(1)" + line 417, "pan.___", state 2092, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 2092, "else" + line 417, "pan.___", state 2095, "(1)" + line 417, "pan.___", state 2096, "(1)" + line 417, "pan.___", state 2096, "(1)" + line 422, "pan.___", state 2105, "(1)" + line 422, "pan.___", state 2105, "(1)" + line 387, "pan.___", state 2112, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 2118, "(1)" + line 391, "pan.___", state 2126, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 2132, "(1)" + line 391, "pan.___", state 2133, "(1)" + line 391, "pan.___", state 2133, "(1)" + line 389, "pan.___", state 2138, "((i<1))" + line 389, "pan.___", state 2138, "((i>=1))" + line 396, "pan.___", state 2144, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2150, "(1)" + line 396, "pan.___", state 2151, "(1)" + line 396, "pan.___", state 2151, "(1)" + line 400, "pan.___", state 2158, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2164, "(1)" + line 400, "pan.___", state 2165, "(1)" + line 400, "pan.___", state 2165, "(1)" + line 398, "pan.___", state 2170, "((i<2))" + line 398, "pan.___", state 2170, "((i>=2))" + line 404, "pan.___", state 2177, "(1)" + line 404, "pan.___", state 2178, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 2178, "else" + line 404, "pan.___", state 2181, "(1)" + line 404, "pan.___", state 2182, "(1)" + line 404, "pan.___", state 2182, "(1)" + line 408, "pan.___", state 2190, "(1)" + line 408, "pan.___", state 2191, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 2191, "else" + line 408, "pan.___", state 2194, "(1)" + line 408, "pan.___", state 2195, "(1)" + line 408, "pan.___", state 2195, "(1)" + line 406, "pan.___", state 2200, "((i<1))" + line 406, "pan.___", state 2200, "((i>=1))" + line 413, "pan.___", state 2207, "(1)" + line 413, "pan.___", state 2208, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 2208, "else" + line 413, "pan.___", state 2211, "(1)" + line 413, "pan.___", state 2212, "(1)" + line 413, "pan.___", state 2212, "(1)" + line 417, "pan.___", state 2220, "(1)" + line 417, "pan.___", state 2221, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 2221, "else" + line 417, "pan.___", state 2224, "(1)" + line 417, "pan.___", state 2225, "(1)" + line 417, "pan.___", state 2225, "(1)" + line 415, "pan.___", state 2230, "((i<2))" + line 415, "pan.___", state 2230, "((i>=2))" + line 422, "pan.___", state 2234, "(1)" + line 422, "pan.___", state 2234, "(1)" + line 387, "pan.___", state 2243, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 2245, "(1)" + line 387, "pan.___", state 2246, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 2246, "else" + line 387, "pan.___", state 2249, "(1)" + line 391, "pan.___", state 2257, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 2259, "(1)" + line 391, "pan.___", state 2260, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 2260, "else" + line 391, "pan.___", state 2263, "(1)" + line 391, "pan.___", state 2264, "(1)" + line 391, "pan.___", state 2264, "(1)" + line 389, "pan.___", state 2269, "((i<1))" + line 389, "pan.___", state 2269, "((i>=1))" + line 396, "pan.___", state 2275, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2277, "(1)" + line 396, "pan.___", state 2278, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 2278, "else" + line 396, "pan.___", state 2281, "(1)" + line 396, "pan.___", state 2282, "(1)" + line 396, "pan.___", state 2282, "(1)" + line 400, "pan.___", state 2289, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2291, "(1)" + line 400, "pan.___", state 2292, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 2292, "else" + line 400, "pan.___", state 2295, "(1)" + line 400, "pan.___", state 2296, "(1)" + line 400, "pan.___", state 2296, "(1)" + line 398, "pan.___", state 2301, "((i<2))" + line 398, "pan.___", state 2301, "((i>=2))" + line 404, "pan.___", state 2308, "(1)" + line 404, "pan.___", state 2309, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 2309, "else" + line 404, "pan.___", state 2312, "(1)" + line 404, "pan.___", state 2313, "(1)" + line 404, "pan.___", state 2313, "(1)" + line 408, "pan.___", state 2321, "(1)" + line 408, "pan.___", state 2322, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 2322, "else" + line 408, "pan.___", state 2325, "(1)" + line 408, "pan.___", state 2326, "(1)" + line 408, "pan.___", state 2326, "(1)" + line 406, "pan.___", state 2331, "((i<1))" + line 406, "pan.___", state 2331, "((i>=1))" + line 413, "pan.___", state 2338, "(1)" + line 413, "pan.___", state 2339, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 2339, "else" + line 413, "pan.___", state 2342, "(1)" + line 413, "pan.___", state 2343, "(1)" + line 413, "pan.___", state 2343, "(1)" + line 417, "pan.___", state 2351, "(1)" + line 417, "pan.___", state 2352, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 2352, "else" + line 417, "pan.___", state 2355, "(1)" + line 417, "pan.___", state 2356, "(1)" + line 417, "pan.___", state 2356, "(1)" + line 415, "pan.___", state 2361, "((i<2))" + line 415, "pan.___", state 2361, "((i>=2))" + line 422, "pan.___", state 2365, "(1)" + line 422, "pan.___", state 2365, "(1)" + line 710, "pan.___", state 2368, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 710, "pan.___", state 2369, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 710, "pan.___", state 2370, "(1)" + line 387, "pan.___", state 2377, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 2383, "(1)" + line 391, "pan.___", state 2393, "(1)" + line 391, "pan.___", state 2394, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 2394, "else" + line 391, "pan.___", state 2397, "(1)" + line 391, "pan.___", state 2398, "(1)" + line 391, "pan.___", state 2398, "(1)" + line 389, "pan.___", state 2403, "((i<1))" + line 389, "pan.___", state 2403, "((i>=1))" + line 396, "pan.___", state 2409, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2415, "(1)" + line 396, "pan.___", state 2416, "(1)" + line 396, "pan.___", state 2416, "(1)" + line 400, "pan.___", state 2423, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2429, "(1)" + line 400, "pan.___", state 2430, "(1)" + line 400, "pan.___", state 2430, "(1)" + line 398, "pan.___", state 2435, "((i<2))" + line 398, "pan.___", state 2435, "((i>=2))" + line 404, "pan.___", state 2442, "(1)" + line 404, "pan.___", state 2443, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 2443, "else" + line 404, "pan.___", state 2446, "(1)" + line 404, "pan.___", state 2447, "(1)" + line 404, "pan.___", state 2447, "(1)" + line 408, "pan.___", state 2455, "(1)" + line 408, "pan.___", state 2456, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 2456, "else" + line 408, "pan.___", state 2459, "(1)" + line 408, "pan.___", state 2460, "(1)" + line 408, "pan.___", state 2460, "(1)" + line 406, "pan.___", state 2465, "((i<1))" + line 406, "pan.___", state 2465, "((i>=1))" + line 413, "pan.___", state 2472, "(1)" + line 413, "pan.___", state 2473, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 2473, "else" + line 413, "pan.___", state 2476, "(1)" + line 413, "pan.___", state 2477, "(1)" + line 413, "pan.___", state 2477, "(1)" + line 417, "pan.___", state 2485, "(1)" + line 417, "pan.___", state 2486, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 2486, "else" + line 417, "pan.___", state 2489, "(1)" + line 417, "pan.___", state 2490, "(1)" + line 417, "pan.___", state 2490, "(1)" + line 422, "pan.___", state 2499, "(1)" + line 422, "pan.___", state 2499, "(1)" + line 387, "pan.___", state 2512, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 2526, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2544, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2558, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2577, "(1)" + line 408, "pan.___", state 2590, "(1)" + line 413, "pan.___", state 2607, "(1)" + line 417, "pan.___", state 2620, "(1)" + line 387, "pan.___", state 2641, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 2655, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2673, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2687, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2706, "(1)" + line 408, "pan.___", state 2719, "(1)" + line 413, "pan.___", state 2736, "(1)" + line 417, "pan.___", state 2749, "(1)" + line 227, "pan.___", state 2782, "(1)" + line 231, "pan.___", state 2790, "(1)" + line 231, "pan.___", state 2791, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 2791, "else" + line 229, "pan.___", state 2796, "((i<1))" + line 229, "pan.___", state 2796, "((i>=1))" + line 235, "pan.___", state 2802, "(1)" + line 235, "pan.___", state 2803, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 2803, "else" + line 239, "pan.___", state 2810, "(1)" + line 239, "pan.___", state 2811, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 2811, "else" + line 244, "pan.___", state 2820, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 2820, "else" + line 227, "pan.___", state 2825, "(1)" + line 231, "pan.___", state 2833, "(1)" + line 235, "pan.___", state 2845, "(1)" + line 239, "pan.___", state 2853, "(1)" + line 870, "pan.___", state 2870, "-end-" + (659 of 2870 states) +unreached in proctype urcu_writer + line 387, "pan.___", state 18, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 32, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 50, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 83, "(1)" + line 408, "pan.___", state 96, "(1)" + line 413, "pan.___", state 113, "(1)" + line 417, "pan.___", state 126, "(1)" + line 250, "pan.___", state 149, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 158, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 171, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 211, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 217, "(1)" + line 391, "pan.___", state 225, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 231, "(1)" + line 391, "pan.___", state 232, "(1)" + line 391, "pan.___", state 232, "(1)" + line 389, "pan.___", state 237, "((i<1))" + line 389, "pan.___", state 237, "((i>=1))" + line 396, "pan.___", state 243, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 249, "(1)" + line 396, "pan.___", state 250, "(1)" + line 396, "pan.___", state 250, "(1)" + line 400, "pan.___", state 257, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 263, "(1)" + line 400, "pan.___", state 264, "(1)" + line 400, "pan.___", state 264, "(1)" + line 398, "pan.___", state 269, "((i<2))" + line 398, "pan.___", state 269, "((i>=2))" + line 404, "pan.___", state 276, "(1)" + line 404, "pan.___", state 277, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 277, "else" + line 404, "pan.___", state 280, "(1)" + line 404, "pan.___", state 281, "(1)" + line 404, "pan.___", state 281, "(1)" + line 408, "pan.___", state 289, "(1)" + line 408, "pan.___", state 290, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 290, "else" + line 408, "pan.___", state 293, "(1)" + line 408, "pan.___", state 294, "(1)" + line 408, "pan.___", state 294, "(1)" + line 406, "pan.___", state 299, "((i<1))" + line 406, "pan.___", state 299, "((i>=1))" + line 413, "pan.___", state 306, "(1)" + line 413, "pan.___", state 307, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 307, "else" + line 413, "pan.___", state 310, "(1)" + line 413, "pan.___", state 311, "(1)" + line 413, "pan.___", state 311, "(1)" + line 417, "pan.___", state 319, "(1)" + line 417, "pan.___", state 320, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 320, "else" + line 417, "pan.___", state 323, "(1)" + line 417, "pan.___", state 324, "(1)" + line 417, "pan.___", state 324, "(1)" + line 415, "pan.___", state 329, "((i<2))" + line 415, "pan.___", state 329, "((i>=2))" + line 422, "pan.___", state 333, "(1)" + line 422, "pan.___", state 333, "(1)" + line 387, "pan.___", state 344, "(1)" + line 387, "pan.___", state 345, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 345, "else" + line 387, "pan.___", state 348, "(1)" + line 391, "pan.___", state 356, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 362, "(1)" + line 391, "pan.___", state 363, "(1)" + line 391, "pan.___", state 363, "(1)" + line 389, "pan.___", state 368, "((i<1))" + line 389, "pan.___", state 368, "((i>=1))" + line 396, "pan.___", state 374, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 380, "(1)" + line 396, "pan.___", state 381, "(1)" + line 396, "pan.___", state 381, "(1)" + line 400, "pan.___", state 388, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 394, "(1)" + line 400, "pan.___", state 395, "(1)" + line 400, "pan.___", state 395, "(1)" + line 398, "pan.___", state 400, "((i<2))" + line 398, "pan.___", state 400, "((i>=2))" + line 404, "pan.___", state 407, "(1)" + line 404, "pan.___", state 408, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 408, "else" + line 404, "pan.___", state 411, "(1)" + line 404, "pan.___", state 412, "(1)" + line 404, "pan.___", state 412, "(1)" + line 408, "pan.___", state 420, "(1)" + line 408, "pan.___", state 421, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 421, "else" + line 408, "pan.___", state 424, "(1)" + line 408, "pan.___", state 425, "(1)" + line 408, "pan.___", state 425, "(1)" + line 406, "pan.___", state 430, "((i<1))" + line 406, "pan.___", state 430, "((i>=1))" + line 413, "pan.___", state 437, "(1)" + line 413, "pan.___", state 438, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 438, "else" + line 413, "pan.___", state 441, "(1)" + line 413, "pan.___", state 442, "(1)" + line 413, "pan.___", state 442, "(1)" + line 417, "pan.___", state 450, "(1)" + line 417, "pan.___", state 451, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 451, "else" + line 417, "pan.___", state 454, "(1)" + line 417, "pan.___", state 455, "(1)" + line 417, "pan.___", state 455, "(1)" + line 415, "pan.___", state 460, "((i<2))" + line 415, "pan.___", state 460, "((i>=2))" + line 422, "pan.___", state 464, "(1)" + line 422, "pan.___", state 464, "(1)" + line 1056, "pan.___", state 475, "_proc_urcu_writer = (_proc_urcu_writer&~(((1<<8)|(1<<7))))" + line 387, "pan.___", state 480, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 486, "(1)" + line 391, "pan.___", state 494, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 500, "(1)" + line 391, "pan.___", state 501, "(1)" + line 391, "pan.___", state 501, "(1)" + line 389, "pan.___", state 506, "((i<1))" + line 389, "pan.___", state 506, "((i>=1))" + line 396, "pan.___", state 512, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 518, "(1)" + line 396, "pan.___", state 519, "(1)" + line 396, "pan.___", state 519, "(1)" + line 400, "pan.___", state 526, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 532, "(1)" + line 400, "pan.___", state 533, "(1)" + line 400, "pan.___", state 533, "(1)" + line 398, "pan.___", state 538, "((i<2))" + line 398, "pan.___", state 538, "((i>=2))" + line 404, "pan.___", state 545, "(1)" + line 404, "pan.___", state 546, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 546, "else" + line 404, "pan.___", state 549, "(1)" + line 404, "pan.___", state 550, "(1)" + line 404, "pan.___", state 550, "(1)" + line 408, "pan.___", state 558, "(1)" + line 408, "pan.___", state 559, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 559, "else" + line 408, "pan.___", state 562, "(1)" + line 408, "pan.___", state 563, "(1)" + line 408, "pan.___", state 563, "(1)" + line 406, "pan.___", state 568, "((i<1))" + line 406, "pan.___", state 568, "((i>=1))" + line 413, "pan.___", state 575, "(1)" + line 413, "pan.___", state 576, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 576, "else" + line 413, "pan.___", state 579, "(1)" + line 413, "pan.___", state 580, "(1)" + line 413, "pan.___", state 580, "(1)" + line 417, "pan.___", state 588, "(1)" + line 417, "pan.___", state 589, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 589, "else" + line 417, "pan.___", state 592, "(1)" + line 417, "pan.___", state 593, "(1)" + line 417, "pan.___", state 593, "(1)" + line 422, "pan.___", state 602, "(1)" + line 422, "pan.___", state 602, "(1)" + line 387, "pan.___", state 609, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 615, "(1)" + line 391, "pan.___", state 623, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 629, "(1)" + line 391, "pan.___", state 630, "(1)" + line 391, "pan.___", state 630, "(1)" + line 389, "pan.___", state 635, "((i<1))" + line 389, "pan.___", state 635, "((i>=1))" + line 396, "pan.___", state 641, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 647, "(1)" + line 396, "pan.___", state 648, "(1)" + line 396, "pan.___", state 648, "(1)" + line 400, "pan.___", state 655, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 661, "(1)" + line 400, "pan.___", state 662, "(1)" + line 400, "pan.___", state 662, "(1)" + line 398, "pan.___", state 667, "((i<2))" + line 398, "pan.___", state 667, "((i>=2))" + line 404, "pan.___", state 674, "(1)" + line 404, "pan.___", state 675, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 675, "else" + line 404, "pan.___", state 678, "(1)" + line 404, "pan.___", state 679, "(1)" + line 404, "pan.___", state 679, "(1)" + line 408, "pan.___", state 687, "(1)" + line 408, "pan.___", state 688, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 688, "else" + line 408, "pan.___", state 691, "(1)" + line 408, "pan.___", state 692, "(1)" + line 408, "pan.___", state 692, "(1)" + line 406, "pan.___", state 697, "((i<1))" + line 406, "pan.___", state 697, "((i>=1))" + line 413, "pan.___", state 704, "(1)" + line 413, "pan.___", state 705, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 705, "else" + line 413, "pan.___", state 708, "(1)" + line 413, "pan.___", state 709, "(1)" + line 413, "pan.___", state 709, "(1)" + line 417, "pan.___", state 717, "(1)" + line 417, "pan.___", state 718, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 718, "else" + line 417, "pan.___", state 721, "(1)" + line 417, "pan.___", state 722, "(1)" + line 417, "pan.___", state 722, "(1)" + line 415, "pan.___", state 727, "((i<2))" + line 415, "pan.___", state 727, "((i>=2))" + line 422, "pan.___", state 731, "(1)" + line 422, "pan.___", state 731, "(1)" + line 387, "pan.___", state 742, "(1)" + line 387, "pan.___", state 743, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 743, "else" + line 387, "pan.___", state 746, "(1)" + line 391, "pan.___", state 754, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 760, "(1)" + line 391, "pan.___", state 761, "(1)" + line 391, "pan.___", state 761, "(1)" + line 389, "pan.___", state 766, "((i<1))" + line 389, "pan.___", state 766, "((i>=1))" + line 396, "pan.___", state 772, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 778, "(1)" + line 396, "pan.___", state 779, "(1)" + line 396, "pan.___", state 779, "(1)" + line 400, "pan.___", state 786, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 792, "(1)" + line 400, "pan.___", state 793, "(1)" + line 400, "pan.___", state 793, "(1)" + line 398, "pan.___", state 798, "((i<2))" + line 398, "pan.___", state 798, "((i>=2))" + line 404, "pan.___", state 805, "(1)" + line 404, "pan.___", state 806, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 806, "else" + line 404, "pan.___", state 809, "(1)" + line 404, "pan.___", state 810, "(1)" + line 404, "pan.___", state 810, "(1)" + line 408, "pan.___", state 818, "(1)" + line 408, "pan.___", state 819, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 819, "else" + line 408, "pan.___", state 822, "(1)" + line 408, "pan.___", state 823, "(1)" + line 408, "pan.___", state 823, "(1)" + line 406, "pan.___", state 828, "((i<1))" + line 406, "pan.___", state 828, "((i>=1))" + line 413, "pan.___", state 835, "(1)" + line 413, "pan.___", state 836, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 836, "else" + line 413, "pan.___", state 839, "(1)" + line 413, "pan.___", state 840, "(1)" + line 413, "pan.___", state 840, "(1)" + line 417, "pan.___", state 848, "(1)" + line 417, "pan.___", state 849, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 849, "else" + line 417, "pan.___", state 852, "(1)" + line 417, "pan.___", state 853, "(1)" + line 417, "pan.___", state 853, "(1)" + line 415, "pan.___", state 858, "((i<2))" + line 415, "pan.___", state 858, "((i>=2))" + line 422, "pan.___", state 862, "(1)" + line 422, "pan.___", state 862, "(1)" + line 1113, "pan.___", state 872, "_proc_urcu_writer = (_proc_urcu_writer&~(((1<<12)|(1<<11))))" + line 250, "pan.___", state 903, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 912, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 927, "(1)" + line 262, "pan.___", state 934, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 950, "(1)" + line 231, "pan.___", state 958, "(1)" + line 235, "pan.___", state 970, "(1)" + line 239, "pan.___", state 978, "(1)" + line 250, "pan.___", state 1009, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1018, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 252, "pan.___", state 1026, "((i<1))" + line 252, "pan.___", state 1026, "((i>=1))" + line 258, "pan.___", state 1031, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1040, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 260, "pan.___", state 1048, "((i<2))" + line 260, "pan.___", state 1048, "((i>=2))" + line 227, "pan.___", state 1056, "(1)" + line 231, "pan.___", state 1064, "(1)" + line 231, "pan.___", state 1065, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1065, "else" + line 229, "pan.___", state 1070, "((i<1))" + line 229, "pan.___", state 1070, "((i>=1))" + line 235, "pan.___", state 1076, "(1)" + line 235, "pan.___", state 1077, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1077, "else" + line 239, "pan.___", state 1084, "(1)" + line 239, "pan.___", state 1085, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1085, "else" + line 244, "pan.___", state 1094, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1094, "else" + line 250, "pan.___", state 1101, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1103, "(1)" + line 254, "pan.___", state 1110, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1112, "(1)" + line 254, "pan.___", state 1113, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1113, "else" + line 252, "pan.___", state 1118, "((i<1))" + line 252, "pan.___", state 1118, "((i>=1))" + line 258, "pan.___", state 1123, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1125, "(1)" + line 258, "pan.___", state 1126, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1126, "else" + line 262, "pan.___", state 1132, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1134, "(1)" + line 262, "pan.___", state 1135, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1135, "else" + line 260, "pan.___", state 1140, "((i<2))" + line 260, "pan.___", state 1140, "((i>=2))" + line 227, "pan.___", state 1148, "(1)" + line 231, "pan.___", state 1156, "(1)" + line 231, "pan.___", state 1157, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1157, "else" + line 229, "pan.___", state 1162, "((i<1))" + line 229, "pan.___", state 1162, "((i>=1))" + line 235, "pan.___", state 1168, "(1)" + line 235, "pan.___", state 1169, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1169, "else" + line 239, "pan.___", state 1176, "(1)" + line 239, "pan.___", state 1177, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1177, "else" + line 244, "pan.___", state 1186, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1186, "else" + line 1180, "pan.___", state 1189, "i = 0" + line 1180, "pan.___", state 1191, "reader_barrier = 1" + line 1180, "pan.___", state 1202, "((i<1))" + line 1180, "pan.___", state 1202, "((i>=1))" + line 250, "pan.___", state 1207, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1209, "(1)" + line 254, "pan.___", state 1216, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1218, "(1)" + line 254, "pan.___", state 1219, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1219, "else" + line 252, "pan.___", state 1224, "((i<1))" + line 252, "pan.___", state 1224, "((i>=1))" + line 258, "pan.___", state 1229, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1231, "(1)" + line 258, "pan.___", state 1232, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1232, "else" + line 262, "pan.___", state 1238, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1240, "(1)" + line 262, "pan.___", state 1241, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1241, "else" + line 260, "pan.___", state 1246, "((i<2))" + line 260, "pan.___", state 1246, "((i>=2))" + line 227, "pan.___", state 1254, "(1)" + line 231, "pan.___", state 1262, "(1)" + line 231, "pan.___", state 1263, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1263, "else" + line 229, "pan.___", state 1268, "((i<1))" + line 229, "pan.___", state 1268, "((i>=1))" + line 235, "pan.___", state 1274, "(1)" + line 235, "pan.___", state 1275, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1275, "else" + line 239, "pan.___", state 1282, "(1)" + line 239, "pan.___", state 1283, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1283, "else" + line 244, "pan.___", state 1292, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1292, "else" + line 277, "pan.___", state 1294, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 1294, "else" + line 1180, "pan.___", state 1295, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 1180, "pan.___", state 1295, "else" + line 250, "pan.___", state 1299, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1301, "(1)" + line 254, "pan.___", state 1308, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1310, "(1)" + line 254, "pan.___", state 1311, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1311, "else" + line 252, "pan.___", state 1316, "((i<1))" + line 252, "pan.___", state 1316, "((i>=1))" + line 258, "pan.___", state 1321, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1323, "(1)" + line 258, "pan.___", state 1324, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1324, "else" + line 262, "pan.___", state 1330, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1332, "(1)" + line 262, "pan.___", state 1333, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1333, "else" + line 260, "pan.___", state 1338, "((i<2))" + line 260, "pan.___", state 1338, "((i>=2))" + line 227, "pan.___", state 1346, "(1)" + line 231, "pan.___", state 1354, "(1)" + line 231, "pan.___", state 1355, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1355, "else" + line 229, "pan.___", state 1360, "((i<1))" + line 229, "pan.___", state 1360, "((i>=1))" + line 235, "pan.___", state 1366, "(1)" + line 235, "pan.___", state 1367, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1367, "else" + line 239, "pan.___", state 1374, "(1)" + line 239, "pan.___", state 1375, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1375, "else" + line 244, "pan.___", state 1384, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1384, "else" + line 1183, "pan.___", state 1387, "i = 0" + line 1183, "pan.___", state 1389, "reader_barrier = 1" + line 1183, "pan.___", state 1400, "((i<1))" + line 1183, "pan.___", state 1400, "((i>=1))" + line 250, "pan.___", state 1405, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1407, "(1)" + line 254, "pan.___", state 1414, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1416, "(1)" + line 254, "pan.___", state 1417, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1417, "else" + line 252, "pan.___", state 1422, "((i<1))" + line 252, "pan.___", state 1422, "((i>=1))" + line 258, "pan.___", state 1427, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1429, "(1)" + line 258, "pan.___", state 1430, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1430, "else" + line 262, "pan.___", state 1436, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1438, "(1)" + line 262, "pan.___", state 1439, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1439, "else" + line 260, "pan.___", state 1444, "((i<2))" + line 260, "pan.___", state 1444, "((i>=2))" + line 227, "pan.___", state 1452, "(1)" + line 231, "pan.___", state 1460, "(1)" + line 231, "pan.___", state 1461, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1461, "else" + line 229, "pan.___", state 1466, "((i<1))" + line 229, "pan.___", state 1466, "((i>=1))" + line 235, "pan.___", state 1472, "(1)" + line 235, "pan.___", state 1473, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1473, "else" + line 239, "pan.___", state 1480, "(1)" + line 239, "pan.___", state 1481, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1481, "else" + line 244, "pan.___", state 1490, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1490, "else" + line 277, "pan.___", state 1492, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 1492, "else" + line 1183, "pan.___", state 1493, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 1183, "pan.___", state 1493, "else" + line 250, "pan.___", state 1497, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1506, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 252, "pan.___", state 1514, "((i<1))" + line 252, "pan.___", state 1514, "((i>=1))" + line 258, "pan.___", state 1519, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1528, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 260, "pan.___", state 1536, "((i<2))" + line 260, "pan.___", state 1536, "((i>=2))" + line 227, "pan.___", state 1544, "(1)" + line 231, "pan.___", state 1552, "(1)" + line 231, "pan.___", state 1553, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1553, "else" + line 229, "pan.___", state 1558, "((i<1))" + line 229, "pan.___", state 1558, "((i>=1))" + line 235, "pan.___", state 1564, "(1)" + line 235, "pan.___", state 1565, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1565, "else" + line 239, "pan.___", state 1572, "(1)" + line 239, "pan.___", state 1573, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1573, "else" + line 244, "pan.___", state 1582, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1582, "else" + line 1187, "pan.___", state 1585, "i = 0" + line 1187, "pan.___", state 1587, "reader_barrier = 1" + line 1187, "pan.___", state 1598, "((i<1))" + line 1187, "pan.___", state 1598, "((i>=1))" + line 250, "pan.___", state 1603, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1612, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 252, "pan.___", state 1620, "((i<1))" + line 252, "pan.___", state 1620, "((i>=1))" + line 258, "pan.___", state 1625, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1634, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 260, "pan.___", state 1642, "((i<2))" + line 260, "pan.___", state 1642, "((i>=2))" + line 227, "pan.___", state 1650, "(1)" + line 231, "pan.___", state 1658, "(1)" + line 231, "pan.___", state 1659, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1659, "else" + line 229, "pan.___", state 1664, "((i<1))" + line 229, "pan.___", state 1664, "((i>=1))" + line 235, "pan.___", state 1670, "(1)" + line 235, "pan.___", state 1671, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1671, "else" + line 239, "pan.___", state 1678, "(1)" + line 239, "pan.___", state 1679, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1679, "else" + line 244, "pan.___", state 1688, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1688, "else" + line 1191, "pan.___", state 1694, "-end-" + (328 of 1694 states) +unreached in proctype :init: + (0 of 78 states) +unreached in proctype :never: + line 1252, "pan.___", state 11, "-end-" + (1 of 11 states) + +pan: elapsed time 0.03 seconds +pan: rate 32966.667 states/second +pan: avg transition delay 1.6739e-06 usec +cp .input.spin urcu_progress_reader.spin.input +cp .input.spin.trail urcu_progress_reader.spin.input.trail +make[1]: Leaving directory `/home/compudj/doc/userspace-rcu/formal-model/urcu-controldataflow' diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_reader.spin.input b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_reader.spin.input new file mode 100644 index 0000000..9f350f2 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_reader.spin.input @@ -0,0 +1,1227 @@ +#define READER_PROGRESS + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* We choose to ignore writer's non-progress caused from the + * reader ignoring the writer's mb() requests */ +#ifdef WRITER_PROGRESS +progress_writer_from_reader: +#endif + break; + od; +} + +#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: +#define PROGRESS_LABEL(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; \ + /* \ + * 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) \ + do \ + :: (reader_barrier[i] == 1) -> skip; \ + :: (reader_barrier[i] == 0) -> break; \ + od; \ + i++; \ + :: i >= NR_READERS -> \ + break \ + od; \ + smp_mb(i, j); \ +} + +#else + +#define smp_mb_send(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + :: 1 -> skip; + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_reader.spin.input.trail b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_reader.spin.input.trail new file mode 100644 index 0000000..46f9f69 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_reader.spin.input.trail @@ -0,0 +1,2937 @@ +-2:3:-2 +-4:-4:-4 +1:0:4644 +2:3:4564 +3:3:4567 +4:3:4567 +5:3:4570 +6:3:4578 +7:3:4578 +8:3:4581 +9:3:4587 +10:3:4591 +11:3:4591 +12:3:4594 +13:3:4604 +14:3:4612 +15:3:4612 +16:3:4615 +17:3:4621 +18:3:4625 +19:3:4625 +20:3:4628 +21:3:4634 +22:3:4638 +23:3:4639 +24:0:4644 +25:3:4641 +26:0:4644 +27:2:2872 +28:0:4644 +29:2:2878 +30:0:4644 +31:2:2879 +32:0:4644 +33:2:2881 +34:0:4644 +35:2:2882 +36:0:4644 +37:2:2883 +38:2:2884 +39:2:2888 +40:2:2889 +41:2:2897 +42:2:2898 +43:2:2902 +44:2:2903 +45:2:2911 +46:2:2916 +47:2:2920 +48:2:2921 +49:2:2929 +50:2:2930 +51:2:2934 +52:2:2935 +53:2:2929 +54:2:2930 +55:2:2934 +56:2:2935 +57:2:2943 +58:2:2948 +59:2:2949 +60:2:2960 +61:2:2961 +62:2:2962 +63:2:2973 +64:2:2978 +65:2:2979 +66:2:2990 +67:2:2991 +68:2:2992 +69:2:2990 +70:2:2991 +71:2:2992 +72:2:3003 +73:2:3011 +74:0:4644 +75:2:2882 +76:0:4644 +77:2:3015 +78:2:3019 +79:2:3020 +80:2:3024 +81:2:3028 +82:2:3029 +83:2:3033 +84:2:3041 +85:2:3042 +86:2:3046 +87:2:3050 +88:2:3051 +89:2:3046 +90:2:3047 +91:2:3055 +92:0:4644 +93:2:2882 +94:0:4644 +95:2:3063 +96:2:3064 +97:2:3065 +98:0:4644 +99:2:2882 +100:0:4644 +101:2:3070 +102:0:4644 +103:2:3773 +104:2:3774 +105:2:3778 +106:2:3782 +107:2:3783 +108:2:3787 +109:2:3792 +110:2:3800 +111:2:3804 +112:2:3805 +113:2:3800 +114:2:3804 +115:2:3805 +116:2:3809 +117:2:3816 +118:2:3823 +119:2:3824 +120:2:3831 +121:2:3836 +122:2:3843 +123:2:3844 +124:2:3843 +125:2:3844 +126:2:3851 +127:2:3855 +128:0:4644 +129:2:3860 +130:0:4644 +131:2:3861 +132:0:4644 +133:2:3862 +134:0:4644 +135:2:3863 +136:0:4644 +137:1:2 +138:0:4644 +139:2:3864 +140:0:4644 +141:1:8 +142:0:4644 +143:2:3863 +144:0:4644 +145:1:9 +146:0:4644 +147:2:3864 +148:0:4644 +149:1:10 +150:0:4642 +151:2:3863 +152:0:4648 +153:2:3864 +154:0:4648 +155:1:11 +156:0:4648 +157:2:3863 +158:0:4648 +159:2:3864 +160:0:4648 +161:1:12 +162:0:4648 +163:2:3863 +164:0:4648 +165:2:3864 +166:0:4648 +167:1:13 +168:0:4648 +169:2:3863 +170:0:4648 +171:2:3864 +172:0:4648 +173:1:14 +174:0:4648 +175:1:15 +176:0:4648 +177:1:16 +178:0:4648 +179:2:3863 +180:0:4648 +181:2:3864 +182:0:4648 +183:1:17 +184:0:4648 +185:2:3863 +186:0:4648 +187:2:3864 +188:0:4648 +189:1:28 +190:0:4648 +191:2:3863 +192:0:4648 +193:2:3864 +194:0:4648 +195:1:32 +196:1:33 +197:1:37 +198:1:41 +199:1:42 +200:1:46 +201:1:54 +202:1:55 +203:1:59 +204:1:63 +205:1:64 +206:1:59 +207:1:63 +208:1:64 +209:1:68 +210:1:75 +211:1:82 +212:1:83 +213:1:90 +214:1:95 +215:1:102 +216:1:103 +217:1:102 +218:1:103 +219:1:110 +220:1:114 +221:0:4648 +222:2:3863 +223:0:4648 +224:2:3864 +225:0:4648 +226:1:119 +227:0:4648 +228:2:3865 +229:0:4648 +230:2:3870 +231:0:4648 +232:2:3871 +233:0:4648 +234:2:3879 +235:2:3880 +236:2:3884 +237:2:3888 +238:2:3889 +239:2:3893 +240:2:3901 +241:2:3902 +242:2:3906 +243:2:3910 +244:2:3911 +245:2:3906 +246:2:3910 +247:2:3911 +248:2:3915 +249:2:3922 +250:2:3929 +251:2:3930 +252:2:3937 +253:2:3942 +254:2:3949 +255:2:3950 +256:2:3949 +257:2:3950 +258:2:3957 +259:2:3961 +260:0:4648 +261:2:3072 +262:2:3754 +263:0:4648 +264:2:2882 +265:0:4648 +266:2:3073 +267:0:4648 +268:2:2882 +269:0:4648 +270:2:3076 +271:2:3077 +272:2:3081 +273:2:3082 +274:2:3090 +275:2:3091 +276:2:3095 +277:2:3096 +278:2:3104 +279:2:3109 +280:2:3113 +281:2:3114 +282:2:3122 +283:2:3123 +284:2:3127 +285:2:3128 +286:2:3122 +287:2:3123 +288:2:3127 +289:2:3128 +290:2:3136 +291:2:3141 +292:2:3142 +293:2:3153 +294:2:3154 +295:2:3155 +296:2:3166 +297:2:3171 +298:2:3172 +299:2:3183 +300:2:3184 +301:2:3185 +302:2:3183 +303:2:3184 +304:2:3185 +305:2:3196 +306:2:3203 +307:0:4648 +308:2:2882 +309:0:4648 +310:2:3207 +311:2:3208 +312:2:3209 +313:2:3221 +314:2:3222 +315:2:3226 +316:2:3227 +317:2:3235 +318:2:3240 +319:2:3244 +320:2:3245 +321:2:3253 +322:2:3254 +323:2:3258 +324:2:3259 +325:2:3253 +326:2:3254 +327:2:3258 +328:2:3259 +329:2:3267 +330:2:3272 +331:2:3273 +332:2:3284 +333:2:3285 +334:2:3286 +335:2:3297 +336:2:3302 +337:2:3303 +338:2:3314 +339:2:3315 +340:2:3316 +341:2:3314 +342:2:3315 +343:2:3316 +344:2:3327 +345:2:3338 +346:2:3339 +347:0:4648 +348:2:2882 +349:0:4648 +350:2:3345 +351:2:3346 +352:2:3350 +353:2:3351 +354:2:3359 +355:2:3360 +356:2:3364 +357:2:3365 +358:2:3373 +359:2:3378 +360:2:3382 +361:2:3383 +362:2:3391 +363:2:3392 +364:2:3396 +365:2:3397 +366:2:3391 +367:2:3392 +368:2:3396 +369:2:3397 +370:2:3405 +371:2:3410 +372:2:3411 +373:2:3422 +374:2:3423 +375:2:3424 +376:2:3435 +377:2:3440 +378:2:3441 +379:2:3452 +380:2:3453 +381:2:3454 +382:2:3452 +383:2:3453 +384:2:3454 +385:2:3465 +386:0:4648 +387:2:2882 +388:0:4648 +389:2:3474 +390:2:3475 +391:2:3479 +392:2:3480 +393:2:3488 +394:2:3489 +395:2:3493 +396:2:3494 +397:2:3502 +398:2:3507 +399:2:3511 +400:2:3512 +401:2:3520 +402:2:3521 +403:2:3525 +404:2:3526 +405:2:3520 +406:2:3521 +407:2:3525 +408:2:3526 +409:2:3534 +410:2:3539 +411:2:3540 +412:2:3551 +413:2:3552 +414:2:3553 +415:2:3564 +416:2:3569 +417:2:3570 +418:2:3581 +419:2:3582 +420:2:3583 +421:2:3581 +422:2:3582 +423:2:3583 +424:2:3594 +425:2:3601 +426:0:4648 +427:2:2882 +428:0:4648 +429:2:3605 +430:2:3606 +431:2:3607 +432:2:3619 +433:2:3620 +434:2:3624 +435:2:3625 +436:2:3633 +437:2:3638 +438:2:3642 +439:2:3643 +440:2:3651 +441:2:3652 +442:2:3656 +443:2:3657 +444:2:3651 +445:2:3652 +446:2:3656 +447:2:3657 +448:2:3665 +449:2:3670 +450:2:3671 +451:2:3682 +452:2:3683 +453:2:3684 +454:2:3695 +455:2:3700 +456:2:3701 +457:2:3712 +458:2:3713 +459:2:3714 +460:2:3712 +461:2:3713 +462:2:3714 +463:2:3725 +464:2:3735 +465:2:3736 +466:0:4648 +467:2:2882 +468:0:4648 +469:2:3742 +470:0:4648 +471:2:4367 +472:2:4368 +473:2:4372 +474:2:4376 +475:2:4377 +476:2:4381 +477:2:4389 +478:2:4390 +479:2:4394 +480:2:4398 +481:2:4399 +482:2:4394 +483:2:4398 +484:2:4399 +485:2:4403 +486:2:4410 +487:2:4417 +488:2:4418 +489:2:4425 +490:2:4430 +491:2:4437 +492:2:4438 +493:2:4437 +494:2:4438 +495:2:4445 +496:2:4449 +497:0:4648 +498:2:4454 +499:0:4648 +500:2:4455 +501:0:4648 +502:2:4456 +503:0:4648 +504:2:4457 +505:0:4648 +506:1:28 +507:0:4648 +508:2:4458 +509:0:4648 +510:2:4457 +511:0:4648 +512:1:32 +513:1:33 +514:1:37 +515:1:41 +516:1:42 +517:1:46 +518:1:54 +519:1:55 +520:1:59 +521:1:63 +522:1:64 +523:1:59 +524:1:63 +525:1:64 +526:1:68 +527:1:75 +528:1:82 +529:1:83 +530:1:90 +531:1:95 +532:1:102 +533:1:103 +534:1:102 +535:1:103 +536:1:110 +537:1:114 +538:0:4648 +539:2:4458 +540:0:4648 +541:2:4457 +542:0:4648 +543:1:119 +544:0:4648 +545:2:4458 +546:0:4648 +547:2:4459 +548:0:4648 +549:2:4464 +550:0:4648 +551:2:4465 +552:0:4648 +553:2:4473 +554:2:4474 +555:2:4478 +556:2:4482 +557:2:4483 +558:2:4487 +559:2:4495 +560:2:4496 +561:2:4500 +562:2:4504 +563:2:4505 +564:2:4500 +565:2:4504 +566:2:4505 +567:2:4509 +568:2:4516 +569:2:4523 +570:2:4524 +571:2:4531 +572:2:4536 +573:2:4543 +574:2:4544 +575:2:4543 +576:2:4544 +577:2:4551 +578:2:4555 +579:0:4648 +580:2:3744 +581:2:3754 +582:0:4648 +583:2:2882 +584:0:4648 +585:2:3745 +586:2:3746 +587:0:4648 +588:2:2882 +589:0:4648 +590:2:3750 +591:0:4648 +592:2:3758 +593:0:4648 +594:2:2879 +595:0:4648 +596:2:2881 +597:0:4648 +598:2:2882 +599:0:4648 +600:2:2883 +601:2:2884 +602:2:2888 +603:2:2889 +604:2:2897 +605:2:2898 +606:2:2902 +607:2:2903 +608:2:2911 +609:2:2916 +610:2:2920 +611:2:2921 +612:2:2929 +613:2:2930 +614:2:2931 +615:2:2929 +616:2:2930 +617:2:2934 +618:2:2935 +619:2:2943 +620:2:2948 +621:2:2949 +622:2:2960 +623:2:2961 +624:2:2962 +625:2:2973 +626:2:2978 +627:2:2979 +628:2:2990 +629:2:2991 +630:2:2992 +631:2:2990 +632:2:2991 +633:2:2992 +634:2:3003 +635:2:3011 +636:0:4648 +637:2:2882 +638:0:4648 +639:2:3015 +640:2:3019 +641:2:3020 +642:2:3024 +643:2:3028 +644:2:3029 +645:2:3033 +646:2:3041 +647:2:3042 +648:2:3046 +649:2:3047 +650:2:3046 +651:2:3050 +652:2:3051 +653:2:3055 +654:0:4648 +655:2:2882 +656:0:4648 +657:2:3063 +658:2:3064 +659:2:3065 +660:0:4648 +661:2:2882 +662:0:4648 +663:2:3070 +664:0:4648 +665:2:3773 +666:2:3774 +667:2:3778 +668:2:3782 +669:2:3783 +670:2:3787 +671:2:3792 +672:2:3800 +673:2:3804 +674:2:3805 +675:2:3800 +676:2:3804 +677:2:3805 +678:2:3809 +679:2:3816 +680:2:3823 +681:2:3824 +682:2:3831 +683:2:3836 +684:2:3843 +685:2:3844 +686:2:3843 +687:2:3844 +688:2:3851 +689:2:3855 +690:0:4648 +691:2:3860 +692:0:4648 +693:2:3861 +694:0:4648 +695:2:3862 +696:0:4648 +697:2:3863 +698:0:4648 +699:1:28 +700:0:4648 +701:2:3864 +702:0:4648 +703:2:3863 +704:0:4648 +705:1:32 +706:1:33 +707:1:37 +708:1:41 +709:1:42 +710:1:46 +711:1:54 +712:1:55 +713:1:59 +714:1:63 +715:1:64 +716:1:59 +717:1:63 +718:1:64 +719:1:68 +720:1:75 +721:1:82 +722:1:83 +723:1:90 +724:1:95 +725:1:102 +726:1:103 +727:1:102 +728:1:103 +729:1:110 +730:1:114 +731:0:4648 +732:2:3864 +733:0:4648 +734:2:3863 +735:0:4648 +736:1:119 +737:0:4648 +738:2:3864 +739:0:4648 +740:2:3865 +741:0:4648 +742:2:3870 +743:0:4648 +744:2:3871 +745:0:4648 +746:2:3879 +747:2:3880 +748:2:3884 +749:2:3888 +750:2:3889 +751:2:3893 +752:2:3901 +753:2:3902 +754:2:3906 +755:2:3910 +756:2:3911 +757:2:3906 +758:2:3910 +759:2:3911 +760:2:3915 +761:2:3922 +762:2:3929 +763:2:3930 +764:2:3937 +765:2:3942 +766:2:3949 +767:2:3950 +768:2:3949 +769:2:3950 +770:2:3957 +771:2:3961 +772:0:4648 +773:2:3072 +774:2:3754 +775:0:4648 +776:2:2882 +777:0:4648 +778:2:3073 +779:0:4648 +780:2:2882 +781:0:4648 +782:2:3076 +783:2:3077 +784:2:3081 +785:2:3082 +786:2:3090 +787:2:3091 +788:2:3095 +789:2:3096 +790:2:3104 +791:2:3109 +792:2:3113 +793:2:3114 +794:2:3122 +795:2:3123 +796:2:3127 +797:2:3128 +798:2:3122 +799:2:3123 +800:2:3127 +801:2:3128 +802:2:3136 +803:2:3141 +804:2:3142 +805:2:3153 +806:2:3154 +807:2:3155 +808:2:3166 +809:2:3171 +810:2:3172 +811:2:3183 +812:2:3184 +813:2:3185 +814:2:3183 +815:2:3184 +816:2:3185 +817:2:3196 +818:2:3203 +819:0:4648 +820:2:2882 +821:0:4648 +822:2:3207 +823:2:3208 +824:2:3209 +825:2:3221 +826:2:3222 +827:2:3226 +828:2:3227 +829:2:3235 +830:2:3240 +831:2:3244 +832:2:3245 +833:2:3253 +834:2:3254 +835:2:3258 +836:2:3259 +837:2:3253 +838:2:3254 +839:2:3258 +840:2:3259 +841:2:3267 +842:2:3272 +843:2:3273 +844:2:3284 +845:2:3285 +846:2:3286 +847:2:3297 +848:2:3302 +849:2:3303 +850:2:3314 +851:2:3315 +852:2:3316 +853:2:3314 +854:2:3315 +855:2:3316 +856:2:3327 +857:2:3338 +858:2:3339 +859:0:4648 +860:2:2882 +861:0:4648 +862:2:3345 +863:2:3346 +864:2:3350 +865:2:3351 +866:2:3359 +867:2:3360 +868:2:3364 +869:2:3365 +870:2:3373 +871:2:3378 +872:2:3382 +873:2:3383 +874:2:3391 +875:2:3392 +876:2:3396 +877:2:3397 +878:2:3391 +879:2:3392 +880:2:3396 +881:2:3397 +882:2:3405 +883:2:3410 +884:2:3411 +885:2:3422 +886:2:3423 +887:2:3424 +888:2:3435 +889:2:3440 +890:2:3441 +891:2:3452 +892:2:3453 +893:2:3454 +894:2:3452 +895:2:3453 +896:2:3454 +897:2:3465 +898:0:4648 +899:2:2882 +900:0:4648 +901:2:3474 +902:2:3475 +903:2:3479 +904:2:3480 +905:2:3488 +906:2:3489 +907:2:3493 +908:2:3494 +909:2:3502 +910:2:3507 +911:2:3511 +912:2:3512 +913:2:3520 +914:2:3521 +915:2:3525 +916:2:3526 +917:2:3520 +918:2:3521 +919:2:3525 +920:2:3526 +921:2:3534 +922:2:3539 +923:2:3540 +924:2:3551 +925:2:3552 +926:2:3553 +927:2:3564 +928:2:3569 +929:2:3570 +930:2:3581 +931:2:3582 +932:2:3583 +933:2:3581 +934:2:3582 +935:2:3583 +936:2:3594 +937:2:3601 +938:0:4648 +939:2:2882 +940:0:4648 +941:2:3605 +942:2:3606 +943:2:3607 +944:2:3619 +945:2:3620 +946:2:3624 +947:2:3625 +948:2:3633 +949:2:3638 +950:2:3642 +951:2:3643 +952:2:3651 +953:2:3652 +954:2:3656 +955:2:3657 +956:2:3651 +957:2:3652 +958:2:3656 +959:2:3657 +960:2:3665 +961:2:3670 +962:2:3671 +963:2:3682 +964:2:3683 +965:2:3684 +966:2:3695 +967:2:3700 +968:2:3701 +969:2:3712 +970:2:3713 +971:2:3714 +972:2:3712 +973:2:3713 +974:2:3714 +975:2:3725 +976:2:3735 +977:2:3736 +978:0:4648 +979:2:2882 +980:0:4648 +981:2:3742 +982:0:4648 +983:2:4367 +984:2:4368 +985:2:4372 +986:2:4376 +987:2:4377 +988:2:4381 +989:2:4389 +990:2:4390 +991:2:4394 +992:2:4398 +993:2:4399 +994:2:4394 +995:2:4398 +996:2:4399 +997:2:4403 +998:2:4410 +999:2:4417 +1000:2:4418 +1001:2:4425 +1002:2:4430 +1003:2:4437 +1004:2:4438 +1005:2:4437 +1006:2:4438 +1007:2:4445 +1008:2:4449 +1009:0:4648 +1010:2:4454 +1011:0:4648 +1012:2:4455 +1013:0:4648 +1014:2:4456 +1015:0:4648 +1016:2:4457 +1017:0:4648 +1018:1:28 +1019:0:4648 +1020:2:4458 +1021:0:4648 +1022:2:4457 +1023:0:4648 +1024:1:32 +1025:1:33 +1026:1:37 +1027:1:41 +1028:1:42 +1029:1:46 +1030:1:54 +1031:1:55 +1032:1:59 +1033:1:63 +1034:1:64 +1035:1:59 +1036:1:63 +1037:1:64 +1038:1:68 +1039:1:75 +1040:1:82 +1041:1:83 +1042:1:90 +1043:1:95 +1044:1:102 +1045:1:103 +1046:1:102 +1047:1:103 +1048:1:110 +1049:1:114 +1050:0:4648 +1051:2:4458 +1052:0:4648 +1053:2:4457 +1054:0:4648 +1055:1:119 +1056:0:4648 +1057:2:4458 +1058:0:4648 +1059:2:4459 +1060:0:4648 +1061:2:4464 +1062:0:4648 +1063:2:4465 +1064:0:4648 +1065:2:4473 +1066:2:4474 +1067:2:4478 +1068:2:4482 +1069:2:4483 +1070:2:4487 +1071:2:4495 +1072:2:4496 +1073:2:4500 +1074:2:4504 +1075:2:4505 +1076:2:4500 +1077:2:4504 +1078:2:4505 +1079:2:4509 +1080:2:4516 +1081:2:4523 +1082:2:4524 +1083:2:4531 +1084:2:4536 +1085:2:4543 +1086:2:4544 +1087:2:4543 +1088:2:4544 +1089:2:4551 +1090:2:4555 +1091:0:4648 +1092:2:3744 +1093:2:3754 +1094:0:4648 +1095:2:2882 +1096:0:4648 +1097:2:3745 +1098:2:3746 +1099:0:4648 +1100:2:2882 +1101:0:4648 +1102:2:3750 +1103:0:4648 +1104:2:3758 +1105:0:4648 +1106:2:2879 +1107:0:4648 +1108:2:2881 +1109:0:4648 +1110:2:2882 +1111:0:4648 +1112:2:2883 +1113:2:2884 +1114:2:2888 +1115:2:2889 +1116:2:2897 +1117:2:2898 +1118:2:2902 +1119:2:2903 +1120:2:2911 +1121:2:2916 +1122:2:2920 +1123:2:2921 +1124:2:2929 +1125:2:2930 +1126:2:2934 +1127:2:2935 +1128:2:2929 +1129:2:2930 +1130:2:2931 +1131:2:2943 +1132:2:2948 +1133:2:2949 +1134:2:2960 +1135:2:2961 +1136:2:2962 +1137:2:2973 +1138:2:2978 +1139:2:2979 +1140:2:2990 +1141:2:2991 +1142:2:2992 +1143:2:2990 +1144:2:2991 +1145:2:2992 +1146:2:3003 +1147:2:3011 +1148:0:4648 +1149:2:2882 +1150:0:4648 +1151:2:3015 +1152:2:3019 +1153:2:3020 +1154:2:3024 +1155:2:3028 +1156:2:3029 +1157:2:3033 +1158:2:3041 +1159:2:3042 +1160:2:3046 +1161:2:3050 +1162:2:3051 +1163:2:3046 +1164:2:3047 +1165:2:3055 +1166:0:4648 +1167:2:2882 +1168:0:4648 +1169:2:3063 +1170:2:3064 +1171:2:3065 +1172:0:4648 +1173:2:2882 +1174:0:4648 +1175:2:3070 +1176:0:4648 +1177:2:3773 +1178:2:3774 +1179:2:3778 +1180:2:3782 +1181:2:3783 +1182:2:3787 +1183:2:3792 +1184:2:3800 +1185:2:3804 +1186:2:3805 +1187:2:3800 +1188:2:3804 +1189:2:3805 +1190:2:3809 +1191:2:3816 +1192:2:3823 +1193:2:3824 +1194:2:3831 +1195:2:3836 +1196:2:3843 +1197:2:3844 +1198:2:3843 +1199:2:3844 +1200:2:3851 +1201:2:3855 +1202:0:4648 +1203:2:3860 +1204:0:4648 +1205:2:3861 +1206:0:4648 +1207:2:3862 +1208:0:4648 +1209:2:3863 +1210:0:4648 +1211:1:28 +1212:0:4648 +1213:2:3864 +1214:0:4648 +1215:2:3863 +1216:0:4648 +1217:1:32 +1218:1:33 +1219:1:37 +1220:1:41 +1221:1:42 +1222:1:46 +1223:1:54 +1224:1:55 +1225:1:59 +1226:1:63 +1227:1:64 +1228:1:59 +1229:1:63 +1230:1:64 +1231:1:68 +1232:1:75 +1233:1:82 +1234:1:83 +1235:1:90 +1236:1:95 +1237:1:102 +1238:1:103 +1239:1:102 +1240:1:103 +1241:1:110 +1242:1:114 +1243:0:4648 +1244:2:3864 +1245:0:4648 +1246:2:3863 +1247:0:4648 +1248:1:119 +1249:0:4648 +1250:2:3864 +1251:0:4648 +1252:2:3865 +1253:0:4648 +1254:2:3870 +1255:0:4648 +1256:2:3871 +1257:0:4648 +1258:2:3879 +1259:2:3880 +1260:2:3884 +1261:2:3888 +1262:2:3889 +1263:2:3893 +1264:2:3901 +1265:2:3902 +1266:2:3906 +1267:2:3910 +1268:2:3911 +1269:2:3906 +1270:2:3910 +1271:2:3911 +1272:2:3915 +1273:2:3922 +1274:2:3929 +1275:2:3930 +1276:2:3937 +1277:2:3942 +1278:2:3949 +1279:2:3950 +1280:2:3949 +1281:2:3950 +1282:2:3957 +1283:2:3961 +1284:0:4648 +1285:2:3072 +1286:2:3754 +1287:0:4648 +1288:2:2882 +1289:0:4648 +1290:2:3073 +1291:0:4648 +1292:2:2882 +1293:0:4648 +1294:2:3076 +1295:2:3077 +1296:2:3081 +1297:2:3082 +1298:2:3090 +1299:2:3091 +1300:2:3095 +1301:2:3096 +1302:2:3104 +1303:2:3109 +1304:2:3113 +1305:2:3114 +1306:2:3122 +1307:2:3123 +1308:2:3127 +1309:2:3128 +1310:2:3122 +1311:2:3123 +1312:2:3127 +1313:2:3128 +1314:2:3136 +1315:2:3141 +1316:2:3142 +1317:2:3153 +1318:2:3154 +1319:2:3155 +1320:2:3166 +1321:2:3171 +1322:2:3172 +1323:2:3183 +1324:2:3184 +1325:2:3185 +1326:2:3183 +1327:2:3184 +1328:2:3185 +1329:2:3196 +1330:2:3203 +1331:0:4648 +1332:2:2882 +1333:0:4648 +1334:2:3207 +1335:2:3208 +1336:2:3209 +1337:2:3221 +1338:2:3222 +1339:2:3226 +1340:2:3227 +1341:2:3235 +1342:2:3240 +1343:2:3244 +1344:2:3245 +1345:2:3253 +1346:2:3254 +1347:2:3258 +1348:2:3259 +1349:2:3253 +1350:2:3254 +1351:2:3258 +1352:2:3259 +1353:2:3267 +1354:2:3272 +1355:2:3273 +1356:2:3284 +1357:2:3285 +1358:2:3286 +1359:2:3297 +1360:2:3302 +1361:2:3303 +1362:2:3314 +1363:2:3315 +1364:2:3316 +1365:2:3314 +1366:2:3315 +1367:2:3316 +1368:2:3327 +1369:2:3338 +1370:2:3339 +1371:0:4648 +1372:2:2882 +1373:0:4648 +1374:2:3345 +1375:2:3346 +1376:2:3350 +1377:2:3351 +1378:2:3359 +1379:2:3360 +1380:2:3364 +1381:2:3365 +1382:2:3373 +1383:2:3378 +1384:2:3382 +1385:2:3383 +1386:2:3391 +1387:2:3392 +1388:2:3396 +1389:2:3397 +1390:2:3391 +1391:2:3392 +1392:2:3396 +1393:2:3397 +1394:2:3405 +1395:2:3410 +1396:2:3411 +1397:2:3422 +1398:2:3423 +1399:2:3424 +1400:2:3435 +1401:2:3440 +1402:2:3441 +1403:2:3452 +1404:2:3453 +1405:2:3454 +1406:2:3452 +1407:2:3453 +1408:2:3454 +1409:2:3465 +1410:0:4648 +1411:2:2882 +1412:0:4648 +1413:2:3474 +1414:2:3475 +1415:2:3479 +1416:2:3480 +1417:2:3488 +1418:2:3489 +1419:2:3493 +1420:2:3494 +1421:2:3502 +1422:2:3507 +1423:2:3511 +1424:2:3512 +1425:2:3520 +1426:2:3521 +1427:2:3525 +1428:2:3526 +1429:2:3520 +1430:2:3521 +1431:2:3525 +1432:2:3526 +1433:2:3534 +1434:2:3539 +1435:2:3540 +1436:2:3551 +1437:2:3552 +1438:2:3553 +1439:2:3564 +1440:2:3569 +1441:2:3570 +1442:2:3581 +1443:2:3582 +1444:2:3583 +1445:2:3581 +1446:2:3582 +1447:2:3583 +1448:2:3594 +1449:2:3601 +1450:0:4648 +1451:2:2882 +1452:0:4648 +1453:2:3605 +1454:2:3606 +1455:2:3607 +1456:2:3619 +1457:2:3620 +1458:2:3624 +1459:2:3625 +1460:2:3633 +1461:2:3638 +1462:2:3642 +1463:2:3643 +1464:2:3651 +1465:2:3652 +1466:2:3656 +1467:2:3657 +1468:2:3651 +1469:2:3652 +1470:2:3656 +1471:2:3657 +1472:2:3665 +1473:2:3670 +1474:2:3671 +1475:2:3682 +1476:2:3683 +1477:2:3684 +1478:2:3695 +1479:2:3700 +1480:2:3701 +1481:2:3712 +1482:2:3713 +1483:2:3714 +1484:2:3712 +1485:2:3713 +1486:2:3714 +1487:2:3725 +1488:2:3735 +1489:2:3736 +1490:0:4648 +1491:2:2882 +1492:0:4648 +1493:2:3742 +1494:0:4648 +1495:2:4367 +1496:2:4368 +1497:2:4372 +1498:2:4376 +1499:2:4377 +1500:2:4381 +1501:2:4389 +1502:2:4390 +1503:2:4394 +1504:2:4398 +1505:2:4399 +1506:2:4394 +1507:2:4398 +1508:2:4399 +1509:2:4403 +1510:2:4410 +1511:2:4417 +1512:2:4418 +1513:2:4425 +1514:2:4430 +1515:2:4437 +1516:2:4438 +1517:2:4437 +1518:2:4438 +1519:2:4445 +1520:2:4449 +1521:0:4648 +1522:2:4454 +1523:0:4648 +1524:2:4455 +1525:0:4648 +1526:2:4456 +1527:0:4648 +1528:2:4457 +1529:0:4648 +1530:1:28 +1531:0:4648 +1532:2:4458 +1533:0:4648 +1534:2:4457 +1535:0:4648 +1536:1:32 +1537:1:33 +1538:1:37 +1539:1:41 +1540:1:42 +1541:1:46 +1542:1:54 +1543:1:55 +1544:1:59 +1545:1:63 +1546:1:64 +1547:1:59 +1548:1:63 +1549:1:64 +1550:1:68 +1551:1:75 +1552:1:82 +1553:1:83 +1554:1:90 +1555:1:95 +1556:1:102 +1557:1:103 +1558:1:102 +1559:1:103 +1560:1:110 +1561:1:114 +1562:0:4648 +1563:2:4458 +1564:0:4648 +1565:2:4457 +1566:0:4648 +1567:1:119 +1568:0:4648 +1569:2:4458 +1570:0:4648 +1571:2:4459 +1572:0:4648 +1573:2:4464 +1574:0:4648 +1575:2:4465 +1576:0:4648 +1577:2:4473 +1578:2:4474 +1579:2:4478 +1580:2:4482 +1581:2:4483 +1582:2:4487 +1583:2:4495 +1584:2:4496 +1585:2:4500 +1586:2:4504 +1587:2:4505 +1588:2:4500 +1589:2:4504 +1590:2:4505 +1591:2:4509 +1592:2:4516 +1593:2:4523 +1594:2:4524 +1595:2:4531 +1596:2:4536 +1597:2:4543 +1598:2:4544 +1599:2:4543 +1600:2:4544 +1601:2:4551 +1602:2:4555 +1603:0:4648 +1604:2:3744 +1605:2:3754 +1606:0:4648 +1607:2:2882 +1608:0:4648 +1609:2:3745 +1610:2:3746 +1611:0:4648 +1612:2:2882 +1613:0:4648 +1614:2:3750 +1615:0:4648 +1616:2:3758 +1617:0:4648 +1618:2:3759 +1619:0:4648 +1620:2:3764 +1621:0:4648 +1622:1:120 +1623:0:4648 +1624:2:3765 +1625:0:4648 +1626:2:3764 +1627:0:4648 +1628:1:19 +1629:0:4648 +1630:2:3765 +1631:0:4648 +1632:2:3764 +1633:0:4648 +1634:1:127 +1635:1:128 +1636:1:132 +1637:1:133 +1638:1:141 +1639:1:142 +1640:1:146 +1641:1:147 +1642:1:155 +1643:1:160 +1644:1:164 +1645:1:165 +1646:1:173 +1647:1:174 +1648:1:178 +1649:1:179 +1650:1:173 +1651:1:174 +1652:1:178 +1653:1:179 +1654:1:187 +1655:1:192 +1656:1:193 +1657:1:204 +1658:1:205 +1659:1:206 +1660:1:217 +1661:1:222 +1662:1:223 +1663:1:234 +1664:1:235 +1665:1:236 +1666:1:234 +1667:1:235 +1668:1:236 +1669:1:247 +1670:0:4648 +1671:2:3765 +1672:0:4648 +1673:2:3764 +1674:0:4648 +1675:1:15 +1676:0:4648 +1677:2:3765 +1678:0:4648 +1679:2:3764 +1680:0:4648 +1681:1:16 +1682:0:4648 +1683:2:3765 +1684:0:4648 +1685:2:3764 +1686:0:4648 +1687:1:17 +1688:0:4648 +1689:2:3765 +1690:0:4648 +1691:2:3764 +1692:0:4648 +1693:1:120 +1694:0:4648 +1695:2:3765 +1696:0:4648 +1697:2:3764 +1698:0:4648 +1699:1:19 +1700:0:4648 +1701:2:3765 +1702:0:4648 +1703:2:3764 +1704:0:4648 +1705:1:256 +1706:1:257 +1707:0:4648 +1708:2:3765 +1709:0:4648 +1710:2:3764 +1711:0:4648 +1712:1:15 +1713:0:4648 +1714:2:3765 +1715:0:4648 +1716:2:3764 +1717:0:4648 +1718:1:16 +1719:0:4648 +1720:2:3765 +1721:0:4648 +1722:2:3764 +1723:0:4648 +1724:1:17 +1725:0:4648 +1726:2:3765 +1727:0:4648 +1728:2:3764 +1729:0:4648 +1730:1:120 +1731:0:4648 +1732:2:3765 +1733:0:4648 +1734:2:3764 +1735:0:4648 +1736:1:19 +1737:0:4648 +1738:2:3765 +1739:0:4648 +1740:2:3764 +1741:0:4648 +1742:1:263 +1743:1:264 +1744:1:268 +1745:1:269 +1746:1:277 +1747:1:278 +1748:1:282 +1749:1:283 +1750:1:291 +1751:1:296 +1752:1:300 +1753:1:301 +1754:1:309 +1755:1:310 +1756:1:314 +1757:1:315 +1758:1:309 +1759:1:310 +1760:1:314 +1761:1:315 +1762:1:323 +1763:1:328 +1764:1:329 +1765:1:340 +1766:1:341 +1767:1:342 +1768:1:353 +1769:1:358 +1770:1:359 +1771:1:370 +1772:1:371 +1773:1:372 +1774:1:370 +1775:1:371 +1776:1:372 +1777:1:383 +1778:0:4648 +1779:2:3765 +1780:0:4648 +1781:2:3764 +1782:0:4648 +1783:1:15 +1784:0:4648 +1785:2:3765 +1786:0:4648 +1787:2:3764 +1788:0:4648 +1789:1:16 +1790:0:4648 +1791:2:3765 +1792:0:4648 +1793:2:3764 +1794:0:4648 +1795:1:17 +1796:0:4648 +1797:2:3765 +1798:0:4648 +1799:2:3764 +1800:0:4648 +1801:1:120 +1802:0:4648 +1803:2:3765 +1804:0:4648 +1805:2:3764 +1806:0:4648 +1807:1:19 +1808:0:4648 +1809:2:3765 +1810:0:4648 +1811:2:3764 +1812:0:4648 +1813:1:392 +1814:1:393 +1815:1:397 +1816:1:398 +1817:1:406 +1818:1:407 +1819:1:411 +1820:1:412 +1821:1:420 +1822:1:425 +1823:1:429 +1824:1:430 +1825:1:438 +1826:1:439 +1827:1:443 +1828:1:444 +1829:1:438 +1830:1:439 +1831:1:443 +1832:1:444 +1833:1:452 +1834:1:457 +1835:1:458 +1836:1:469 +1837:1:470 +1838:1:471 +1839:1:482 +1840:1:487 +1841:1:488 +1842:1:499 +1843:1:500 +1844:1:501 +1845:1:499 +1846:1:500 +1847:1:501 +1848:1:512 +1849:1:519 +1850:0:4648 +1851:2:3765 +1852:0:4648 +1853:2:3764 +1854:0:4648 +1855:1:15 +1856:0:4648 +1857:2:3765 +1858:0:4648 +1859:2:3764 +1860:0:4648 +1861:1:16 +1862:0:4648 +1863:2:3765 +1864:0:4648 +1865:2:3764 +1866:0:4648 +1867:1:17 +1868:0:4648 +1869:2:3765 +1870:0:4648 +1871:2:3764 +1872:0:4648 +1873:1:120 +1874:0:4648 +1875:2:3765 +1876:0:4648 +1877:2:3764 +1878:0:4648 +1879:1:19 +1880:0:4648 +1881:2:3765 +1882:0:4648 +1883:2:3764 +1884:0:4648 +1885:1:657 +1886:1:658 +1887:1:662 +1888:1:663 +1889:1:671 +1890:1:672 +1891:1:673 +1892:1:685 +1893:1:690 +1894:1:694 +1895:1:695 +1896:1:703 +1897:1:704 +1898:1:708 +1899:1:709 +1900:1:703 +1901:1:704 +1902:1:708 +1903:1:709 +1904:1:717 +1905:1:722 +1906:1:723 +1907:1:734 +1908:1:735 +1909:1:736 +1910:1:747 +1911:1:752 +1912:1:753 +1913:1:764 +1914:1:765 +1915:1:766 +1916:1:764 +1917:1:765 +1918:1:766 +1919:1:777 +1920:0:4648 +1921:2:3765 +1922:0:4648 +1923:2:3764 +1924:0:4648 +1925:1:15 +1926:0:4648 +1927:2:3765 +1928:0:4648 +1929:2:3764 +1930:0:4648 +1931:1:16 +1932:0:4648 +1933:2:3765 +1934:0:4648 +1935:2:3764 +1936:0:4648 +1937:1:17 +1938:0:4648 +1939:2:3765 +1940:0:4648 +1941:2:3764 +1942:0:4648 +1943:1:120 +1944:0:4648 +1945:2:3765 +1946:0:4648 +1947:2:3764 +1948:0:4648 +1949:1:19 +1950:0:4648 +1951:2:3765 +1952:0:4648 +1953:2:3764 +1954:0:4648 +1955:1:786 +1956:1:789 +1957:1:790 +1958:0:4648 +1959:2:3765 +1960:0:4648 +1961:2:3764 +1962:0:4648 +1963:1:15 +1964:0:4648 +1965:2:3765 +1966:0:4648 +1967:2:3764 +1968:0:4648 +1969:1:16 +1970:0:4648 +1971:2:3765 +1972:0:4648 +1973:2:3764 +1974:0:4648 +1975:1:17 +1976:0:4648 +1977:2:3765 +1978:0:4648 +1979:2:3764 +1980:0:4648 +1981:1:120 +1982:0:4648 +1983:2:3765 +1984:0:4648 +1985:2:3764 +1986:0:4648 +1987:1:19 +1988:0:4648 +1989:2:3765 +1990:0:4648 +1991:2:3764 +1992:0:4648 +1993:1:1053 +1994:1:1054 +1995:1:1058 +1996:1:1059 +1997:1:1067 +1998:1:1068 +1999:1:1072 +2000:1:1073 +2001:1:1081 +2002:1:1086 +2003:1:1090 +2004:1:1091 +2005:1:1099 +2006:1:1100 +2007:1:1104 +2008:1:1105 +2009:1:1099 +2010:1:1100 +2011:1:1104 +2012:1:1105 +2013:1:1113 +2014:1:1118 +2015:1:1119 +2016:1:1130 +2017:1:1131 +2018:1:1132 +2019:1:1143 +2020:1:1148 +2021:1:1149 +2022:1:1160 +2023:1:1161 +2024:1:1162 +2025:1:1160 +2026:1:1161 +2027:1:1162 +2028:1:1173 +2029:1:1180 +2030:1:1184 +2031:0:4648 +2032:2:3765 +2033:0:4648 +2034:2:3764 +2035:0:4648 +2036:1:15 +2037:0:4648 +2038:2:3765 +2039:0:4648 +2040:2:3764 +2041:0:4648 +2042:1:16 +2043:0:4648 +2044:2:3765 +2045:0:4648 +2046:2:3764 +2047:0:4648 +2048:1:17 +2049:0:4648 +2050:2:3765 +2051:0:4648 +2052:2:3764 +2053:0:4648 +2054:1:120 +2055:0:4648 +2056:2:3765 +2057:0:4648 +2058:2:3764 +2059:0:4648 +2060:1:19 +2061:0:4648 +2062:2:3765 +2063:0:4648 +2064:2:3764 +2065:0:4648 +2066:1:1185 +2067:1:1186 +2068:1:1190 +2069:1:1191 +2070:1:1199 +2071:1:1200 +2072:1:1201 +2073:1:1213 +2074:1:1218 +2075:1:1222 +2076:1:1223 +2077:1:1231 +2078:1:1232 +2079:1:1236 +2080:1:1237 +2081:1:1231 +2082:1:1232 +2083:1:1236 +2084:1:1237 +2085:1:1245 +2086:1:1250 +2087:1:1251 +2088:1:1262 +2089:1:1263 +2090:1:1264 +2091:1:1275 +2092:1:1280 +2093:1:1281 +2094:1:1292 +2095:1:1293 +2096:1:1294 +2097:1:1292 +2098:1:1293 +2099:1:1294 +2100:1:1305 +2101:0:4648 +2102:2:3765 +2103:0:4648 +2104:2:3764 +2105:0:4648 +2106:1:15 +2107:0:4648 +2108:2:3765 +2109:0:4648 +2110:2:3764 +2111:0:4648 +2112:1:16 +2113:0:4648 +2114:2:3765 +2115:0:4648 +2116:2:3764 +2117:0:4648 +2118:1:17 +2119:0:4648 +2120:2:3765 +2121:0:4648 +2122:2:3764 +2123:0:4648 +2124:1:120 +2125:0:4648 +2126:2:3765 +2127:0:4648 +2128:2:3764 +2129:0:4648 +2130:1:19 +2131:0:4648 +2132:2:3765 +2133:0:4648 +2134:2:3764 +2135:0:4648 +2136:1:1314 +2137:0:4648 +2138:2:3765 +2139:0:4648 +2140:2:3764 +2141:0:4648 +2142:1:2778 +2143:1:2785 +2144:1:2786 +2145:1:2793 +2146:1:2798 +2147:1:2805 +2148:1:2806 +2149:1:2805 +2150:1:2806 +2151:1:2813 +2152:1:2817 +2153:0:4648 +2154:2:3765 +2155:0:4648 +2156:2:3764 +2157:0:4648 +2158:1:1316 +2159:1:1317 +2160:0:4648 +2161:2:3765 +2162:0:4648 +2163:2:3764 +2164:0:4648 +2165:1:15 +2166:0:4648 +2167:2:3765 +2168:0:4648 +2169:2:3764 +2170:0:4648 +2171:1:16 +2172:0:4648 +2173:2:3765 +2174:0:4648 +2175:2:3764 +2176:0:4648 +2177:1:17 +2178:0:4648 +2179:2:3765 +2180:0:4648 +2181:2:3764 +2182:0:4648 +2183:1:120 +2184:0:4648 +2185:2:3765 +2186:0:4648 +2187:2:3764 +2188:0:4648 +2189:1:19 +2190:0:4648 +2191:2:3765 +2192:0:4648 +2193:2:3764 +2194:0:4648 +2195:1:1318 +2196:1:1319 +2197:1:1323 +2198:1:1324 +2199:1:1332 +2200:1:1333 +2201:1:1337 +2202:1:1338 +2203:1:1346 +2204:1:1351 +2205:1:1355 +2206:1:1356 +2207:1:1364 +2208:1:1365 +2209:1:1369 +2210:1:1370 +2211:1:1364 +2212:1:1365 +2213:1:1369 +2214:1:1370 +2215:1:1378 +2216:1:1383 +2217:1:1384 +2218:1:1395 +2219:1:1396 +2220:1:1397 +2221:1:1408 +2222:1:1413 +2223:1:1414 +2224:1:1425 +2225:1:1426 +2226:1:1427 +2227:1:1425 +2228:1:1426 +2229:1:1427 +2230:1:1438 +2231:0:4648 +2232:2:3765 +2233:0:4648 +2234:2:3764 +2235:0:4648 +2236:1:15 +2237:0:4648 +2238:2:3765 +2239:0:4648 +2240:2:3764 +2241:0:4648 +2242:1:16 +2243:0:4648 +2244:2:3765 +2245:0:4648 +2246:2:3764 +2247:0:4648 +2248:1:17 +2249:0:4648 +2250:2:3765 +2251:0:4648 +2252:2:3764 +2253:0:4648 +2254:1:120 +2255:0:4648 +2256:2:3765 +2257:0:4648 +2258:2:3764 +2259:0:4648 +2260:1:19 +2261:0:4648 +2262:2:3765 +2263:0:4648 +2264:2:3764 +2265:0:4648 +2266:1:1447 +2267:1:1448 +2268:1:1452 +2269:1:1453 +2270:1:1461 +2271:1:1462 +2272:1:1466 +2273:1:1467 +2274:1:1475 +2275:1:1480 +2276:1:1484 +2277:1:1485 +2278:1:1493 +2279:1:1494 +2280:1:1498 +2281:1:1499 +2282:1:1493 +2283:1:1494 +2284:1:1498 +2285:1:1499 +2286:1:1507 +2287:1:1512 +2288:1:1513 +2289:1:1524 +2290:1:1525 +2291:1:1526 +2292:1:1537 +2293:1:1542 +2294:1:1543 +2295:1:1554 +2296:1:1555 +2297:1:1556 +2298:1:1554 +2299:1:1555 +2300:1:1556 +2301:1:1567 +2302:1:1574 +2303:1:1578 +2304:0:4648 +2305:2:3765 +2306:0:4648 +2307:2:3764 +2308:0:4648 +2309:1:15 +2310:0:4648 +2311:2:3765 +2312:0:4648 +2313:2:3764 +2314:0:4648 +2315:1:16 +2316:0:4648 +2317:2:3765 +2318:0:4648 +2319:2:3764 +2320:0:4648 +2321:1:17 +2322:0:4648 +2323:2:3765 +2324:0:4648 +2325:2:3764 +2326:0:4648 +2327:1:120 +2328:0:4648 +2329:2:3765 +2330:0:4648 +2331:2:3764 +2332:0:4648 +2333:1:19 +2334:0:4648 +2335:2:3765 +2336:0:4648 +2337:2:3764 +2338:0:4648 +2339:1:1581 +2340:1:1582 +2341:1:1586 +2342:1:1587 +2343:1:1595 +2344:1:1596 +2345:1:1597 +2346:1:1609 +2347:1:1614 +2348:1:1618 +2349:1:1619 +2350:1:1627 +2351:1:1628 +2352:1:1632 +2353:1:1633 +2354:1:1627 +2355:1:1628 +2356:1:1632 +2357:1:1633 +2358:1:1641 +2359:1:1646 +2360:1:1647 +2361:1:1658 +2362:1:1659 +2363:1:1660 +2364:1:1671 +2365:1:1676 +2366:1:1677 +2367:1:1688 +2368:1:1689 +2369:1:1690 +2370:1:1688 +2371:1:1689 +2372:1:1690 +2373:1:1701 +2374:0:4648 +2375:2:3765 +2376:0:4648 +2377:2:3764 +2378:0:4648 +2379:1:15 +2380:0:4648 +2381:2:3765 +2382:0:4648 +2383:2:3764 +2384:0:4648 +2385:1:16 +2386:0:4648 +2387:2:3765 +2388:0:4648 +2389:2:3764 +2390:0:4648 +2391:1:17 +2392:0:4648 +2393:2:3765 +2394:0:4648 +2395:2:3764 +2396:0:4648 +2397:1:120 +2398:0:4648 +2399:2:3765 +2400:0:4648 +2401:2:3764 +2402:0:4648 +2403:1:19 +2404:0:4648 +2405:2:3765 +2406:0:4648 +2407:2:3764 +2408:0:4648 +2409:1:1710 +2410:1:1711 +2411:1:1715 +2412:1:1716 +2413:1:1724 +2414:1:1725 +2415:1:1729 +2416:1:1730 +2417:1:1738 +2418:1:1743 +2419:1:1747 +2420:1:1748 +2421:1:1756 +2422:1:1757 +2423:1:1761 +2424:1:1762 +2425:1:1756 +2426:1:1757 +2427:1:1761 +2428:1:1762 +2429:1:1770 +2430:1:1775 +2431:1:1776 +2432:1:1787 +2433:1:1788 +2434:1:1789 +2435:1:1800 +2436:1:1805 +2437:1:1806 +2438:1:1817 +2439:1:1818 +2440:1:1819 +2441:1:1817 +2442:1:1818 +2443:1:1819 +2444:1:1830 +2445:1:1837 +2446:1:1841 +2447:0:4648 +2448:2:3765 +2449:0:4648 +2450:2:3764 +2451:0:4648 +2452:1:15 +2453:0:4648 +2454:2:3765 +2455:0:4648 +2456:2:3764 +2457:0:4648 +2458:1:16 +2459:0:4648 +2460:2:3765 +2461:0:4648 +2462:2:3764 +2463:0:4648 +2464:1:17 +2465:0:4648 +2466:2:3765 +2467:0:4648 +2468:2:3764 +2469:0:4648 +2470:1:120 +2471:0:4648 +2472:2:3765 +2473:0:4648 +2474:2:3764 +2475:0:4648 +2476:1:19 +2477:0:4648 +2478:2:3765 +2479:0:4648 +2480:2:3764 +2481:0:4648 +2482:1:1842 +2483:1:1843 +2484:1:1847 +2485:1:1848 +2486:1:1856 +2487:1:1857 +2488:1:1858 +2489:1:1870 +2490:1:1875 +2491:1:1879 +2492:1:1880 +2493:1:1888 +2494:1:1889 +2495:1:1893 +2496:1:1894 +2497:1:1888 +2498:1:1889 +2499:1:1893 +2500:1:1894 +2501:1:1902 +2502:1:1907 +2503:1:1908 +2504:1:1919 +2505:1:1920 +2506:1:1921 +2507:1:1932 +2508:1:1937 +2509:1:1938 +2510:1:1949 +2511:1:1950 +2512:1:1951 +2513:1:1949 +2514:1:1950 +2515:1:1951 +2516:1:1962 +2517:0:4648 +2518:2:3765 +2519:0:4648 +2520:2:3764 +2521:0:4648 +2522:1:15 +2523:0:4648 +2524:2:3765 +2525:0:4648 +2526:2:3764 +2527:0:4648 +2528:1:16 +2529:0:4648 +2530:2:3765 +2531:0:4648 +2532:2:3764 +2533:0:4648 +2534:1:17 +2535:0:4648 +2536:2:3765 +2537:0:4648 +2538:2:3764 +2539:0:4648 +2540:1:120 +2541:0:4648 +2542:2:3765 +2543:0:4648 +2544:2:3764 +2545:0:4648 +2546:1:19 +2547:0:4648 +2548:2:3765 +2549:0:4648 +2550:2:3764 +2551:0:4648 +2552:1:1971 +2553:1:1972 +2554:0:4648 +2555:2:3765 +2556:0:4648 +2557:2:3764 +2558:0:4648 +2559:1:15 +2560:0:4648 +2561:2:3765 +2562:0:4648 +2563:2:3764 +2564:0:4648 +2565:1:16 +2566:0:4648 +2567:2:3765 +2568:0:4648 +2569:2:3764 +2570:0:4648 +2571:1:17 +2572:0:4648 +2573:2:3765 +2574:0:4648 +2575:2:3764 +2576:0:4648 +2577:1:120 +2578:0:4648 +2579:2:3765 +2580:0:4648 +2581:2:3764 +2582:0:4648 +2583:1:19 +2584:0:4648 +2585:2:3765 +2586:0:4648 +2587:2:3764 +2588:0:4648 +2589:1:1978 +2590:1:1979 +2591:1:1983 +2592:1:1984 +2593:1:1992 +2594:1:1993 +2595:1:1997 +2596:1:1998 +2597:1:2006 +2598:1:2011 +2599:1:2015 +2600:1:2016 +2601:1:2024 +2602:1:2025 +2603:1:2029 +2604:1:2030 +2605:1:2024 +2606:1:2025 +2607:1:2029 +2608:1:2030 +2609:1:2038 +2610:1:2043 +2611:1:2044 +2612:1:2055 +2613:1:2056 +2614:1:2057 +2615:1:2068 +2616:1:2073 +2617:1:2074 +2618:1:2085 +2619:1:2086 +2620:1:2087 +2621:1:2085 +2622:1:2086 +2623:1:2087 +2624:1:2098 +2625:0:4648 +2626:2:3765 +2627:0:4648 +2628:2:3764 +2629:0:4648 +2630:1:15 +2631:0:4648 +2632:2:3765 +2633:0:4648 +2634:2:3764 +2635:0:4648 +2636:1:16 +2637:0:4648 +2638:2:3765 +2639:0:4648 +2640:2:3764 +2641:0:4648 +2642:1:17 +2643:0:4648 +2644:2:3765 +2645:0:4648 +2646:2:3764 +2647:0:4648 +2648:1:120 +2649:0:4648 +2650:2:3765 +2651:0:4648 +2652:2:3764 +2653:0:4648 +2654:1:19 +2655:0:4648 +2656:2:3765 +2657:0:4648 +2658:2:3764 +2659:0:4648 +2660:1:2107 +2661:1:2108 +2662:1:2112 +2663:1:2113 +2664:1:2121 +2665:1:2122 +2666:1:2126 +2667:1:2127 +2668:1:2135 +2669:1:2140 +2670:1:2144 +2671:1:2145 +2672:1:2153 +2673:1:2154 +2674:1:2158 +2675:1:2159 +2676:1:2153 +2677:1:2154 +2678:1:2158 +2679:1:2159 +2680:1:2167 +2681:1:2172 +2682:1:2173 +2683:1:2184 +2684:1:2185 +2685:1:2186 +2686:1:2197 +2687:1:2202 +2688:1:2203 +2689:1:2214 +2690:1:2215 +2691:1:2216 +2692:1:2214 +2693:1:2215 +2694:1:2216 +2695:1:2227 +2696:1:2234 +2697:0:4648 +2698:2:3765 +2699:0:4648 +2700:2:3764 +2701:0:4648 +2702:1:15 +2703:0:4648 +2704:2:3765 +2705:0:4648 +2706:2:3764 +2707:0:4648 +2708:1:16 +2709:0:4648 +2710:2:3765 +2711:0:4648 +2712:2:3764 +2713:0:4648 +2714:1:17 +2715:0:4648 +2716:2:3765 +2717:0:4648 +2718:2:3764 +2719:0:4648 +2720:1:120 +2721:0:4648 +2722:2:3765 +2723:0:4648 +2724:2:3764 +2725:0:4648 +2726:1:19 +2727:0:4648 +2728:2:3765 +2729:0:4648 +2730:2:3764 +2731:0:4648 +2732:1:2372 +2733:1:2373 +2734:1:2377 +2735:1:2378 +2736:1:2386 +2737:1:2387 +2738:1:2388 +2739:1:2400 +2740:1:2405 +2741:1:2409 +2742:1:2410 +2743:1:2418 +2744:1:2419 +2745:1:2423 +2746:1:2424 +2747:1:2418 +2748:1:2419 +2749:1:2423 +2750:1:2424 +2751:1:2432 +2752:1:2437 +2753:1:2438 +2754:1:2449 +2755:1:2450 +2756:1:2451 +2757:1:2462 +2758:1:2467 +2759:1:2468 +2760:1:2479 +2761:1:2480 +2762:1:2481 +2763:1:2479 +2764:1:2480 +2765:1:2481 +2766:1:2492 +2767:0:4648 +2768:2:3765 +2769:0:4648 +2770:2:3764 +2771:0:4648 +2772:1:15 +2773:0:4648 +2774:2:3765 +2775:0:4648 +2776:2:3764 +2777:0:4648 +2778:1:16 +2779:0:4648 +2780:2:3765 +2781:0:4648 +2782:2:3764 +2783:0:4648 +2784:1:17 +2785:0:4648 +2786:2:3765 +2787:0:4648 +2788:2:3764 +2789:0:4648 +2790:1:120 +2791:0:4648 +2792:2:3765 +2793:0:4648 +2794:2:3764 +2795:0:4648 +2796:1:19 +2797:0:4648 +2798:2:3765 +2799:0:4648 +2800:2:3764 +2801:0:4648 +2802:1:2507 +2803:1:2508 +2804:1:2512 +2805:1:2513 +2806:1:2521 +2807:1:2522 +2808:1:2526 +2809:1:2527 +2810:1:2535 +2811:1:2540 +2812:1:2544 +2813:1:2545 +2814:1:2553 +2815:1:2554 +2816:1:2558 +2817:1:2559 +2818:1:2553 +2819:1:2554 +2820:1:2558 +2821:1:2559 +2822:1:2567 +2823:1:2572 +2824:1:2573 +2825:1:2584 +2826:1:2585 +2827:1:2586 +2828:1:2597 +2829:1:2602 +2830:1:2603 +2831:1:2614 +2832:1:2615 +2833:1:2616 +2834:1:2614 +2835:1:2615 +2836:1:2616 +2837:1:2627 +2838:0:4648 +2839:2:3765 +2840:0:4648 +2841:2:3764 +2842:0:4648 +2843:1:15 +2844:0:4648 +2845:2:3765 +2846:0:4648 +2847:2:3764 +2848:0:4648 +2849:1:16 +2850:0:4648 +2851:2:3765 +2852:0:4648 +2853:2:3764 +2854:0:4648 +2855:1:17 +2856:0:4648 +2857:2:3765 +2858:0:4648 +2859:2:3764 +2860:0:4648 +2861:1:120 +2862:0:4648 +2863:2:3765 +2864:0:4648 +2865:2:3764 +2866:0:4648 +2867:1:19 +2868:0:4648 +2869:2:3765 +2870:0:4648 +2871:2:3764 +2872:0:4648 +2873:1:2636 +2874:1:2637 +2875:1:2641 +2876:1:2642 +2877:1:2650 +2878:1:2651 +2879:1:2655 +2880:1:2656 +2881:1:2664 +2882:1:2669 +2883:1:2673 +2884:1:2674 +2885:1:2682 +2886:1:2683 +2887:1:2687 +2888:1:2688 +2889:1:2682 +2890:1:2683 +2891:1:2687 +2892:1:2688 +2893:1:2696 +2894:1:2701 +2895:1:2702 +2896:1:2713 +2897:1:2714 +2898:1:2715 +2899:1:2726 +2900:1:2731 +2901:1:2732 +2902:1:2743 +2903:1:2744 +2904:1:2745 +2905:1:2743 +2906:1:2744 +2907:1:2745 +2908:1:2756 +2909:1:2763 +2910:1:2767 +2911:0:4648 +2912:2:3765 +2913:0:4648 +2914:2:3764 +2915:0:4648 +2916:1:15 +2917:0:4648 +2918:2:3765 +2919:0:4648 +2920:2:3764 +2921:0:4648 +2922:1:16 +-1:-1:-1 +2923:0:4648 +2924:2:3765 +2925:0:4648 +2926:2:3764 +2927:0:4648 +2928:2:3765 +2929:0:4648 +2930:2:3764 +2931:0:4648 +2932:2:3765 +2933:0:4648 +2934:2:3764 diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer.define b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer.define new file mode 100644 index 0000000..1e4417f --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer.define @@ -0,0 +1 @@ +#define WRITER_PROGRESS diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer.log b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer.log new file mode 100644 index 0000000..09dde01 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer.log @@ -0,0 +1,677 @@ +make[1]: Entering directory `/home/compudj/doc/userspace-rcu/formal-model/urcu-controldataflow' +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define > pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_progress.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_progress_writer.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -f -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1245) +depth 23: Claim reached state 9 (line 1250) +depth 51: Claim reached state 9 (line 1249) +pan: acceptance cycle (at depth 573) +pan: wrote .input.spin.trail + +(Spin Version 5.1.7 -- 23 December 2008) +Warning: Search not completed + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness enabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 3997, errors: 1 + 24768 states, stored (55970 visited) + 10426084 states, matched + 10482054 transitions (= visited+matched) + 56520057 atomic steps +hash conflicts: 68749 (resolved) + +Stats on memory usage (in Megabytes): + 2.740 equivalent memory usage for states (stored*(State-vector + overhead)) + 2.770 actual memory usage for states (unsuccessful compression: 101.10%) + state-vector as stored = 89 byte + 28 byte overhead + 8.000 memory used for hash table (-w20) + 457.764 memory used for DFS stack (-m10000000) + 468.498 total actual memory usage + +unreached in proctype urcu_reader + line 647, "pan.___", state 20, "(1)" + line 250, "pan.___", state 32, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 54, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 63, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 79, "(1)" + line 231, "pan.___", state 87, "(1)" + line 235, "pan.___", state 99, "(1)" + line 239, "pan.___", state 107, "(1)" + line 387, "pan.___", state 133, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 165, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 179, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 198, "(1)" + line 413, "pan.___", state 228, "(1)" + line 417, "pan.___", state 241, "(1)" + line 663, "pan.___", state 262, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 387, "pan.___", state 269, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 301, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 315, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 334, "(1)" + line 413, "pan.___", state 364, "(1)" + line 417, "pan.___", state 377, "(1)" + line 387, "pan.___", state 398, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 430, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 444, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 463, "(1)" + line 413, "pan.___", state 493, "(1)" + line 417, "pan.___", state 506, "(1)" + line 387, "pan.___", state 529, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 531, "(1)" + line 387, "pan.___", state 532, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 532, "else" + line 387, "pan.___", state 535, "(1)" + line 391, "pan.___", state 543, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 545, "(1)" + line 391, "pan.___", state 546, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 546, "else" + line 391, "pan.___", state 549, "(1)" + line 391, "pan.___", state 550, "(1)" + line 391, "pan.___", state 550, "(1)" + line 389, "pan.___", state 555, "((i<1))" + line 389, "pan.___", state 555, "((i>=1))" + line 396, "pan.___", state 561, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 563, "(1)" + line 396, "pan.___", state 564, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 564, "else" + line 396, "pan.___", state 567, "(1)" + line 396, "pan.___", state 568, "(1)" + line 396, "pan.___", state 568, "(1)" + line 400, "pan.___", state 575, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 577, "(1)" + line 400, "pan.___", state 578, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 578, "else" + line 400, "pan.___", state 581, "(1)" + line 400, "pan.___", state 582, "(1)" + line 400, "pan.___", state 582, "(1)" + line 398, "pan.___", state 587, "((i<2))" + line 398, "pan.___", state 587, "((i>=2))" + line 404, "pan.___", state 594, "(1)" + line 404, "pan.___", state 595, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 595, "else" + line 404, "pan.___", state 598, "(1)" + line 404, "pan.___", state 599, "(1)" + line 404, "pan.___", state 599, "(1)" + line 408, "pan.___", state 607, "(1)" + line 408, "pan.___", state 608, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 608, "else" + line 408, "pan.___", state 611, "(1)" + line 408, "pan.___", state 612, "(1)" + line 408, "pan.___", state 612, "(1)" + line 406, "pan.___", state 617, "((i<1))" + line 406, "pan.___", state 617, "((i>=1))" + line 413, "pan.___", state 624, "(1)" + line 413, "pan.___", state 625, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 625, "else" + line 413, "pan.___", state 628, "(1)" + line 413, "pan.___", state 629, "(1)" + line 413, "pan.___", state 629, "(1)" + line 417, "pan.___", state 637, "(1)" + line 417, "pan.___", state 638, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 638, "else" + line 417, "pan.___", state 641, "(1)" + line 417, "pan.___", state 642, "(1)" + line 417, "pan.___", state 642, "(1)" + line 415, "pan.___", state 647, "((i<2))" + line 415, "pan.___", state 647, "((i>=2))" + line 422, "pan.___", state 651, "(1)" + line 422, "pan.___", state 651, "(1)" + line 663, "pan.___", state 654, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 663, "pan.___", state 655, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 663, "pan.___", state 656, "(1)" + line 387, "pan.___", state 663, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 695, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 709, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 728, "(1)" + line 413, "pan.___", state 758, "(1)" + line 417, "pan.___", state 771, "(1)" + line 387, "pan.___", state 799, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 801, "(1)" + line 387, "pan.___", state 802, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 802, "else" + line 387, "pan.___", state 805, "(1)" + line 391, "pan.___", state 813, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 815, "(1)" + line 391, "pan.___", state 816, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 816, "else" + line 391, "pan.___", state 819, "(1)" + line 391, "pan.___", state 820, "(1)" + line 391, "pan.___", state 820, "(1)" + line 389, "pan.___", state 825, "((i<1))" + line 389, "pan.___", state 825, "((i>=1))" + line 396, "pan.___", state 831, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 833, "(1)" + line 396, "pan.___", state 834, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 834, "else" + line 396, "pan.___", state 837, "(1)" + line 396, "pan.___", state 838, "(1)" + line 396, "pan.___", state 838, "(1)" + line 400, "pan.___", state 845, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 847, "(1)" + line 400, "pan.___", state 848, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 848, "else" + line 400, "pan.___", state 851, "(1)" + line 400, "pan.___", state 852, "(1)" + line 400, "pan.___", state 852, "(1)" + line 398, "pan.___", state 857, "((i<2))" + line 398, "pan.___", state 857, "((i>=2))" + line 404, "pan.___", state 864, "(1)" + line 404, "pan.___", state 865, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 865, "else" + line 404, "pan.___", state 868, "(1)" + line 404, "pan.___", state 869, "(1)" + line 404, "pan.___", state 869, "(1)" + line 408, "pan.___", state 877, "(1)" + line 408, "pan.___", state 878, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 878, "else" + line 408, "pan.___", state 881, "(1)" + line 408, "pan.___", state 882, "(1)" + line 408, "pan.___", state 882, "(1)" + line 406, "pan.___", state 887, "((i<1))" + line 406, "pan.___", state 887, "((i>=1))" + line 413, "pan.___", state 894, "(1)" + line 413, "pan.___", state 895, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 895, "else" + line 413, "pan.___", state 898, "(1)" + line 413, "pan.___", state 899, "(1)" + line 413, "pan.___", state 899, "(1)" + line 417, "pan.___", state 907, "(1)" + line 417, "pan.___", state 908, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 908, "else" + line 417, "pan.___", state 911, "(1)" + line 417, "pan.___", state 912, "(1)" + line 417, "pan.___", state 912, "(1)" + line 422, "pan.___", state 921, "(1)" + line 422, "pan.___", state 921, "(1)" + line 387, "pan.___", state 928, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 930, "(1)" + line 387, "pan.___", state 931, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 931, "else" + line 387, "pan.___", state 934, "(1)" + line 391, "pan.___", state 942, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 944, "(1)" + line 391, "pan.___", state 945, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 945, "else" + line 391, "pan.___", state 948, "(1)" + line 391, "pan.___", state 949, "(1)" + line 391, "pan.___", state 949, "(1)" + line 389, "pan.___", state 954, "((i<1))" + line 389, "pan.___", state 954, "((i>=1))" + line 396, "pan.___", state 960, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 962, "(1)" + line 396, "pan.___", state 963, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 963, "else" + line 396, "pan.___", state 966, "(1)" + line 396, "pan.___", state 967, "(1)" + line 396, "pan.___", state 967, "(1)" + line 400, "pan.___", state 974, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 976, "(1)" + line 400, "pan.___", state 977, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 977, "else" + line 400, "pan.___", state 980, "(1)" + line 400, "pan.___", state 981, "(1)" + line 400, "pan.___", state 981, "(1)" + line 398, "pan.___", state 986, "((i<2))" + line 398, "pan.___", state 986, "((i>=2))" + line 404, "pan.___", state 993, "(1)" + line 404, "pan.___", state 994, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 994, "else" + line 404, "pan.___", state 997, "(1)" + line 404, "pan.___", state 998, "(1)" + line 404, "pan.___", state 998, "(1)" + line 408, "pan.___", state 1006, "(1)" + line 408, "pan.___", state 1007, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 1007, "else" + line 408, "pan.___", state 1010, "(1)" + line 408, "pan.___", state 1011, "(1)" + line 408, "pan.___", state 1011, "(1)" + line 406, "pan.___", state 1016, "((i<1))" + line 406, "pan.___", state 1016, "((i>=1))" + line 413, "pan.___", state 1023, "(1)" + line 413, "pan.___", state 1024, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 1024, "else" + line 413, "pan.___", state 1027, "(1)" + line 413, "pan.___", state 1028, "(1)" + line 413, "pan.___", state 1028, "(1)" + line 417, "pan.___", state 1036, "(1)" + line 417, "pan.___", state 1037, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 1037, "else" + line 417, "pan.___", state 1040, "(1)" + line 417, "pan.___", state 1041, "(1)" + line 417, "pan.___", state 1041, "(1)" + line 415, "pan.___", state 1046, "((i<2))" + line 415, "pan.___", state 1046, "((i>=2))" + line 422, "pan.___", state 1050, "(1)" + line 422, "pan.___", state 1050, "(1)" + line 671, "pan.___", state 1054, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 387, "pan.___", state 1059, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1091, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1105, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1124, "(1)" + line 413, "pan.___", state 1154, "(1)" + line 417, "pan.___", state 1167, "(1)" + line 387, "pan.___", state 1191, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1223, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1237, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1256, "(1)" + line 413, "pan.___", state 1286, "(1)" + line 417, "pan.___", state 1299, "(1)" + line 387, "pan.___", state 1324, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1356, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1370, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1389, "(1)" + line 413, "pan.___", state 1419, "(1)" + line 417, "pan.___", state 1432, "(1)" + line 387, "pan.___", state 1453, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1485, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1499, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1518, "(1)" + line 413, "pan.___", state 1548, "(1)" + line 417, "pan.___", state 1561, "(1)" + line 387, "pan.___", state 1587, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1619, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1633, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1652, "(1)" + line 413, "pan.___", state 1682, "(1)" + line 417, "pan.___", state 1695, "(1)" + line 387, "pan.___", state 1716, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1748, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1762, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1781, "(1)" + line 413, "pan.___", state 1811, "(1)" + line 417, "pan.___", state 1824, "(1)" + line 387, "pan.___", state 1848, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 1880, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1894, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1913, "(1)" + line 413, "pan.___", state 1943, "(1)" + line 417, "pan.___", state 1956, "(1)" + line 710, "pan.___", state 1977, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 387, "pan.___", state 1984, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2016, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2030, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2049, "(1)" + line 413, "pan.___", state 2079, "(1)" + line 417, "pan.___", state 2092, "(1)" + line 387, "pan.___", state 2113, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2145, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2159, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2178, "(1)" + line 413, "pan.___", state 2208, "(1)" + line 417, "pan.___", state 2221, "(1)" + line 387, "pan.___", state 2244, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 2246, "(1)" + line 387, "pan.___", state 2247, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 387, "pan.___", state 2247, "else" + line 387, "pan.___", state 2250, "(1)" + line 391, "pan.___", state 2258, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 2260, "(1)" + line 391, "pan.___", state 2261, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 391, "pan.___", state 2261, "else" + line 391, "pan.___", state 2264, "(1)" + line 391, "pan.___", state 2265, "(1)" + line 391, "pan.___", state 2265, "(1)" + line 389, "pan.___", state 2270, "((i<1))" + line 389, "pan.___", state 2270, "((i>=1))" + line 396, "pan.___", state 2276, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2278, "(1)" + line 396, "pan.___", state 2279, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 2279, "else" + line 396, "pan.___", state 2282, "(1)" + line 396, "pan.___", state 2283, "(1)" + line 396, "pan.___", state 2283, "(1)" + line 400, "pan.___", state 2290, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2292, "(1)" + line 400, "pan.___", state 2293, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 400, "pan.___", state 2293, "else" + line 400, "pan.___", state 2296, "(1)" + line 400, "pan.___", state 2297, "(1)" + line 400, "pan.___", state 2297, "(1)" + line 398, "pan.___", state 2302, "((i<2))" + line 398, "pan.___", state 2302, "((i>=2))" + line 404, "pan.___", state 2309, "(1)" + line 404, "pan.___", state 2310, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 2310, "else" + line 404, "pan.___", state 2313, "(1)" + line 404, "pan.___", state 2314, "(1)" + line 404, "pan.___", state 2314, "(1)" + line 408, "pan.___", state 2322, "(1)" + line 408, "pan.___", state 2323, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 2323, "else" + line 408, "pan.___", state 2326, "(1)" + line 408, "pan.___", state 2327, "(1)" + line 408, "pan.___", state 2327, "(1)" + line 406, "pan.___", state 2332, "((i<1))" + line 406, "pan.___", state 2332, "((i>=1))" + line 413, "pan.___", state 2339, "(1)" + line 413, "pan.___", state 2340, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 2340, "else" + line 413, "pan.___", state 2343, "(1)" + line 413, "pan.___", state 2344, "(1)" + line 413, "pan.___", state 2344, "(1)" + line 417, "pan.___", state 2352, "(1)" + line 417, "pan.___", state 2353, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 2353, "else" + line 417, "pan.___", state 2356, "(1)" + line 417, "pan.___", state 2357, "(1)" + line 417, "pan.___", state 2357, "(1)" + line 415, "pan.___", state 2362, "((i<2))" + line 415, "pan.___", state 2362, "((i>=2))" + line 422, "pan.___", state 2366, "(1)" + line 422, "pan.___", state 2366, "(1)" + line 710, "pan.___", state 2369, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 710, "pan.___", state 2370, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 710, "pan.___", state 2371, "(1)" + line 387, "pan.___", state 2378, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2410, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2424, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2443, "(1)" + line 413, "pan.___", state 2473, "(1)" + line 417, "pan.___", state 2486, "(1)" + line 387, "pan.___", state 2513, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2545, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2559, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2578, "(1)" + line 413, "pan.___", state 2608, "(1)" + line 417, "pan.___", state 2621, "(1)" + line 387, "pan.___", state 2642, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2674, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2688, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2707, "(1)" + line 413, "pan.___", state 2737, "(1)" + line 417, "pan.___", state 2750, "(1)" + line 227, "pan.___", state 2783, "(1)" + line 235, "pan.___", state 2803, "(1)" + line 239, "pan.___", state 2811, "(1)" + line 227, "pan.___", state 2826, "(1)" + line 235, "pan.___", state 2846, "(1)" + line 239, "pan.___", state 2854, "(1)" + line 870, "pan.___", state 2871, "-end-" + (279 of 2871 states) +unreached in proctype urcu_writer + line 387, "pan.___", state 18, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 387, "pan.___", state 24, "(1)" + line 391, "pan.___", state 32, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 38, "(1)" + line 391, "pan.___", state 39, "(1)" + line 391, "pan.___", state 39, "(1)" + line 389, "pan.___", state 44, "((i<1))" + line 389, "pan.___", state 44, "((i>=1))" + line 396, "pan.___", state 50, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 56, "(1)" + line 396, "pan.___", state 57, "(1)" + line 396, "pan.___", state 57, "(1)" + line 400, "pan.___", state 64, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 400, "pan.___", state 70, "(1)" + line 400, "pan.___", state 71, "(1)" + line 400, "pan.___", state 71, "(1)" + line 398, "pan.___", state 76, "((i<2))" + line 398, "pan.___", state 76, "((i>=2))" + line 404, "pan.___", state 83, "(1)" + line 404, "pan.___", state 84, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 404, "pan.___", state 84, "else" + line 404, "pan.___", state 87, "(1)" + line 404, "pan.___", state 88, "(1)" + line 404, "pan.___", state 88, "(1)" + line 408, "pan.___", state 96, "(1)" + line 408, "pan.___", state 97, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 408, "pan.___", state 97, "else" + line 408, "pan.___", state 100, "(1)" + line 408, "pan.___", state 101, "(1)" + line 408, "pan.___", state 101, "(1)" + line 406, "pan.___", state 106, "((i<1))" + line 406, "pan.___", state 106, "((i>=1))" + line 413, "pan.___", state 113, "(1)" + line 413, "pan.___", state 114, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 114, "else" + line 413, "pan.___", state 117, "(1)" + line 413, "pan.___", state 118, "(1)" + line 413, "pan.___", state 118, "(1)" + line 417, "pan.___", state 126, "(1)" + line 417, "pan.___", state 127, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 417, "pan.___", state 127, "else" + line 417, "pan.___", state 130, "(1)" + line 417, "pan.___", state 131, "(1)" + line 417, "pan.___", state 131, "(1)" + line 415, "pan.___", state 136, "((i<2))" + line 415, "pan.___", state 136, "((i>=2))" + line 422, "pan.___", state 140, "(1)" + line 422, "pan.___", state 140, "(1)" + line 250, "pan.___", state 149, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 158, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 252, "pan.___", state 166, "((i<1))" + line 252, "pan.___", state 166, "((i>=1))" + line 258, "pan.___", state 171, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 993, "pan.___", state 199, "old_data = cached_rcu_ptr.val[_pid]" + line 387, "pan.___", state 211, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 391, "pan.___", state 225, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 243, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 257, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 404, "pan.___", state 276, "(1)" + line 408, "pan.___", state 289, "(1)" + line 413, "pan.___", state 306, "(1)" + line 417, "pan.___", state 319, "(1)" + line 391, "pan.___", state 356, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 374, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 388, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 420, "(1)" + line 413, "pan.___", state 437, "(1)" + line 417, "pan.___", state 450, "(1)" + line 391, "pan.___", state 494, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 512, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 526, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 558, "(1)" + line 413, "pan.___", state 575, "(1)" + line 417, "pan.___", state 588, "(1)" + line 391, "pan.___", state 623, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 641, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 655, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 687, "(1)" + line 413, "pan.___", state 704, "(1)" + line 417, "pan.___", state 717, "(1)" + line 391, "pan.___", state 754, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 772, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 786, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 818, "(1)" + line 413, "pan.___", state 835, "(1)" + line 417, "pan.___", state 848, "(1)" + line 1113, "pan.___", state 872, "_proc_urcu_writer = (_proc_urcu_writer&~(((1<<12)|(1<<11))))" + line 250, "pan.___", state 903, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 912, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 252, "pan.___", state 920, "((i<1))" + line 252, "pan.___", state 920, "((i>=1))" + line 258, "pan.___", state 927, "(1)" + line 258, "pan.___", state 928, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 928, "else" + line 262, "pan.___", state 934, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 260, "pan.___", state 942, "((i<2))" + line 260, "pan.___", state 942, "((i>=2))" + line 227, "pan.___", state 950, "(1)" + line 231, "pan.___", state 958, "(1)" + line 231, "pan.___", state 959, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 959, "else" + line 229, "pan.___", state 964, "((i<1))" + line 229, "pan.___", state 964, "((i>=1))" + line 235, "pan.___", state 970, "(1)" + line 235, "pan.___", state 971, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 971, "else" + line 239, "pan.___", state 978, "(1)" + line 239, "pan.___", state 979, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 979, "else" + line 244, "pan.___", state 988, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 988, "else" + line 250, "pan.___", state 1009, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1018, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1031, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1040, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1056, "(1)" + line 231, "pan.___", state 1064, "(1)" + line 235, "pan.___", state 1076, "(1)" + line 239, "pan.___", state 1084, "(1)" + line 250, "pan.___", state 1101, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1110, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 252, "pan.___", state 1118, "((i<1))" + line 252, "pan.___", state 1118, "((i>=1))" + line 258, "pan.___", state 1123, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1132, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 260, "pan.___", state 1140, "((i<2))" + line 260, "pan.___", state 1140, "((i>=2))" + line 227, "pan.___", state 1148, "(1)" + line 231, "pan.___", state 1156, "(1)" + line 231, "pan.___", state 1157, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1157, "else" + line 229, "pan.___", state 1162, "((i<1))" + line 229, "pan.___", state 1162, "((i>=1))" + line 235, "pan.___", state 1168, "(1)" + line 235, "pan.___", state 1169, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1169, "else" + line 239, "pan.___", state 1176, "(1)" + line 239, "pan.___", state 1177, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1177, "else" + line 244, "pan.___", state 1186, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1186, "else" + line 1180, "pan.___", state 1189, "i = 0" + line 1180, "pan.___", state 1191, "reader_barrier = 1" + line 1180, "pan.___", state 1202, "((i<1))" + line 1180, "pan.___", state 1202, "((i>=1))" + line 250, "pan.___", state 1207, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1216, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 252, "pan.___", state 1224, "((i<1))" + line 252, "pan.___", state 1224, "((i>=1))" + line 258, "pan.___", state 1229, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1238, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 260, "pan.___", state 1246, "((i<2))" + line 260, "pan.___", state 1246, "((i>=2))" + line 227, "pan.___", state 1254, "(1)" + line 231, "pan.___", state 1262, "(1)" + line 231, "pan.___", state 1263, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1263, "else" + line 229, "pan.___", state 1268, "((i<1))" + line 229, "pan.___", state 1268, "((i>=1))" + line 235, "pan.___", state 1274, "(1)" + line 235, "pan.___", state 1275, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1275, "else" + line 239, "pan.___", state 1282, "(1)" + line 239, "pan.___", state 1283, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1283, "else" + line 244, "pan.___", state 1292, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1292, "else" + line 250, "pan.___", state 1299, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1301, "(1)" + line 254, "pan.___", state 1308, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1310, "(1)" + line 254, "pan.___", state 1311, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1311, "else" + line 252, "pan.___", state 1316, "((i<1))" + line 252, "pan.___", state 1316, "((i>=1))" + line 258, "pan.___", state 1321, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1323, "(1)" + line 258, "pan.___", state 1324, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1324, "else" + line 262, "pan.___", state 1330, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1332, "(1)" + line 262, "pan.___", state 1333, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1333, "else" + line 260, "pan.___", state 1338, "((i<2))" + line 260, "pan.___", state 1338, "((i>=2))" + line 227, "pan.___", state 1346, "(1)" + line 231, "pan.___", state 1354, "(1)" + line 231, "pan.___", state 1355, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1355, "else" + line 229, "pan.___", state 1360, "((i<1))" + line 229, "pan.___", state 1360, "((i>=1))" + line 235, "pan.___", state 1366, "(1)" + line 235, "pan.___", state 1367, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1367, "else" + line 239, "pan.___", state 1374, "(1)" + line 239, "pan.___", state 1375, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1375, "else" + line 244, "pan.___", state 1384, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1384, "else" + line 1183, "pan.___", state 1387, "i = 0" + line 1183, "pan.___", state 1389, "reader_barrier = 1" + line 1183, "pan.___", state 1400, "((i<1))" + line 1183, "pan.___", state 1400, "((i>=1))" + line 250, "pan.___", state 1405, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1407, "(1)" + line 254, "pan.___", state 1414, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1416, "(1)" + line 254, "pan.___", state 1417, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1417, "else" + line 252, "pan.___", state 1422, "((i<1))" + line 252, "pan.___", state 1422, "((i>=1))" + line 258, "pan.___", state 1427, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1429, "(1)" + line 258, "pan.___", state 1430, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1430, "else" + line 262, "pan.___", state 1436, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1438, "(1)" + line 262, "pan.___", state 1439, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1439, "else" + line 260, "pan.___", state 1444, "((i<2))" + line 260, "pan.___", state 1444, "((i>=2))" + line 227, "pan.___", state 1452, "(1)" + line 231, "pan.___", state 1460, "(1)" + line 231, "pan.___", state 1461, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1461, "else" + line 229, "pan.___", state 1466, "((i<1))" + line 229, "pan.___", state 1466, "((i>=1))" + line 235, "pan.___", state 1472, "(1)" + line 235, "pan.___", state 1473, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1473, "else" + line 239, "pan.___", state 1480, "(1)" + line 239, "pan.___", state 1481, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1481, "else" + line 244, "pan.___", state 1490, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1490, "else" + line 277, "pan.___", state 1492, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 1492, "else" + line 1183, "pan.___", state 1493, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 1183, "pan.___", state 1493, "else" + line 254, "pan.___", state 1506, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1519, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1528, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1544, "(1)" + line 231, "pan.___", state 1552, "(1)" + line 235, "pan.___", state 1564, "(1)" + line 239, "pan.___", state 1572, "(1)" + line 250, "pan.___", state 1603, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1612, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1625, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1634, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1650, "(1)" + line 231, "pan.___", state 1658, "(1)" + line 235, "pan.___", state 1670, "(1)" + line 239, "pan.___", state 1678, "(1)" + line 1191, "pan.___", state 1694, "-end-" + (192 of 1694 states) +unreached in proctype :init: + (0 of 78 states) +unreached in proctype :never: + line 1252, "pan.___", state 11, "-end-" + (1 of 11 states) + +pan: elapsed time 13.7 seconds +pan: rate 4094.3672 states/second +pan: avg transition delay 1.3041e-06 usec +cp .input.spin urcu_progress_writer.spin.input +cp .input.spin.trail urcu_progress_writer.spin.input.trail +make[1]: Leaving directory `/home/compudj/doc/userspace-rcu/formal-model/urcu-controldataflow' diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer.spin.input b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer.spin.input new file mode 100644 index 0000000..f1dd6fb --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer.spin.input @@ -0,0 +1,1227 @@ +#define WRITER_PROGRESS + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* We choose to ignore writer's non-progress caused from the + * reader ignoring the writer's mb() requests */ +#ifdef WRITER_PROGRESS +progress_writer_from_reader: +#endif + break; + od; +} + +#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: +#define PROGRESS_LABEL(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; \ + /* \ + * 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) \ + do \ + :: (reader_barrier[i] == 1) -> skip; \ + :: (reader_barrier[i] == 0) -> break; \ + od; \ + i++; \ + :: i >= NR_READERS -> \ + break \ + od; \ + smp_mb(i, j); \ +} + +#else + +#define smp_mb_send(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + :: 1 -> skip; + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer.spin.input.trail b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer.spin.input.trail new file mode 100644 index 0000000..e8b02f0 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer.spin.input.trail @@ -0,0 +1,884 @@ +-2:3:-2 +-4:-4:-4 +1:0:4645 +2:3:4565 +3:3:4568 +4:3:4568 +5:3:4571 +6:3:4579 +7:3:4579 +8:3:4582 +9:3:4588 +10:3:4592 +11:3:4592 +12:3:4595 +13:3:4605 +14:3:4613 +15:3:4613 +16:3:4616 +17:3:4622 +18:3:4626 +19:3:4626 +20:3:4629 +21:3:4635 +22:3:4639 +23:3:4640 +24:0:4645 +25:3:4642 +26:0:4645 +27:2:2873 +28:0:4645 +29:2:2879 +30:0:4645 +31:2:2880 +32:0:4645 +33:2:2881 +34:0:4643 +35:2:2882 +36:0:4649 +37:2:2883 +38:0:4649 +39:2:2884 +40:2:2885 +41:2:2889 +42:2:2890 +43:2:2898 +44:2:2899 +45:2:2903 +46:2:2904 +47:2:2912 +48:2:2917 +49:2:2921 +50:2:2922 +51:2:2930 +52:2:2931 +53:2:2935 +54:2:2936 +55:2:2930 +56:2:2931 +57:2:2935 +58:2:2936 +59:2:2944 +60:2:2949 +61:2:2950 +62:2:2961 +63:2:2962 +64:2:2963 +65:2:2974 +66:2:2979 +67:2:2980 +68:2:2991 +69:2:2992 +70:2:2993 +71:2:2991 +72:2:2992 +73:2:2993 +74:2:3004 +75:2:3012 +76:0:4649 +77:2:2883 +78:0:4649 +79:2:3016 +80:2:3020 +81:2:3021 +82:2:3025 +83:2:3029 +84:2:3030 +85:2:3034 +86:2:3042 +87:2:3043 +88:2:3047 +89:2:3051 +90:2:3052 +91:2:3047 +92:2:3048 +93:2:3056 +94:0:4649 +95:2:2883 +96:0:4649 +97:2:3064 +98:2:3065 +99:2:3066 +100:0:4649 +101:2:2883 +102:0:4649 +103:2:3071 +104:0:4649 +105:2:3774 +106:2:3775 +107:2:3779 +108:2:3783 +109:2:3784 +110:2:3788 +111:2:3793 +112:2:3801 +113:2:3805 +114:2:3806 +115:2:3801 +116:2:3805 +117:2:3806 +118:2:3810 +119:2:3817 +120:2:3824 +121:2:3825 +122:2:3832 +123:2:3837 +124:2:3844 +125:2:3845 +126:2:3844 +127:2:3845 +128:2:3852 +129:2:3856 +130:0:4649 +131:2:3861 +132:0:4649 +133:2:3862 +134:0:4649 +135:2:3863 +136:0:4649 +137:2:3864 +138:0:4649 +139:1:2 +140:0:4649 +141:2:3865 +142:0:4649 +143:1:8 +144:0:4649 +145:1:9 +146:0:4649 +147:2:3864 +148:0:4649 +149:2:3865 +150:0:4649 +151:1:10 +152:0:4649 +153:2:3864 +154:0:4649 +155:2:3865 +156:0:4649 +157:1:11 +158:0:4649 +159:2:3864 +160:0:4649 +161:2:3865 +162:0:4649 +163:1:12 +164:0:4649 +165:2:3864 +166:0:4649 +167:2:3865 +168:0:4649 +169:1:13 +170:0:4649 +171:2:3864 +172:0:4649 +173:2:3865 +174:0:4649 +175:1:14 +176:0:4649 +177:1:15 +178:0:4649 +179:1:23 +180:0:4649 +181:1:24 +182:0:4649 +183:2:3864 +184:0:4649 +185:2:3865 +186:0:4649 +187:1:128 +188:1:129 +189:1:133 +190:1:134 +191:1:142 +192:1:143 +193:1:147 +194:1:148 +195:1:156 +196:1:161 +197:1:165 +198:1:166 +199:1:174 +200:1:175 +201:1:179 +202:1:180 +203:1:174 +204:1:175 +205:1:179 +206:1:180 +207:1:188 +208:1:193 +209:1:194 +210:1:205 +211:1:206 +212:1:207 +213:1:218 +214:1:223 +215:1:224 +216:1:235 +217:1:236 +218:1:237 +219:1:235 +220:1:236 +221:1:237 +222:1:248 +223:0:4649 +224:1:15 +225:0:4649 +226:1:23 +227:0:4649 +228:1:24 +229:0:4649 +230:2:3864 +231:0:4649 +232:2:3865 +233:0:4649 +234:1:257 +235:1:258 +236:0:4649 +237:1:15 +238:0:4649 +239:1:23 +240:0:4649 +241:1:24 +242:0:4649 +243:2:3864 +244:0:4649 +245:2:3865 +246:0:4649 +247:1:264 +248:1:265 +249:1:269 +250:1:270 +251:1:278 +252:1:279 +253:1:283 +254:1:284 +255:1:292 +256:1:297 +257:1:301 +258:1:302 +259:1:310 +260:1:311 +261:1:315 +262:1:316 +263:1:310 +264:1:311 +265:1:315 +266:1:316 +267:1:324 +268:1:329 +269:1:330 +270:1:341 +271:1:342 +272:1:343 +273:1:354 +274:1:359 +275:1:360 +276:1:371 +277:1:372 +278:1:373 +279:1:371 +280:1:372 +281:1:373 +282:1:384 +283:0:4649 +284:1:15 +285:0:4649 +286:1:23 +287:0:4649 +288:1:24 +289:0:4649 +290:2:3864 +291:0:4649 +292:2:3865 +293:0:4649 +294:1:393 +295:1:394 +296:1:398 +297:1:399 +298:1:407 +299:1:408 +300:1:412 +301:1:413 +302:1:421 +303:1:426 +304:1:430 +305:1:431 +306:1:439 +307:1:440 +308:1:444 +309:1:445 +310:1:439 +311:1:440 +312:1:444 +313:1:445 +314:1:453 +315:1:458 +316:1:459 +317:1:470 +318:1:471 +319:1:472 +320:1:483 +321:1:488 +322:1:489 +323:1:500 +324:1:501 +325:1:502 +326:1:500 +327:1:501 +328:1:502 +329:1:513 +330:1:520 +331:0:4649 +332:1:15 +333:0:4649 +334:1:16 +335:0:4649 +336:2:3864 +337:0:4649 +338:2:3865 +339:0:4649 +340:1:17 +341:0:4649 +342:2:3864 +343:0:4649 +344:2:3865 +345:0:4649 +346:1:28 +347:0:4649 +348:2:3864 +349:0:4649 +350:2:3865 +351:0:4649 +352:1:32 +353:1:33 +354:1:37 +355:1:38 +356:1:46 +357:1:54 +358:1:55 +359:1:59 +360:1:63 +361:1:64 +362:1:59 +363:1:63 +364:1:64 +365:1:68 +366:1:75 +367:1:82 +368:1:83 +369:1:90 +370:1:95 +371:1:102 +372:1:103 +373:1:102 +374:1:103 +375:1:110 +376:1:114 +377:0:4649 +378:2:3864 +379:0:4649 +380:2:3865 +381:0:4649 +382:1:119 +383:0:4649 +384:2:3866 +385:0:4649 +386:2:3871 +387:0:4649 +388:2:3872 +389:0:4649 +390:2:3880 +391:2:3881 +392:2:3885 +393:2:3889 +394:2:3890 +395:2:3894 +396:2:3902 +397:2:3903 +398:2:3907 +399:2:3911 +400:2:3912 +401:2:3907 +402:2:3911 +403:2:3912 +404:2:3916 +405:2:3923 +406:2:3930 +407:2:3931 +408:2:3938 +409:2:3943 +410:2:3950 +411:2:3951 +412:2:3950 +413:2:3951 +414:2:3958 +415:2:3962 +416:0:4649 +417:2:3073 +418:2:3755 +419:0:4649 +420:2:2883 +421:0:4649 +422:2:3074 +423:0:4649 +424:2:2883 +425:0:4649 +426:2:3077 +427:2:3078 +428:2:3082 +429:2:3083 +430:2:3091 +431:2:3092 +432:2:3096 +433:2:3097 +434:2:3105 +435:2:3110 +436:2:3114 +437:2:3115 +438:2:3123 +439:2:3124 +440:2:3128 +441:2:3129 +442:2:3123 +443:2:3124 +444:2:3128 +445:2:3129 +446:2:3137 +447:2:3142 +448:2:3143 +449:2:3154 +450:2:3155 +451:2:3156 +452:2:3167 +453:2:3172 +454:2:3173 +455:2:3184 +456:2:3185 +457:2:3186 +458:2:3184 +459:2:3185 +460:2:3186 +461:2:3197 +462:2:3204 +463:0:4649 +464:2:2883 +465:0:4649 +466:2:3208 +467:2:3209 +468:2:3210 +469:2:3222 +470:2:3223 +471:2:3227 +472:2:3228 +473:2:3236 +474:2:3241 +475:2:3245 +476:2:3246 +477:2:3254 +478:2:3255 +479:2:3259 +480:2:3260 +481:2:3254 +482:2:3255 +483:2:3259 +484:2:3260 +485:2:3268 +486:2:3273 +487:2:3274 +488:2:3285 +489:2:3286 +490:2:3287 +491:2:3298 +492:2:3303 +493:2:3304 +494:2:3315 +495:2:3316 +496:2:3317 +497:2:3315 +498:2:3316 +499:2:3317 +500:2:3328 +501:2:3337 +502:0:4649 +503:2:2883 +504:0:4649 +505:2:3343 +506:0:4649 +507:2:3972 +508:2:3973 +509:2:3977 +510:2:3981 +511:2:3982 +512:2:3986 +513:2:3994 +514:2:3995 +515:2:3999 +516:2:4003 +517:2:4004 +518:2:3999 +519:2:4003 +520:2:4004 +521:2:4008 +522:2:4015 +523:2:4022 +524:2:4023 +525:2:4030 +526:2:4035 +527:2:4042 +528:2:4043 +529:2:4042 +530:2:4043 +531:2:4050 +532:2:4054 +533:0:4649 +534:2:4059 +535:0:4649 +536:2:4060 +537:0:4649 +538:2:4061 +539:0:4649 +540:2:4062 +541:0:4649 +542:1:28 +543:0:4649 +544:2:4063 +545:0:4649 +546:2:4062 +547:0:4649 +548:1:32 +549:1:33 +550:1:37 +551:1:41 +552:1:42 +553:1:46 +554:1:54 +555:1:55 +556:1:59 +557:1:63 +558:1:64 +559:1:59 +560:1:63 +561:1:64 +562:1:68 +563:1:75 +564:1:82 +565:1:83 +566:1:90 +567:1:95 +568:1:102 +569:1:103 +570:1:102 +571:1:103 +572:1:110 +573:1:114 +-1:-1:-1 +574:0:4649 +575:2:4063 +576:0:4649 +577:2:4062 +578:0:4649 +579:1:119 +580:0:4649 +581:2:4063 +582:0:4649 +583:2:4064 +584:0:4649 +585:2:4069 +586:0:4649 +587:2:4070 +588:0:4649 +589:2:4078 +590:2:4079 +591:2:4083 +592:2:4087 +593:2:4088 +594:2:4092 +595:2:4100 +596:2:4101 +597:2:4105 +598:2:4109 +599:2:4110 +600:2:4105 +601:2:4109 +602:2:4110 +603:2:4114 +604:2:4121 +605:2:4128 +606:2:4129 +607:2:4136 +608:2:4141 +609:2:4148 +610:2:4149 +611:2:4148 +612:2:4149 +613:2:4156 +614:2:4160 +615:0:4649 +616:2:3345 +617:2:3755 +618:0:4649 +619:2:2883 +620:0:4649 +621:2:3208 +622:2:3209 +623:2:3213 +624:2:3214 +625:2:3222 +626:2:3223 +627:2:3227 +628:2:3228 +629:2:3236 +630:2:3241 +631:2:3245 +632:2:3246 +633:2:3254 +634:2:3255 +635:2:3259 +636:2:3260 +637:2:3254 +638:2:3255 +639:2:3259 +640:2:3260 +641:2:3268 +642:2:3273 +643:2:3274 +644:2:3285 +645:2:3286 +646:2:3287 +647:2:3298 +648:2:3303 +649:2:3304 +650:2:3315 +651:2:3316 +652:2:3317 +653:2:3315 +654:2:3316 +655:2:3317 +656:2:3328 +657:2:3337 +658:0:4649 +659:2:2883 +660:0:4649 +661:2:3343 +662:0:4649 +663:2:3972 +664:2:3973 +665:2:3977 +666:2:3981 +667:2:3982 +668:2:3986 +669:2:3994 +670:2:3995 +671:2:3999 +672:2:4003 +673:2:4004 +674:2:3999 +675:2:4003 +676:2:4004 +677:2:4008 +678:2:4015 +679:2:4022 +680:2:4023 +681:2:4030 +682:2:4035 +683:2:4042 +684:2:4043 +685:2:4042 +686:2:4043 +687:2:4050 +688:2:4054 +689:0:4649 +690:2:4059 +691:0:4649 +692:2:4060 +693:0:4649 +694:2:4061 +695:0:4649 +696:2:4062 +697:0:4649 +698:1:28 +699:0:4649 +700:2:4063 +701:0:4649 +702:1:32 +703:1:33 +704:1:37 +705:1:41 +706:1:42 +707:1:46 +708:1:54 +709:1:55 +710:1:59 +711:1:63 +712:1:64 +713:1:59 +714:1:63 +715:1:64 +716:1:68 +717:1:75 +718:1:82 +719:1:83 +720:1:90 +721:1:95 +722:1:102 +723:1:103 +724:1:102 +725:1:103 +726:1:110 +727:1:114 +728:0:4649 +729:2:4062 +730:0:4649 +731:2:4063 +732:0:4649 +733:1:119 +734:0:4649 +735:2:4064 +736:0:4649 +737:2:4069 +738:0:4649 +739:2:4070 +740:0:4649 +741:2:4078 +742:2:4079 +743:2:4083 +744:2:4087 +745:2:4088 +746:2:4092 +747:2:4100 +748:2:4101 +749:2:4105 +750:2:4109 +751:2:4110 +752:2:4105 +753:2:4109 +754:2:4110 +755:2:4114 +756:2:4121 +757:2:4128 +758:2:4129 +759:2:4136 +760:2:4141 +761:2:4148 +762:2:4149 +763:2:4148 +764:2:4149 +765:2:4156 +766:2:4160 +767:0:4649 +768:2:3345 +769:2:3755 +770:0:4649 +771:2:2883 +772:0:4649 +773:2:3208 +774:2:3209 +775:2:3213 +776:2:3214 +777:2:3222 +778:2:3223 +779:2:3227 +780:2:3228 +781:2:3236 +782:2:3241 +783:2:3245 +784:2:3246 +785:2:3254 +786:2:3255 +787:2:3259 +788:2:3260 +789:2:3254 +790:2:3255 +791:2:3259 +792:2:3260 +793:2:3268 +794:2:3273 +795:2:3274 +796:2:3285 +797:2:3286 +798:2:3287 +799:2:3298 +800:2:3303 +801:2:3304 +802:2:3315 +803:2:3316 +804:2:3317 +805:2:3315 +806:2:3316 +807:2:3317 +808:2:3328 +809:2:3337 +810:0:4649 +811:2:2883 +812:0:4649 +813:2:3343 +814:0:4649 +815:2:3972 +816:2:3973 +817:2:3977 +818:2:3981 +819:2:3982 +820:2:3986 +821:2:3994 +822:2:3995 +823:2:3999 +824:2:4003 +825:2:4004 +826:2:3999 +827:2:4003 +828:2:4004 +829:2:4008 +830:2:4015 +831:2:4022 +832:2:4023 +833:2:4030 +834:2:4035 +835:2:4042 +836:2:4043 +837:2:4042 +838:2:4043 +839:2:4050 +840:2:4054 +841:0:4649 +842:2:4059 +843:0:4649 +844:2:4060 +845:0:4649 +846:2:4061 +847:0:4649 +848:2:4062 +849:0:4649 +850:1:28 +851:0:4649 +852:2:4063 +853:0:4649 +854:2:4062 +855:0:4649 +856:1:32 +857:1:33 +858:1:37 +859:1:41 +860:1:42 +861:1:46 +862:1:54 +863:1:55 +864:1:59 +865:1:63 +866:1:64 +867:1:59 +868:1:63 +869:1:64 +870:1:68 +871:1:75 +872:1:82 +873:1:83 +874:1:90 +875:1:95 +876:1:102 +877:1:103 +878:1:102 +879:1:103 +880:1:110 +881:1:114 diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer_error.define b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer_error.define new file mode 100644 index 0000000..8d304f5 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer_error.define @@ -0,0 +1,2 @@ +#define WRITER_PROGRESS +#define GEN_ERROR_WRITER_PROGRESS diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer_error.log b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer_error.log new file mode 100644 index 0000000..d6f24ba --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer_error.log @@ -0,0 +1,620 @@ +make[1]: Entering directory `/home/compudj/doc/userspace-rcu/formal-model/urcu-controldataflow' +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define > pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_progress.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_progress_writer_error.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -f -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1246) +depth 23: Claim reached state 9 (line 1251) +depth 51: Claim reached state 9 (line 1250) +pan: acceptance cycle (at depth 1200) +pan: wrote .input.spin.trail + +(Spin Version 5.1.7 -- 23 December 2008) +Warning: Search not completed + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness enabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 3997, errors: 1 + 26291 states, stored (59381 visited) + 11000989 states, matched + 11060370 transitions (= visited+matched) + 60052117 atomic steps +hash conflicts: 84608 (resolved) + +Stats on memory usage (in Megabytes): + 2.908 equivalent memory usage for states (stored*(State-vector + overhead)) + 2.889 actual memory usage for states (compression: 99.33%) + state-vector as stored = 87 byte + 28 byte overhead + 8.000 memory used for hash table (-w20) + 457.764 memory used for DFS stack (-m10000000) + 468.596 total actual memory usage + +unreached in proctype urcu_reader + line 648, "pan.___", state 20, "(1)" + line 251, "pan.___", state 32, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 259, "pan.___", state 54, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 263, "pan.___", state 63, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 228, "pan.___", state 79, "(1)" + line 232, "pan.___", state 87, "(1)" + line 236, "pan.___", state 99, "(1)" + line 240, "pan.___", state 107, "(1)" + line 388, "pan.___", state 133, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 165, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 179, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 405, "pan.___", state 198, "(1)" + line 414, "pan.___", state 228, "(1)" + line 418, "pan.___", state 241, "(1)" + line 664, "pan.___", state 262, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 388, "pan.___", state 269, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 301, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 315, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 405, "pan.___", state 334, "(1)" + line 414, "pan.___", state 364, "(1)" + line 418, "pan.___", state 377, "(1)" + line 388, "pan.___", state 398, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 430, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 444, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 405, "pan.___", state 463, "(1)" + line 414, "pan.___", state 493, "(1)" + line 418, "pan.___", state 506, "(1)" + line 388, "pan.___", state 529, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 388, "pan.___", state 531, "(1)" + line 388, "pan.___", state 532, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 388, "pan.___", state 532, "else" + line 388, "pan.___", state 535, "(1)" + line 392, "pan.___", state 543, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 392, "pan.___", state 545, "(1)" + line 392, "pan.___", state 546, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 392, "pan.___", state 546, "else" + line 392, "pan.___", state 549, "(1)" + line 392, "pan.___", state 550, "(1)" + line 392, "pan.___", state 550, "(1)" + line 390, "pan.___", state 555, "((i<1))" + line 390, "pan.___", state 555, "((i>=1))" + line 397, "pan.___", state 561, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 563, "(1)" + line 397, "pan.___", state 564, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 397, "pan.___", state 564, "else" + line 397, "pan.___", state 567, "(1)" + line 397, "pan.___", state 568, "(1)" + line 397, "pan.___", state 568, "(1)" + line 401, "pan.___", state 575, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 401, "pan.___", state 577, "(1)" + line 401, "pan.___", state 578, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 401, "pan.___", state 578, "else" + line 401, "pan.___", state 581, "(1)" + line 401, "pan.___", state 582, "(1)" + line 401, "pan.___", state 582, "(1)" + line 399, "pan.___", state 587, "((i<2))" + line 399, "pan.___", state 587, "((i>=2))" + line 405, "pan.___", state 594, "(1)" + line 405, "pan.___", state 595, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 405, "pan.___", state 595, "else" + line 405, "pan.___", state 598, "(1)" + line 405, "pan.___", state 599, "(1)" + line 405, "pan.___", state 599, "(1)" + line 409, "pan.___", state 607, "(1)" + line 409, "pan.___", state 608, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 409, "pan.___", state 608, "else" + line 409, "pan.___", state 611, "(1)" + line 409, "pan.___", state 612, "(1)" + line 409, "pan.___", state 612, "(1)" + line 407, "pan.___", state 617, "((i<1))" + line 407, "pan.___", state 617, "((i>=1))" + line 414, "pan.___", state 624, "(1)" + line 414, "pan.___", state 625, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 414, "pan.___", state 625, "else" + line 414, "pan.___", state 628, "(1)" + line 414, "pan.___", state 629, "(1)" + line 414, "pan.___", state 629, "(1)" + line 418, "pan.___", state 637, "(1)" + line 418, "pan.___", state 638, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 418, "pan.___", state 638, "else" + line 418, "pan.___", state 641, "(1)" + line 418, "pan.___", state 642, "(1)" + line 418, "pan.___", state 642, "(1)" + line 416, "pan.___", state 647, "((i<2))" + line 416, "pan.___", state 647, "((i>=2))" + line 423, "pan.___", state 651, "(1)" + line 423, "pan.___", state 651, "(1)" + line 664, "pan.___", state 654, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 664, "pan.___", state 655, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 664, "pan.___", state 656, "(1)" + line 388, "pan.___", state 663, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 695, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 709, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 405, "pan.___", state 728, "(1)" + line 414, "pan.___", state 758, "(1)" + line 418, "pan.___", state 771, "(1)" + line 388, "pan.___", state 799, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 388, "pan.___", state 801, "(1)" + line 388, "pan.___", state 802, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 388, "pan.___", state 802, "else" + line 388, "pan.___", state 805, "(1)" + line 392, "pan.___", state 813, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 392, "pan.___", state 815, "(1)" + line 392, "pan.___", state 816, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 392, "pan.___", state 816, "else" + line 392, "pan.___", state 819, "(1)" + line 392, "pan.___", state 820, "(1)" + line 392, "pan.___", state 820, "(1)" + line 390, "pan.___", state 825, "((i<1))" + line 390, "pan.___", state 825, "((i>=1))" + line 397, "pan.___", state 831, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 833, "(1)" + line 397, "pan.___", state 834, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 397, "pan.___", state 834, "else" + line 397, "pan.___", state 837, "(1)" + line 397, "pan.___", state 838, "(1)" + line 397, "pan.___", state 838, "(1)" + line 401, "pan.___", state 845, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 401, "pan.___", state 847, "(1)" + line 401, "pan.___", state 848, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 401, "pan.___", state 848, "else" + line 401, "pan.___", state 851, "(1)" + line 401, "pan.___", state 852, "(1)" + line 401, "pan.___", state 852, "(1)" + line 399, "pan.___", state 857, "((i<2))" + line 399, "pan.___", state 857, "((i>=2))" + line 405, "pan.___", state 864, "(1)" + line 405, "pan.___", state 865, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 405, "pan.___", state 865, "else" + line 405, "pan.___", state 868, "(1)" + line 405, "pan.___", state 869, "(1)" + line 405, "pan.___", state 869, "(1)" + line 409, "pan.___", state 877, "(1)" + line 409, "pan.___", state 878, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 409, "pan.___", state 878, "else" + line 409, "pan.___", state 881, "(1)" + line 409, "pan.___", state 882, "(1)" + line 409, "pan.___", state 882, "(1)" + line 407, "pan.___", state 887, "((i<1))" + line 407, "pan.___", state 887, "((i>=1))" + line 414, "pan.___", state 894, "(1)" + line 414, "pan.___", state 895, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 414, "pan.___", state 895, "else" + line 414, "pan.___", state 898, "(1)" + line 414, "pan.___", state 899, "(1)" + line 414, "pan.___", state 899, "(1)" + line 418, "pan.___", state 907, "(1)" + line 418, "pan.___", state 908, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 418, "pan.___", state 908, "else" + line 418, "pan.___", state 911, "(1)" + line 418, "pan.___", state 912, "(1)" + line 418, "pan.___", state 912, "(1)" + line 423, "pan.___", state 921, "(1)" + line 423, "pan.___", state 921, "(1)" + line 388, "pan.___", state 928, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 388, "pan.___", state 930, "(1)" + line 388, "pan.___", state 931, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 388, "pan.___", state 931, "else" + line 388, "pan.___", state 934, "(1)" + line 392, "pan.___", state 942, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 392, "pan.___", state 944, "(1)" + line 392, "pan.___", state 945, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 392, "pan.___", state 945, "else" + line 392, "pan.___", state 948, "(1)" + line 392, "pan.___", state 949, "(1)" + line 392, "pan.___", state 949, "(1)" + line 390, "pan.___", state 954, "((i<1))" + line 390, "pan.___", state 954, "((i>=1))" + line 397, "pan.___", state 960, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 962, "(1)" + line 397, "pan.___", state 963, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 397, "pan.___", state 963, "else" + line 397, "pan.___", state 966, "(1)" + line 397, "pan.___", state 967, "(1)" + line 397, "pan.___", state 967, "(1)" + line 401, "pan.___", state 974, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 401, "pan.___", state 976, "(1)" + line 401, "pan.___", state 977, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 401, "pan.___", state 977, "else" + line 401, "pan.___", state 980, "(1)" + line 401, "pan.___", state 981, "(1)" + line 401, "pan.___", state 981, "(1)" + line 399, "pan.___", state 986, "((i<2))" + line 399, "pan.___", state 986, "((i>=2))" + line 405, "pan.___", state 993, "(1)" + line 405, "pan.___", state 994, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 405, "pan.___", state 994, "else" + line 405, "pan.___", state 997, "(1)" + line 405, "pan.___", state 998, "(1)" + line 405, "pan.___", state 998, "(1)" + line 409, "pan.___", state 1006, "(1)" + line 409, "pan.___", state 1007, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 409, "pan.___", state 1007, "else" + line 409, "pan.___", state 1010, "(1)" + line 409, "pan.___", state 1011, "(1)" + line 409, "pan.___", state 1011, "(1)" + line 407, "pan.___", state 1016, "((i<1))" + line 407, "pan.___", state 1016, "((i>=1))" + line 414, "pan.___", state 1023, "(1)" + line 414, "pan.___", state 1024, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 414, "pan.___", state 1024, "else" + line 414, "pan.___", state 1027, "(1)" + line 414, "pan.___", state 1028, "(1)" + line 414, "pan.___", state 1028, "(1)" + line 418, "pan.___", state 1036, "(1)" + line 418, "pan.___", state 1037, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 418, "pan.___", state 1037, "else" + line 418, "pan.___", state 1040, "(1)" + line 418, "pan.___", state 1041, "(1)" + line 418, "pan.___", state 1041, "(1)" + line 416, "pan.___", state 1046, "((i<2))" + line 416, "pan.___", state 1046, "((i>=2))" + line 423, "pan.___", state 1050, "(1)" + line 423, "pan.___", state 1050, "(1)" + line 672, "pan.___", state 1054, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 388, "pan.___", state 1059, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 1091, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 1105, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1124, "(1)" + line 414, "pan.___", state 1154, "(1)" + line 418, "pan.___", state 1167, "(1)" + line 388, "pan.___", state 1191, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 1223, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 1237, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1256, "(1)" + line 414, "pan.___", state 1286, "(1)" + line 418, "pan.___", state 1299, "(1)" + line 388, "pan.___", state 1324, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 1356, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 1370, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1389, "(1)" + line 414, "pan.___", state 1419, "(1)" + line 418, "pan.___", state 1432, "(1)" + line 388, "pan.___", state 1453, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 1485, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 1499, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1518, "(1)" + line 414, "pan.___", state 1548, "(1)" + line 418, "pan.___", state 1561, "(1)" + line 388, "pan.___", state 1587, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 1619, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 1633, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1652, "(1)" + line 414, "pan.___", state 1682, "(1)" + line 418, "pan.___", state 1695, "(1)" + line 388, "pan.___", state 1716, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 1748, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 1762, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1781, "(1)" + line 414, "pan.___", state 1811, "(1)" + line 418, "pan.___", state 1824, "(1)" + line 388, "pan.___", state 1848, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 1880, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 1894, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1913, "(1)" + line 414, "pan.___", state 1943, "(1)" + line 418, "pan.___", state 1956, "(1)" + line 711, "pan.___", state 1977, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 388, "pan.___", state 1984, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 2016, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 2030, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 405, "pan.___", state 2049, "(1)" + line 414, "pan.___", state 2079, "(1)" + line 418, "pan.___", state 2092, "(1)" + line 388, "pan.___", state 2113, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 2145, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 2159, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 405, "pan.___", state 2178, "(1)" + line 414, "pan.___", state 2208, "(1)" + line 418, "pan.___", state 2221, "(1)" + line 388, "pan.___", state 2244, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 388, "pan.___", state 2246, "(1)" + line 388, "pan.___", state 2247, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 388, "pan.___", state 2247, "else" + line 388, "pan.___", state 2250, "(1)" + line 392, "pan.___", state 2258, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 392, "pan.___", state 2260, "(1)" + line 392, "pan.___", state 2261, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 392, "pan.___", state 2261, "else" + line 392, "pan.___", state 2264, "(1)" + line 392, "pan.___", state 2265, "(1)" + line 392, "pan.___", state 2265, "(1)" + line 390, "pan.___", state 2270, "((i<1))" + line 390, "pan.___", state 2270, "((i>=1))" + line 397, "pan.___", state 2276, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 2278, "(1)" + line 397, "pan.___", state 2279, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 397, "pan.___", state 2279, "else" + line 397, "pan.___", state 2282, "(1)" + line 397, "pan.___", state 2283, "(1)" + line 397, "pan.___", state 2283, "(1)" + line 401, "pan.___", state 2290, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 401, "pan.___", state 2292, "(1)" + line 401, "pan.___", state 2293, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 401, "pan.___", state 2293, "else" + line 401, "pan.___", state 2296, "(1)" + line 401, "pan.___", state 2297, "(1)" + line 401, "pan.___", state 2297, "(1)" + line 399, "pan.___", state 2302, "((i<2))" + line 399, "pan.___", state 2302, "((i>=2))" + line 405, "pan.___", state 2309, "(1)" + line 405, "pan.___", state 2310, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 405, "pan.___", state 2310, "else" + line 405, "pan.___", state 2313, "(1)" + line 405, "pan.___", state 2314, "(1)" + line 405, "pan.___", state 2314, "(1)" + line 409, "pan.___", state 2322, "(1)" + line 409, "pan.___", state 2323, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 409, "pan.___", state 2323, "else" + line 409, "pan.___", state 2326, "(1)" + line 409, "pan.___", state 2327, "(1)" + line 409, "pan.___", state 2327, "(1)" + line 407, "pan.___", state 2332, "((i<1))" + line 407, "pan.___", state 2332, "((i>=1))" + line 414, "pan.___", state 2339, "(1)" + line 414, "pan.___", state 2340, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 414, "pan.___", state 2340, "else" + line 414, "pan.___", state 2343, "(1)" + line 414, "pan.___", state 2344, "(1)" + line 414, "pan.___", state 2344, "(1)" + line 418, "pan.___", state 2352, "(1)" + line 418, "pan.___", state 2353, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 418, "pan.___", state 2353, "else" + line 418, "pan.___", state 2356, "(1)" + line 418, "pan.___", state 2357, "(1)" + line 418, "pan.___", state 2357, "(1)" + line 416, "pan.___", state 2362, "((i<2))" + line 416, "pan.___", state 2362, "((i>=2))" + line 423, "pan.___", state 2366, "(1)" + line 423, "pan.___", state 2366, "(1)" + line 711, "pan.___", state 2369, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 711, "pan.___", state 2370, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 711, "pan.___", state 2371, "(1)" + line 388, "pan.___", state 2378, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 2410, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 2424, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 405, "pan.___", state 2443, "(1)" + line 414, "pan.___", state 2473, "(1)" + line 418, "pan.___", state 2486, "(1)" + line 388, "pan.___", state 2513, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 2545, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 2559, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 405, "pan.___", state 2578, "(1)" + line 414, "pan.___", state 2608, "(1)" + line 418, "pan.___", state 2621, "(1)" + line 388, "pan.___", state 2642, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 2674, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 2688, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 405, "pan.___", state 2707, "(1)" + line 414, "pan.___", state 2737, "(1)" + line 418, "pan.___", state 2750, "(1)" + line 228, "pan.___", state 2783, "(1)" + line 236, "pan.___", state 2803, "(1)" + line 240, "pan.___", state 2811, "(1)" + line 228, "pan.___", state 2826, "(1)" + line 236, "pan.___", state 2846, "(1)" + line 240, "pan.___", state 2854, "(1)" + line 871, "pan.___", state 2871, "-end-" + (279 of 2871 states) +unreached in proctype urcu_writer + line 388, "pan.___", state 18, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 388, "pan.___", state 24, "(1)" + line 392, "pan.___", state 32, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 392, "pan.___", state 38, "(1)" + line 392, "pan.___", state 39, "(1)" + line 392, "pan.___", state 39, "(1)" + line 390, "pan.___", state 44, "((i<1))" + line 390, "pan.___", state 44, "((i>=1))" + line 397, "pan.___", state 50, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 56, "(1)" + line 397, "pan.___", state 57, "(1)" + line 397, "pan.___", state 57, "(1)" + line 401, "pan.___", state 64, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 401, "pan.___", state 70, "(1)" + line 401, "pan.___", state 71, "(1)" + line 401, "pan.___", state 71, "(1)" + line 399, "pan.___", state 76, "((i<2))" + line 399, "pan.___", state 76, "((i>=2))" + line 405, "pan.___", state 83, "(1)" + line 405, "pan.___", state 84, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 405, "pan.___", state 84, "else" + line 405, "pan.___", state 87, "(1)" + line 405, "pan.___", state 88, "(1)" + line 405, "pan.___", state 88, "(1)" + line 409, "pan.___", state 96, "(1)" + line 409, "pan.___", state 97, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 409, "pan.___", state 97, "else" + line 409, "pan.___", state 100, "(1)" + line 409, "pan.___", state 101, "(1)" + line 409, "pan.___", state 101, "(1)" + line 407, "pan.___", state 106, "((i<1))" + line 407, "pan.___", state 106, "((i>=1))" + line 414, "pan.___", state 113, "(1)" + line 414, "pan.___", state 114, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 414, "pan.___", state 114, "else" + line 414, "pan.___", state 117, "(1)" + line 414, "pan.___", state 118, "(1)" + line 414, "pan.___", state 118, "(1)" + line 418, "pan.___", state 126, "(1)" + line 418, "pan.___", state 127, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 418, "pan.___", state 127, "else" + line 418, "pan.___", state 130, "(1)" + line 418, "pan.___", state 131, "(1)" + line 418, "pan.___", state 131, "(1)" + line 416, "pan.___", state 136, "((i<2))" + line 416, "pan.___", state 136, "((i>=2))" + line 423, "pan.___", state 140, "(1)" + line 423, "pan.___", state 140, "(1)" + line 251, "pan.___", state 149, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 255, "pan.___", state 158, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 166, "((i<1))" + line 253, "pan.___", state 166, "((i>=1))" + line 259, "pan.___", state 171, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 994, "pan.___", state 199, "old_data = cached_rcu_ptr.val[_pid]" + line 388, "pan.___", state 211, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 392, "pan.___", state 225, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 243, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 257, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 405, "pan.___", state 276, "(1)" + line 409, "pan.___", state 289, "(1)" + line 414, "pan.___", state 306, "(1)" + line 418, "pan.___", state 319, "(1)" + line 392, "pan.___", state 356, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 374, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 388, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 420, "(1)" + line 414, "pan.___", state 437, "(1)" + line 418, "pan.___", state 450, "(1)" + line 392, "pan.___", state 491, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 509, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 523, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 555, "(1)" + line 414, "pan.___", state 572, "(1)" + line 418, "pan.___", state 585, "(1)" + line 392, "pan.___", state 619, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 637, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 651, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 683, "(1)" + line 414, "pan.___", state 700, "(1)" + line 418, "pan.___", state 713, "(1)" + line 392, "pan.___", state 748, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 766, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 780, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 812, "(1)" + line 414, "pan.___", state 829, "(1)" + line 418, "pan.___", state 842, "(1)" + line 392, "pan.___", state 879, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 897, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 401, "pan.___", state 911, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 943, "(1)" + line 414, "pan.___", state 960, "(1)" + line 418, "pan.___", state 973, "(1)" + line 388, "pan.___", state 999, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 388, "pan.___", state 1001, "(1)" + line 388, "pan.___", state 1002, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 388, "pan.___", state 1002, "else" + line 388, "pan.___", state 1005, "(1)" + line 392, "pan.___", state 1013, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 392, "pan.___", state 1015, "(1)" + line 392, "pan.___", state 1016, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 392, "pan.___", state 1016, "else" + line 392, "pan.___", state 1019, "(1)" + line 392, "pan.___", state 1020, "(1)" + line 392, "pan.___", state 1020, "(1)" + line 390, "pan.___", state 1025, "((i<1))" + line 390, "pan.___", state 1025, "((i>=1))" + line 397, "pan.___", state 1031, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 397, "pan.___", state 1033, "(1)" + line 397, "pan.___", state 1034, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 397, "pan.___", state 1034, "else" + line 397, "pan.___", state 1037, "(1)" + line 397, "pan.___", state 1038, "(1)" + line 397, "pan.___", state 1038, "(1)" + line 401, "pan.___", state 1045, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 401, "pan.___", state 1047, "(1)" + line 401, "pan.___", state 1048, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 401, "pan.___", state 1048, "else" + line 401, "pan.___", state 1051, "(1)" + line 401, "pan.___", state 1052, "(1)" + line 401, "pan.___", state 1052, "(1)" + line 399, "pan.___", state 1057, "((i<2))" + line 399, "pan.___", state 1057, "((i>=2))" + line 405, "pan.___", state 1064, "(1)" + line 405, "pan.___", state 1065, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 405, "pan.___", state 1065, "else" + line 405, "pan.___", state 1068, "(1)" + line 405, "pan.___", state 1069, "(1)" + line 405, "pan.___", state 1069, "(1)" + line 409, "pan.___", state 1077, "(1)" + line 409, "pan.___", state 1078, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 409, "pan.___", state 1078, "else" + line 409, "pan.___", state 1081, "(1)" + line 409, "pan.___", state 1082, "(1)" + line 409, "pan.___", state 1082, "(1)" + line 407, "pan.___", state 1087, "((i<1))" + line 407, "pan.___", state 1087, "((i>=1))" + line 414, "pan.___", state 1094, "(1)" + line 414, "pan.___", state 1095, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 414, "pan.___", state 1095, "else" + line 414, "pan.___", state 1098, "(1)" + line 414, "pan.___", state 1099, "(1)" + line 414, "pan.___", state 1099, "(1)" + line 418, "pan.___", state 1107, "(1)" + line 418, "pan.___", state 1108, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 418, "pan.___", state 1108, "else" + line 418, "pan.___", state 1111, "(1)" + line 418, "pan.___", state 1112, "(1)" + line 418, "pan.___", state 1112, "(1)" + line 423, "pan.___", state 1121, "(1)" + line 423, "pan.___", state 1121, "(1)" + line 251, "pan.___", state 1153, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 255, "pan.___", state 1162, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 1170, "((i<1))" + line 253, "pan.___", state 1170, "((i>=1))" + line 259, "pan.___", state 1177, "(1)" + line 259, "pan.___", state 1178, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 259, "pan.___", state 1178, "else" + line 263, "pan.___", state 1184, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1192, "((i<2))" + line 261, "pan.___", state 1192, "((i>=2))" + line 228, "pan.___", state 1200, "(1)" + line 232, "pan.___", state 1208, "(1)" + line 232, "pan.___", state 1209, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 232, "pan.___", state 1209, "else" + line 230, "pan.___", state 1214, "((i<1))" + line 230, "pan.___", state 1214, "((i>=1))" + line 236, "pan.___", state 1220, "(1)" + line 236, "pan.___", state 1221, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 236, "pan.___", state 1221, "else" + line 240, "pan.___", state 1228, "(1)" + line 240, "pan.___", state 1229, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 240, "pan.___", state 1229, "else" + line 245, "pan.___", state 1238, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 245, "pan.___", state 1238, "else" + line 251, "pan.___", state 1259, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 255, "pan.___", state 1268, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 259, "pan.___", state 1281, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 263, "pan.___", state 1290, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 228, "pan.___", state 1306, "(1)" + line 232, "pan.___", state 1314, "(1)" + line 236, "pan.___", state 1326, "(1)" + line 240, "pan.___", state 1334, "(1)" + line 255, "pan.___", state 1360, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 259, "pan.___", state 1373, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 263, "pan.___", state 1382, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 228, "pan.___", state 1398, "(1)" + line 232, "pan.___", state 1406, "(1)" + line 236, "pan.___", state 1418, "(1)" + line 240, "pan.___", state 1426, "(1)" + line 251, "pan.___", state 1457, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 255, "pan.___", state 1466, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 259, "pan.___", state 1479, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 263, "pan.___", state 1488, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 228, "pan.___", state 1504, "(1)" + line 232, "pan.___", state 1512, "(1)" + line 236, "pan.___", state 1524, "(1)" + line 240, "pan.___", state 1532, "(1)" + line 1192, "pan.___", state 1548, "-end-" + (154 of 1548 states) +unreached in proctype :init: + (0 of 78 states) +unreached in proctype :never: + line 1253, "pan.___", state 11, "-end-" + (1 of 11 states) + +pan: elapsed time 14 seconds +pan: rate 4238.4725 states/second +pan: avg transition delay 1.2667e-06 usec +cp .input.spin urcu_progress_writer_error.spin.input +cp .input.spin.trail urcu_progress_writer_error.spin.input.trail +make[1]: Leaving directory `/home/compudj/doc/userspace-rcu/formal-model/urcu-controldataflow' diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer_error.spin.input b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer_error.spin.input new file mode 100644 index 0000000..b4c4af4 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer_error.spin.input @@ -0,0 +1,1228 @@ +#define WRITER_PROGRESS +#define GEN_ERROR_WRITER_PROGRESS + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* We choose to ignore writer's non-progress caused from the + * reader ignoring the writer's mb() requests */ +#ifdef WRITER_PROGRESS +progress_writer_from_reader: +#endif + break; + od; +} + +#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: +#define PROGRESS_LABEL(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; \ + /* \ + * 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) \ + do \ + :: (reader_barrier[i] == 1) -> skip; \ + :: (reader_barrier[i] == 0) -> break; \ + od; \ + i++; \ + :: i >= NR_READERS -> \ + break \ + od; \ + smp_mb(i, j); \ +} + +#else + +#define smp_mb_send(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + :: 1 -> skip; + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer_error.spin.input.trail b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer_error.spin.input.trail new file mode 100644 index 0000000..de65bad --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/result-ipi-urcu_free/urcu_progress_writer_error.spin.input.trail @@ -0,0 +1,1215 @@ +-2:3:-2 +-4:-4:-4 +1:0:4499 +2:3:4419 +3:3:4422 +4:3:4422 +5:3:4425 +6:3:4433 +7:3:4433 +8:3:4436 +9:3:4442 +10:3:4446 +11:3:4446 +12:3:4449 +13:3:4459 +14:3:4467 +15:3:4467 +16:3:4470 +17:3:4476 +18:3:4480 +19:3:4480 +20:3:4483 +21:3:4489 +22:3:4493 +23:3:4494 +24:0:4499 +25:3:4496 +26:0:4499 +27:2:2873 +28:0:4499 +29:2:2879 +30:0:4499 +31:2:2880 +32:0:4499 +33:2:2881 +34:0:4497 +35:2:2882 +36:0:4503 +37:2:2883 +38:0:4503 +39:2:2884 +40:2:2885 +41:2:2889 +42:2:2890 +43:2:2898 +44:2:2899 +45:2:2903 +46:2:2904 +47:2:2912 +48:2:2917 +49:2:2921 +50:2:2922 +51:2:2930 +52:2:2931 +53:2:2935 +54:2:2936 +55:2:2930 +56:2:2931 +57:2:2935 +58:2:2936 +59:2:2944 +60:2:2949 +61:2:2950 +62:2:2961 +63:2:2962 +64:2:2963 +65:2:2974 +66:2:2979 +67:2:2980 +68:2:2991 +69:2:2992 +70:2:2993 +71:2:2991 +72:2:2992 +73:2:2993 +74:2:3004 +75:2:3012 +76:0:4503 +77:2:2883 +78:0:4503 +79:2:3016 +80:2:3020 +81:2:3021 +82:2:3025 +83:2:3029 +84:2:3030 +85:2:3034 +86:2:3042 +87:2:3043 +88:2:3047 +89:2:3051 +90:2:3052 +91:2:3047 +92:2:3048 +93:2:3056 +94:0:4503 +95:2:2883 +96:0:4503 +97:2:3064 +98:2:3065 +99:2:3066 +100:0:4503 +101:2:2883 +102:0:4503 +103:2:3071 +104:0:4503 +105:2:4024 +106:2:4025 +107:2:4029 +108:2:4033 +109:2:4034 +110:2:4038 +111:2:4043 +112:2:4051 +113:2:4055 +114:2:4056 +115:2:4051 +116:2:4055 +117:2:4056 +118:2:4060 +119:2:4067 +120:2:4074 +121:2:4075 +122:2:4082 +123:2:4087 +124:2:4094 +125:2:4095 +126:2:4094 +127:2:4095 +128:2:4102 +129:2:4106 +130:0:4503 +131:2:4111 +132:0:4503 +133:2:4112 +134:0:4503 +135:2:4113 +136:0:4503 +137:2:4114 +138:0:4503 +139:1:2 +140:0:4503 +141:2:4115 +142:0:4503 +143:1:8 +144:0:4503 +145:1:9 +146:0:4503 +147:2:4114 +148:0:4503 +149:2:4115 +150:0:4503 +151:1:10 +152:0:4503 +153:2:4114 +154:0:4503 +155:2:4115 +156:0:4503 +157:1:11 +158:0:4503 +159:2:4114 +160:0:4503 +161:2:4115 +162:0:4503 +163:1:12 +164:0:4503 +165:2:4114 +166:0:4503 +167:2:4115 +168:0:4503 +169:1:13 +170:0:4503 +171:2:4114 +172:0:4503 +173:2:4115 +174:0:4503 +175:1:14 +176:0:4503 +177:1:15 +178:0:4503 +179:1:23 +180:0:4503 +181:1:24 +182:0:4503 +183:2:4114 +184:0:4503 +185:2:4115 +186:0:4503 +187:1:128 +188:1:129 +189:1:133 +190:1:134 +191:1:142 +192:1:143 +193:1:147 +194:1:148 +195:1:156 +196:1:161 +197:1:165 +198:1:166 +199:1:174 +200:1:175 +201:1:179 +202:1:180 +203:1:174 +204:1:175 +205:1:179 +206:1:180 +207:1:188 +208:1:193 +209:1:194 +210:1:205 +211:1:206 +212:1:207 +213:1:218 +214:1:223 +215:1:224 +216:1:235 +217:1:236 +218:1:237 +219:1:235 +220:1:236 +221:1:237 +222:1:248 +223:0:4503 +224:1:15 +225:0:4503 +226:1:23 +227:0:4503 +228:1:24 +229:0:4503 +230:2:4114 +231:0:4503 +232:2:4115 +233:0:4503 +234:1:257 +235:1:258 +236:0:4503 +237:1:15 +238:0:4503 +239:1:23 +240:0:4503 +241:1:24 +242:0:4503 +243:2:4114 +244:0:4503 +245:2:4115 +246:0:4503 +247:1:264 +248:1:265 +249:1:269 +250:1:270 +251:1:278 +252:1:279 +253:1:283 +254:1:284 +255:1:292 +256:1:297 +257:1:301 +258:1:302 +259:1:310 +260:1:311 +261:1:315 +262:1:316 +263:1:310 +264:1:311 +265:1:315 +266:1:316 +267:1:324 +268:1:329 +269:1:330 +270:1:341 +271:1:342 +272:1:343 +273:1:354 +274:1:359 +275:1:360 +276:1:371 +277:1:372 +278:1:373 +279:1:371 +280:1:372 +281:1:373 +282:1:384 +283:0:4503 +284:1:15 +285:0:4503 +286:1:23 +287:0:4503 +288:1:24 +289:0:4503 +290:2:4114 +291:0:4503 +292:2:4115 +293:0:4503 +294:1:393 +295:1:394 +296:1:398 +297:1:399 +298:1:407 +299:1:408 +300:1:412 +301:1:413 +302:1:421 +303:1:426 +304:1:430 +305:1:431 +306:1:439 +307:1:440 +308:1:444 +309:1:445 +310:1:439 +311:1:440 +312:1:444 +313:1:445 +314:1:453 +315:1:458 +316:1:459 +317:1:470 +318:1:471 +319:1:472 +320:1:483 +321:1:488 +322:1:489 +323:1:500 +324:1:501 +325:1:502 +326:1:500 +327:1:501 +328:1:502 +329:1:513 +330:1:520 +331:0:4503 +332:1:15 +333:0:4503 +334:1:23 +335:0:4503 +336:1:24 +337:0:4503 +338:2:4114 +339:0:4503 +340:2:4115 +341:0:4503 +342:1:658 +343:1:659 +344:1:663 +345:1:664 +346:1:672 +347:1:673 +348:1:674 +349:1:686 +350:1:691 +351:1:695 +352:1:696 +353:1:704 +354:1:705 +355:1:709 +356:1:710 +357:1:704 +358:1:705 +359:1:709 +360:1:710 +361:1:718 +362:1:723 +363:1:724 +364:1:735 +365:1:736 +366:1:737 +367:1:748 +368:1:753 +369:1:754 +370:1:765 +371:1:766 +372:1:767 +373:1:765 +374:1:766 +375:1:767 +376:1:778 +377:0:4503 +378:1:15 +379:0:4503 +380:1:23 +381:0:4503 +382:1:24 +383:0:4503 +384:2:4114 +385:0:4503 +386:2:4115 +387:0:4503 +388:1:787 +389:1:790 +390:1:791 +391:0:4503 +392:1:15 +393:0:4503 +394:1:23 +395:0:4503 +396:1:24 +397:0:4503 +398:2:4114 +399:0:4503 +400:2:4115 +401:0:4503 +402:1:1054 +403:1:1055 +404:1:1059 +405:1:1060 +406:1:1068 +407:1:1069 +408:1:1073 +409:1:1074 +410:1:1082 +411:1:1087 +412:1:1091 +413:1:1092 +414:1:1100 +415:1:1101 +416:1:1105 +417:1:1106 +418:1:1100 +419:1:1101 +420:1:1105 +421:1:1106 +422:1:1114 +423:1:1119 +424:1:1120 +425:1:1131 +426:1:1132 +427:1:1133 +428:1:1144 +429:1:1149 +430:1:1150 +431:1:1161 +432:1:1162 +433:1:1163 +434:1:1161 +435:1:1162 +436:1:1163 +437:1:1174 +438:1:1181 +439:1:1185 +440:0:4503 +441:1:15 +442:0:4503 +443:1:23 +444:0:4503 +445:1:24 +446:0:4503 +447:2:4114 +448:0:4503 +449:2:4115 +450:0:4503 +451:1:1186 +452:1:1187 +453:1:1191 +454:1:1192 +455:1:1200 +456:1:1201 +457:1:1202 +458:1:1214 +459:1:1219 +460:1:1223 +461:1:1224 +462:1:1232 +463:1:1233 +464:1:1237 +465:1:1238 +466:1:1232 +467:1:1233 +468:1:1237 +469:1:1238 +470:1:1246 +471:1:1251 +472:1:1252 +473:1:1263 +474:1:1264 +475:1:1265 +476:1:1276 +477:1:1281 +478:1:1282 +479:1:1293 +480:1:1294 +481:1:1295 +482:1:1293 +483:1:1294 +484:1:1295 +485:1:1306 +486:0:4503 +487:1:15 +488:0:4503 +489:1:23 +490:0:4503 +491:1:24 +492:0:4503 +493:2:4114 +494:0:4503 +495:2:4115 +496:0:4503 +497:1:1315 +498:0:4503 +499:2:4114 +500:0:4503 +501:2:4115 +502:0:4503 +503:1:2779 +504:1:2786 +505:1:2787 +506:1:2794 +507:1:2799 +508:1:2806 +509:1:2807 +510:1:2806 +511:1:2807 +512:1:2814 +513:1:2818 +514:0:4503 +515:2:4114 +516:0:4503 +517:2:4115 +518:0:4503 +519:1:1317 +520:1:1318 +521:0:4503 +522:1:15 +523:0:4503 +524:1:23 +525:0:4503 +526:1:24 +527:0:4503 +528:2:4114 +529:0:4503 +530:2:4115 +531:0:4503 +532:1:1319 +533:1:1320 +534:1:1324 +535:1:1325 +536:1:1333 +537:1:1334 +538:1:1338 +539:1:1339 +540:1:1347 +541:1:1352 +542:1:1356 +543:1:1357 +544:1:1365 +545:1:1366 +546:1:1370 +547:1:1371 +548:1:1365 +549:1:1366 +550:1:1370 +551:1:1371 +552:1:1379 +553:1:1384 +554:1:1385 +555:1:1396 +556:1:1397 +557:1:1398 +558:1:1409 +559:1:1414 +560:1:1415 +561:1:1426 +562:1:1427 +563:1:1428 +564:1:1426 +565:1:1427 +566:1:1428 +567:1:1439 +568:0:4503 +569:1:15 +570:0:4503 +571:1:23 +572:0:4503 +573:1:24 +574:0:4503 +575:2:4114 +576:0:4503 +577:2:4115 +578:0:4503 +579:1:1448 +580:1:1449 +581:1:1453 +582:1:1454 +583:1:1462 +584:1:1463 +585:1:1467 +586:1:1468 +587:1:1476 +588:1:1481 +589:1:1485 +590:1:1486 +591:1:1494 +592:1:1495 +593:1:1499 +594:1:1500 +595:1:1494 +596:1:1495 +597:1:1499 +598:1:1500 +599:1:1508 +600:1:1513 +601:1:1514 +602:1:1525 +603:1:1526 +604:1:1527 +605:1:1538 +606:1:1543 +607:1:1544 +608:1:1555 +609:1:1556 +610:1:1557 +611:1:1555 +612:1:1556 +613:1:1557 +614:1:1568 +615:1:1575 +616:1:1579 +617:0:4503 +618:1:15 +619:0:4503 +620:1:23 +621:0:4503 +622:1:24 +623:0:4503 +624:2:4114 +625:0:4503 +626:2:4115 +627:0:4503 +628:1:1582 +629:1:1583 +630:1:1587 +631:1:1588 +632:1:1596 +633:1:1597 +634:1:1598 +635:1:1610 +636:1:1615 +637:1:1619 +638:1:1620 +639:1:1628 +640:1:1629 +641:1:1633 +642:1:1634 +643:1:1628 +644:1:1629 +645:1:1633 +646:1:1634 +647:1:1642 +648:1:1647 +649:1:1648 +650:1:1659 +651:1:1660 +652:1:1661 +653:1:1672 +654:1:1677 +655:1:1678 +656:1:1689 +657:1:1690 +658:1:1691 +659:1:1689 +660:1:1690 +661:1:1691 +662:1:1702 +663:0:4503 +664:1:15 +665:0:4503 +666:1:23 +667:0:4503 +668:1:24 +669:0:4503 +670:2:4114 +671:0:4503 +672:2:4115 +673:0:4503 +674:1:1711 +675:1:1712 +676:1:1716 +677:1:1717 +678:1:1725 +679:1:1726 +680:1:1730 +681:1:1731 +682:1:1739 +683:1:1744 +684:1:1748 +685:1:1749 +686:1:1757 +687:1:1758 +688:1:1762 +689:1:1763 +690:1:1757 +691:1:1758 +692:1:1762 +693:1:1763 +694:1:1771 +695:1:1776 +696:1:1777 +697:1:1788 +698:1:1789 +699:1:1790 +700:1:1801 +701:1:1806 +702:1:1807 +703:1:1818 +704:1:1819 +705:1:1820 +706:1:1818 +707:1:1819 +708:1:1820 +709:1:1831 +710:1:1838 +711:1:1842 +712:0:4503 +713:1:15 +714:0:4503 +715:1:23 +716:0:4503 +717:1:24 +718:0:4503 +719:2:4114 +720:0:4503 +721:2:4115 +722:0:4503 +723:1:1843 +724:1:1844 +725:1:1848 +726:1:1849 +727:1:1857 +728:1:1858 +729:1:1859 +730:1:1871 +731:1:1876 +732:1:1880 +733:1:1881 +734:1:1889 +735:1:1890 +736:1:1894 +737:1:1895 +738:1:1889 +739:1:1890 +740:1:1894 +741:1:1895 +742:1:1903 +743:1:1908 +744:1:1909 +745:1:1920 +746:1:1921 +747:1:1922 +748:1:1933 +749:1:1938 +750:1:1939 +751:1:1950 +752:1:1951 +753:1:1952 +754:1:1950 +755:1:1951 +756:1:1952 +757:1:1963 +758:0:4503 +759:1:15 +760:0:4503 +761:1:23 +762:0:4503 +763:1:24 +764:0:4503 +765:2:4114 +766:0:4503 +767:2:4115 +768:0:4503 +769:1:1972 +770:1:1973 +771:0:4503 +772:1:15 +773:0:4503 +774:1:23 +775:0:4503 +776:1:24 +777:0:4503 +778:2:4114 +779:0:4503 +780:2:4115 +781:0:4503 +782:1:1979 +783:1:1980 +784:1:1984 +785:1:1985 +786:1:1993 +787:1:1994 +788:1:1998 +789:1:1999 +790:1:2007 +791:1:2012 +792:1:2016 +793:1:2017 +794:1:2025 +795:1:2026 +796:1:2030 +797:1:2031 +798:1:2025 +799:1:2026 +800:1:2030 +801:1:2031 +802:1:2039 +803:1:2044 +804:1:2045 +805:1:2056 +806:1:2057 +807:1:2058 +808:1:2069 +809:1:2074 +810:1:2075 +811:1:2086 +812:1:2087 +813:1:2088 +814:1:2086 +815:1:2087 +816:1:2088 +817:1:2099 +818:0:4503 +819:1:15 +820:0:4503 +821:1:23 +822:0:4503 +823:1:24 +824:0:4503 +825:2:4114 +826:0:4503 +827:2:4115 +828:0:4503 +829:1:2108 +830:1:2109 +831:1:2113 +832:1:2114 +833:1:2122 +834:1:2123 +835:1:2127 +836:1:2128 +837:1:2136 +838:1:2141 +839:1:2145 +840:1:2146 +841:1:2154 +842:1:2155 +843:1:2159 +844:1:2160 +845:1:2154 +846:1:2155 +847:1:2159 +848:1:2160 +849:1:2168 +850:1:2173 +851:1:2174 +852:1:2185 +853:1:2186 +854:1:2187 +855:1:2198 +856:1:2203 +857:1:2204 +858:1:2215 +859:1:2216 +860:1:2217 +861:1:2215 +862:1:2216 +863:1:2217 +864:1:2228 +865:1:2235 +866:0:4503 +867:1:15 +868:0:4503 +869:1:23 +870:0:4503 +871:1:24 +872:0:4503 +873:2:4114 +874:0:4503 +875:2:4115 +876:0:4503 +877:1:2373 +878:1:2374 +879:1:2378 +880:1:2379 +881:1:2387 +882:1:2388 +883:1:2389 +884:1:2401 +885:1:2406 +886:1:2410 +887:1:2411 +888:1:2419 +889:1:2420 +890:1:2424 +891:1:2425 +892:1:2419 +893:1:2420 +894:1:2424 +895:1:2425 +896:1:2433 +897:1:2438 +898:1:2439 +899:1:2450 +900:1:2451 +901:1:2452 +902:1:2463 +903:1:2468 +904:1:2469 +905:1:2480 +906:1:2481 +907:1:2482 +908:1:2480 +909:1:2481 +910:1:2482 +911:1:2493 +912:0:4503 +913:1:15 +914:0:4503 +915:1:23 +916:0:4503 +917:1:24 +918:0:4503 +919:2:4114 +920:0:4503 +921:2:4115 +922:0:4503 +923:1:2502 +924:0:4503 +925:2:4114 +926:0:4503 +927:2:4115 +928:0:4503 +929:1:2822 +930:1:2829 +931:1:2830 +932:1:2837 +933:1:2842 +934:1:2849 +935:1:2850 +936:1:2849 +937:1:2850 +938:1:2857 +939:1:2861 +940:0:4503 +941:2:4114 +942:0:4503 +943:2:4115 +944:0:4503 +945:1:2504 +946:1:2505 +947:0:4503 +948:1:15 +949:0:4503 +950:1:23 +951:0:4503 +952:1:24 +953:0:4503 +954:2:4114 +955:0:4503 +956:2:4115 +957:0:4503 +958:1:2508 +959:1:2509 +960:1:2513 +961:1:2514 +962:1:2522 +963:1:2523 +964:1:2527 +965:1:2528 +966:1:2536 +967:1:2541 +968:1:2545 +969:1:2546 +970:1:2554 +971:1:2555 +972:1:2559 +973:1:2560 +974:1:2554 +975:1:2555 +976:1:2559 +977:1:2560 +978:1:2568 +979:1:2573 +980:1:2574 +981:1:2585 +982:1:2586 +983:1:2587 +984:1:2598 +985:1:2603 +986:1:2604 +987:1:2615 +988:1:2616 +989:1:2617 +990:1:2615 +991:1:2616 +992:1:2617 +993:1:2628 +994:0:4503 +995:1:15 +996:0:4503 +997:1:23 +998:0:4503 +999:1:24 +1000:0:4503 +1001:2:4114 +1002:0:4503 +1003:2:4115 +1004:0:4503 +1005:1:2637 +1006:1:2638 +1007:1:2642 +1008:1:2643 +1009:1:2651 +1010:1:2652 +1011:1:2656 +1012:1:2657 +1013:1:2665 +1014:1:2670 +1015:1:2674 +1016:1:2675 +1017:1:2683 +1018:1:2684 +1019:1:2688 +1020:1:2689 +1021:1:2683 +1022:1:2684 +1023:1:2688 +1024:1:2689 +1025:1:2697 +1026:1:2702 +1027:1:2703 +1028:1:2714 +1029:1:2715 +1030:1:2716 +1031:1:2727 +1032:1:2732 +1033:1:2733 +1034:1:2744 +1035:1:2745 +1036:1:2746 +1037:1:2744 +1038:1:2745 +1039:1:2746 +1040:1:2757 +1041:1:2764 +1042:1:2768 +1043:0:4503 +1044:1:15 +1045:0:4503 +1046:1:23 +1047:0:4503 +1048:1:24 +1049:0:4503 +1050:2:4114 +1051:0:4503 +1052:2:4115 +1053:0:4503 +1054:1:2769 +1055:0:4503 +1056:1:2777 +1057:0:4503 +1058:1:2865 +1059:0:4503 +1060:1:9 +1061:0:4503 +1062:2:4114 +1063:0:4503 +1064:2:4115 +1065:0:4503 +1066:1:10 +1067:0:4503 +1068:2:4114 +1069:0:4503 +1070:2:4115 +1071:0:4503 +1072:1:11 +1073:0:4503 +1074:2:4114 +1075:0:4503 +1076:2:4115 +1077:0:4503 +1078:1:12 +1079:0:4503 +1080:2:4114 +1081:0:4503 +1082:2:4115 +1083:0:4503 +1084:1:13 +1085:0:4503 +1086:2:4114 +1087:0:4503 +1088:2:4115 +1089:0:4503 +1090:1:14 +1091:0:4503 +1092:1:15 +1093:0:4503 +1094:1:23 +1095:0:4503 +1096:1:24 +1097:0:4503 +1098:2:4114 +1099:0:4503 +1100:2:4115 +1101:0:4503 +1102:1:128 +1103:1:129 +1104:1:133 +1105:1:134 +1106:1:142 +1107:1:143 +1108:1:144 +1109:1:156 +1110:1:161 +1111:1:165 +1112:1:166 +1113:1:174 +1114:1:175 +1115:1:179 +1116:1:180 +1117:1:174 +1118:1:175 +1119:1:179 +1120:1:180 +1121:1:188 +1122:1:193 +1123:1:194 +1124:1:205 +1125:1:206 +1126:1:207 +1127:1:218 +1128:1:223 +1129:1:224 +1130:1:235 +1131:1:236 +1132:1:237 +1133:1:235 +1134:1:236 +1135:1:237 +1136:1:248 +1137:0:4503 +1138:1:15 +1139:0:4503 +1140:1:23 +1141:0:4503 +1142:1:24 +1143:0:4503 +1144:2:4114 +1145:0:4503 +1146:2:4115 +1147:0:4503 +1148:1:257 +1149:1:258 +1150:0:4503 +1151:1:15 +1152:0:4503 +1153:1:23 +1154:0:4503 +1155:1:24 +1156:0:4503 +1157:2:4114 +1158:0:4503 +1159:2:4115 +1160:0:4503 +1161:1:1186 +1162:1:1187 +1163:1:1191 +1164:1:1192 +1165:1:1200 +1166:1:1201 +1167:1:1205 +1168:1:1206 +1169:1:1214 +1170:1:1219 +1171:1:1223 +1172:1:1224 +1173:1:1232 +1174:1:1233 +1175:1:1237 +1176:1:1238 +1177:1:1232 +1178:1:1233 +1179:1:1237 +1180:1:1238 +1181:1:1246 +1182:1:1251 +1183:1:1252 +1184:1:1263 +1185:1:1264 +1186:1:1265 +1187:1:1276 +1188:1:1281 +1189:1:1282 +1190:1:1293 +1191:1:1294 +1192:1:1295 +1193:1:1293 +1194:1:1294 +1195:1:1295 +1196:1:1306 +1197:0:4503 +1198:1:15 +1199:0:4503 +1200:1:16 +-1:-1:-1 +1201:0:4503 +1202:2:4114 +1203:0:4503 +1204:2:4115 +1205:0:4503 +1206:2:4114 +1207:0:4503 +1208:2:4115 +1209:0:4503 +1210:2:4114 +1211:0:4503 +1212:2:4115 diff --git a/formal-model/results/urcu-controldataflow-no-ipi/todo.sh b/formal-model/results/urcu-controldataflow-no-ipi/todo.sh new file mode 100644 index 0000000..f2bcdf6 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/todo.sh @@ -0,0 +1,18 @@ +echo testing no ipi +make urcu_free | tee urcu_free.log +echo testing no ipi +make urcu_free_no_mb | tee urcu_free_no_mb.log +echo testing no ipi +make urcu_free_no_rmb | tee urcu_free_no_rmb.log +echo testing no ipi +make urcu_free_no_wmb | tee urcu_free_no_wmb.log +echo testing no ipi +make urcu_free_single_flip | tee urcu_free_single_flip.log +echo testing no ipi +make urcu_progress_writer | tee urcu_progress_writer.log +echo testing no ipi +make urcu_progress_reader | tee urcu_progress_reader.log +echo testing no ipi +make urcu_progress_writer_error | tee urcu_progress_writer_error.log +echo testing no ipi +make asserts | tee asserts.log diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu.sh b/formal-model/results/urcu-controldataflow-no-ipi/urcu.sh new file mode 100644 index 0000000..65ff517 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# +# Compiles and runs the urcu.spin Promela model. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# Copyright (C) IBM Corporation, 2009 +# Mathieu Desnoyers, 2009 +# +# Authors: Paul E. McKenney +# Mathieu Desnoyers + +# Basic execution, without LTL clauses. See Makefile. + +spin -a urcu.spin +cc -DSAFETY -o pan pan.c +./pan -v -c1 -X -m10000000 -w21 diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu.spin b/formal-model/results/urcu-controldataflow-no-ipi/urcu.spin new file mode 100644 index 0000000..4fe6b9e --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu.spin @@ -0,0 +1,1225 @@ +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu.spin.bkp.b4ptr b/formal-model/results/urcu-controldataflow-no-ipi/urcu.spin.bkp.b4ptr new file mode 100644 index 0000000..6670f3e --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu.spin.bkp.b4ptr @@ -0,0 +1,1123 @@ +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bit { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bit cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(generation_ptr, get_pid()); + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(generation_ptr, get_pid()); + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * Busy-looping waiting for other barrier requests is not considered as + * non-progress. + */ +#ifdef READER_PROGRESS +progress_reader2: +#endif +#ifdef WRITER_PROGRESS +//progress_writer_from_reader1: +#endif + skip; + :: 1 -> + /* We choose to ignore writer's non-progress caused from the + * reader ignoring the writer's mb() requests */ +#ifdef WRITER_PROGRESS +//progress_writer_from_reader2: +#endif + break; + od; +} + +#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; \ + /* \ + * 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) \ + do \ + :: (reader_barrier[i] == 1) -> skip; \ + :: (reader_barrier[i] == 0) -> break; \ + od; \ + i++; \ + :: i >= NR_READERS -> \ + break \ + od; \ + smp_mb(i, j); \ +} + +#else + +#define smp_mb_send(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, wmp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only two readers */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* pointer generation */ +DECLARE_CACHED_VAR(byte, generation_ptr); + +byte last_free_gen = 0; +bit free_done = 0; +byte read_generation[NR_READERS]; +bit data_access[NR_READERS]; + +bit write_lock = 0; + +bit init_done = 0; + +bit sighand_exec = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(generation_ptr, get_pid()); + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(generation_ptr, get_pid()); + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + :: 1 -> skip; + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + read_generation[get_readerid()] = + READ_CACHED_VAR(generation_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + ooo_mem(i); + goto non_atomic; +non_atomic_end: + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + read_generation[get_readerid()] = + READ_CACHED_VAR(generation_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + ooo_mem(i); + goto non_atomic2; +non_atomic2_end: + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +non_atomic: + data_access[get_readerid()] = 1; + data_access[get_readerid()] = 0; + goto non_atomic_end; +non_atomic2: + data_access[get_readerid()] = 1; + data_access[get_readerid()] = 0; + goto non_atomic2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_PROC_FIRST_MB (1 << 1) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 2) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 3) +#define WRITE_PROC_FIRST_WAIT (1 << 4) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 5) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 6) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 7) +#define WRITE_PROC_SECOND_WAIT (1 << 8) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 9) + +#define WRITE_PROC_SECOND_MB (1 << 10) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 11) - 1) + +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte old_gen; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (READ_CACHED_VAR(generation_ptr) < 5) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + ooo_mem(i); + atomic { + 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; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + + write_lock = 0; + /* free-up step, e.g., kfree(). */ + atomic { + last_free_gen = old_gen; + free_done = 1; + } + :: else -> break; + od; + /* + * 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 + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(generation_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + read_generation[i] = 1; + data_access[i] = 0; + i++; + :: i >= NR_READERS -> break + od; + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free.log b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free.log new file mode 100644 index 0000000..8d1493e --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free.log @@ -0,0 +1,525 @@ +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define >> pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_free.ltl | grep -v ^//`)" >> pan.ltl +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1257) +Depth= 4688 States= 1e+06 Transitions= 4.65e+08 Memory= 550.432 t= 592 R= 2e+03 + +(Spin Version 5.1.7 -- 23 December 2008) + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness disabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 4688, errors: 0 + 1884295 states, stored +9.0500538e+08 states, matched +9.0688968e+08 transitions (= stored+matched) +5.3819272e+09 atomic steps +hash conflicts: 4.4602277e+08 (resolved) + +Stats on memory usage (in Megabytes): + 208.452 equivalent memory usage for states (stored*(State-vector + overhead)) + 159.034 actual memory usage for states (compression: 76.29%) + state-vector as stored = 60 byte + 28 byte overhead + 8.000 memory used for hash table (-w20) + 457.764 memory used for DFS stack (-m10000000) + 624.651 total actual memory usage + +unreached in proctype urcu_reader + line 394, "pan.___", state 17, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 49, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 63, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 82, "(1)" + line 420, "pan.___", state 112, "(1)" + line 424, "pan.___", state 125, "(1)" + line 575, "pan.___", state 146, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 394, "pan.___", state 153, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 185, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 199, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 218, "(1)" + line 420, "pan.___", state 248, "(1)" + line 424, "pan.___", state 261, "(1)" + line 394, "pan.___", state 282, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 314, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 328, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 347, "(1)" + line 420, "pan.___", state 377, "(1)" + line 424, "pan.___", state 390, "(1)" + line 394, "pan.___", state 413, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 394, "pan.___", state 415, "(1)" + line 394, "pan.___", state 416, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 394, "pan.___", state 416, "else" + line 394, "pan.___", state 419, "(1)" + line 398, "pan.___", state 427, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 429, "(1)" + line 398, "pan.___", state 430, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 398, "pan.___", state 430, "else" + line 398, "pan.___", state 433, "(1)" + line 398, "pan.___", state 434, "(1)" + line 398, "pan.___", state 434, "(1)" + line 396, "pan.___", state 439, "((i<1))" + line 396, "pan.___", state 439, "((i>=1))" + line 403, "pan.___", state 445, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 447, "(1)" + line 403, "pan.___", state 448, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 403, "pan.___", state 448, "else" + line 403, "pan.___", state 451, "(1)" + line 403, "pan.___", state 452, "(1)" + line 403, "pan.___", state 452, "(1)" + line 407, "pan.___", state 459, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, "pan.___", state 461, "(1)" + line 407, "pan.___", state 462, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 407, "pan.___", state 462, "else" + line 407, "pan.___", state 465, "(1)" + line 407, "pan.___", state 466, "(1)" + line 407, "pan.___", state 466, "(1)" + line 405, "pan.___", state 471, "((i<2))" + line 405, "pan.___", state 471, "((i>=2))" + line 411, "pan.___", state 478, "(1)" + line 411, "pan.___", state 479, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 411, "pan.___", state 479, "else" + line 411, "pan.___", state 482, "(1)" + line 411, "pan.___", state 483, "(1)" + line 411, "pan.___", state 483, "(1)" + line 415, "pan.___", state 491, "(1)" + line 415, "pan.___", state 492, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 415, "pan.___", state 492, "else" + line 415, "pan.___", state 495, "(1)" + line 415, "pan.___", state 496, "(1)" + line 415, "pan.___", state 496, "(1)" + line 413, "pan.___", state 501, "((i<1))" + line 413, "pan.___", state 501, "((i>=1))" + line 420, "pan.___", state 508, "(1)" + line 420, "pan.___", state 509, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 420, "pan.___", state 509, "else" + line 420, "pan.___", state 512, "(1)" + line 420, "pan.___", state 513, "(1)" + line 420, "pan.___", state 513, "(1)" + line 424, "pan.___", state 521, "(1)" + line 424, "pan.___", state 522, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 424, "pan.___", state 522, "else" + line 424, "pan.___", state 525, "(1)" + line 424, "pan.___", state 526, "(1)" + line 424, "pan.___", state 526, "(1)" + line 422, "pan.___", state 531, "((i<2))" + line 422, "pan.___", state 531, "((i>=2))" + line 429, "pan.___", state 535, "(1)" + line 429, "pan.___", state 535, "(1)" + line 575, "pan.___", state 538, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 575, "pan.___", state 539, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 575, "pan.___", state 540, "(1)" + line 249, "pan.___", state 544, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 555, "(1)" + line 257, "pan.___", state 566, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 575, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 591, "(1)" + line 230, "pan.___", state 599, "(1)" + line 234, "pan.___", state 611, "(1)" + line 238, "pan.___", state 619, "(1)" + line 394, "pan.___", state 637, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 651, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 669, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 683, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 702, "(1)" + line 415, "pan.___", state 715, "(1)" + line 420, "pan.___", state 732, "(1)" + line 424, "pan.___", state 745, "(1)" + line 394, "pan.___", state 773, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 394, "pan.___", state 775, "(1)" + line 394, "pan.___", state 776, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 394, "pan.___", state 776, "else" + line 394, "pan.___", state 779, "(1)" + line 398, "pan.___", state 787, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 789, "(1)" + line 398, "pan.___", state 790, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 398, "pan.___", state 790, "else" + line 398, "pan.___", state 793, "(1)" + line 398, "pan.___", state 794, "(1)" + line 398, "pan.___", state 794, "(1)" + line 396, "pan.___", state 799, "((i<1))" + line 396, "pan.___", state 799, "((i>=1))" + line 403, "pan.___", state 805, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 807, "(1)" + line 403, "pan.___", state 808, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 403, "pan.___", state 808, "else" + line 403, "pan.___", state 811, "(1)" + line 403, "pan.___", state 812, "(1)" + line 403, "pan.___", state 812, "(1)" + line 407, "pan.___", state 819, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, "pan.___", state 821, "(1)" + line 407, "pan.___", state 822, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 407, "pan.___", state 822, "else" + line 407, "pan.___", state 825, "(1)" + line 407, "pan.___", state 826, "(1)" + line 407, "pan.___", state 826, "(1)" + line 405, "pan.___", state 831, "((i<2))" + line 405, "pan.___", state 831, "((i>=2))" + line 411, "pan.___", state 838, "(1)" + line 411, "pan.___", state 839, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 411, "pan.___", state 839, "else" + line 411, "pan.___", state 842, "(1)" + line 411, "pan.___", state 843, "(1)" + line 411, "pan.___", state 843, "(1)" + line 415, "pan.___", state 851, "(1)" + line 415, "pan.___", state 852, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 415, "pan.___", state 852, "else" + line 415, "pan.___", state 855, "(1)" + line 415, "pan.___", state 856, "(1)" + line 415, "pan.___", state 856, "(1)" + line 413, "pan.___", state 861, "((i<1))" + line 413, "pan.___", state 861, "((i>=1))" + line 420, "pan.___", state 868, "(1)" + line 420, "pan.___", state 869, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 420, "pan.___", state 869, "else" + line 420, "pan.___", state 872, "(1)" + line 420, "pan.___", state 873, "(1)" + line 420, "pan.___", state 873, "(1)" + line 424, "pan.___", state 881, "(1)" + line 424, "pan.___", state 882, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 424, "pan.___", state 882, "else" + line 424, "pan.___", state 885, "(1)" + line 424, "pan.___", state 886, "(1)" + line 424, "pan.___", state 886, "(1)" + line 429, "pan.___", state 895, "(1)" + line 429, "pan.___", state 895, "(1)" + line 394, "pan.___", state 902, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 394, "pan.___", state 904, "(1)" + line 394, "pan.___", state 905, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 394, "pan.___", state 905, "else" + line 394, "pan.___", state 908, "(1)" + line 398, "pan.___", state 916, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 918, "(1)" + line 398, "pan.___", state 919, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 398, "pan.___", state 919, "else" + line 398, "pan.___", state 922, "(1)" + line 398, "pan.___", state 923, "(1)" + line 398, "pan.___", state 923, "(1)" + line 396, "pan.___", state 928, "((i<1))" + line 396, "pan.___", state 928, "((i>=1))" + line 403, "pan.___", state 934, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 936, "(1)" + line 403, "pan.___", state 937, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 403, "pan.___", state 937, "else" + line 403, "pan.___", state 940, "(1)" + line 403, "pan.___", state 941, "(1)" + line 403, "pan.___", state 941, "(1)" + line 407, "pan.___", state 948, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, "pan.___", state 950, "(1)" + line 407, "pan.___", state 951, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 407, "pan.___", state 951, "else" + line 407, "pan.___", state 954, "(1)" + line 407, "pan.___", state 955, "(1)" + line 407, "pan.___", state 955, "(1)" + line 405, "pan.___", state 960, "((i<2))" + line 405, "pan.___", state 960, "((i>=2))" + line 411, "pan.___", state 967, "(1)" + line 411, "pan.___", state 968, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 411, "pan.___", state 968, "else" + line 411, "pan.___", state 971, "(1)" + line 411, "pan.___", state 972, "(1)" + line 411, "pan.___", state 972, "(1)" + line 415, "pan.___", state 980, "(1)" + line 415, "pan.___", state 981, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 415, "pan.___", state 981, "else" + line 415, "pan.___", state 984, "(1)" + line 415, "pan.___", state 985, "(1)" + line 415, "pan.___", state 985, "(1)" + line 413, "pan.___", state 990, "((i<1))" + line 413, "pan.___", state 990, "((i>=1))" + line 420, "pan.___", state 997, "(1)" + line 420, "pan.___", state 998, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 420, "pan.___", state 998, "else" + line 420, "pan.___", state 1001, "(1)" + line 420, "pan.___", state 1002, "(1)" + line 420, "pan.___", state 1002, "(1)" + line 424, "pan.___", state 1010, "(1)" + line 424, "pan.___", state 1011, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 424, "pan.___", state 1011, "else" + line 424, "pan.___", state 1014, "(1)" + line 424, "pan.___", state 1015, "(1)" + line 424, "pan.___", state 1015, "(1)" + line 422, "pan.___", state 1020, "((i<2))" + line 422, "pan.___", state 1020, "((i>=2))" + line 429, "pan.___", state 1024, "(1)" + line 429, "pan.___", state 1024, "(1)" + line 583, "pan.___", state 1028, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 394, "pan.___", state 1033, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 1047, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1065, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 1079, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 1098, "(1)" + line 415, "pan.___", state 1111, "(1)" + line 420, "pan.___", state 1128, "(1)" + line 424, "pan.___", state 1141, "(1)" + line 394, "pan.___", state 1165, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1197, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 1211, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 1230, "(1)" + line 420, "pan.___", state 1260, "(1)" + line 424, "pan.___", state 1273, "(1)" + line 394, "pan.___", state 1298, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1330, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 1344, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 1363, "(1)" + line 420, "pan.___", state 1393, "(1)" + line 424, "pan.___", state 1406, "(1)" + line 394, "pan.___", state 1427, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1459, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 1473, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 1492, "(1)" + line 420, "pan.___", state 1522, "(1)" + line 424, "pan.___", state 1535, "(1)" + line 249, "pan.___", state 1558, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 1580, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1589, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 1605, "(1)" + line 230, "pan.___", state 1613, "(1)" + line 234, "pan.___", state 1625, "(1)" + line 238, "pan.___", state 1633, "(1)" + line 394, "pan.___", state 1651, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 1665, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1683, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 1697, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 1716, "(1)" + line 415, "pan.___", state 1729, "(1)" + line 420, "pan.___", state 1746, "(1)" + line 424, "pan.___", state 1759, "(1)" + line 394, "pan.___", state 1780, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 1794, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 1812, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 1826, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 1845, "(1)" + line 415, "pan.___", state 1858, "(1)" + line 420, "pan.___", state 1875, "(1)" + line 424, "pan.___", state 1888, "(1)" + line 394, "pan.___", state 1912, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 1928, "(1)" + line 403, "pan.___", state 1944, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 1958, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 1977, "(1)" + line 420, "pan.___", state 2007, "(1)" + line 424, "pan.___", state 2020, "(1)" + line 622, "pan.___", state 2041, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 394, "pan.___", state 2048, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 2080, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 2094, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 2113, "(1)" + line 420, "pan.___", state 2143, "(1)" + line 424, "pan.___", state 2156, "(1)" + line 394, "pan.___", state 2177, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 2209, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 2223, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 2242, "(1)" + line 420, "pan.___", state 2272, "(1)" + line 424, "pan.___", state 2285, "(1)" + line 394, "pan.___", state 2308, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 394, "pan.___", state 2310, "(1)" + line 394, "pan.___", state 2311, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 394, "pan.___", state 2311, "else" + line 394, "pan.___", state 2314, "(1)" + line 398, "pan.___", state 2322, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 2324, "(1)" + line 398, "pan.___", state 2325, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 398, "pan.___", state 2325, "else" + line 398, "pan.___", state 2328, "(1)" + line 398, "pan.___", state 2329, "(1)" + line 398, "pan.___", state 2329, "(1)" + line 396, "pan.___", state 2334, "((i<1))" + line 396, "pan.___", state 2334, "((i>=1))" + line 403, "pan.___", state 2340, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 2342, "(1)" + line 403, "pan.___", state 2343, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 403, "pan.___", state 2343, "else" + line 403, "pan.___", state 2346, "(1)" + line 403, "pan.___", state 2347, "(1)" + line 403, "pan.___", state 2347, "(1)" + line 407, "pan.___", state 2354, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 407, "pan.___", state 2356, "(1)" + line 407, "pan.___", state 2357, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 407, "pan.___", state 2357, "else" + line 407, "pan.___", state 2360, "(1)" + line 407, "pan.___", state 2361, "(1)" + line 407, "pan.___", state 2361, "(1)" + line 405, "pan.___", state 2366, "((i<2))" + line 405, "pan.___", state 2366, "((i>=2))" + line 411, "pan.___", state 2373, "(1)" + line 411, "pan.___", state 2374, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 411, "pan.___", state 2374, "else" + line 411, "pan.___", state 2377, "(1)" + line 411, "pan.___", state 2378, "(1)" + line 411, "pan.___", state 2378, "(1)" + line 415, "pan.___", state 2386, "(1)" + line 415, "pan.___", state 2387, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 415, "pan.___", state 2387, "else" + line 415, "pan.___", state 2390, "(1)" + line 415, "pan.___", state 2391, "(1)" + line 415, "pan.___", state 2391, "(1)" + line 413, "pan.___", state 2396, "((i<1))" + line 413, "pan.___", state 2396, "((i>=1))" + line 420, "pan.___", state 2403, "(1)" + line 420, "pan.___", state 2404, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 420, "pan.___", state 2404, "else" + line 420, "pan.___", state 2407, "(1)" + line 420, "pan.___", state 2408, "(1)" + line 420, "pan.___", state 2408, "(1)" + line 424, "pan.___", state 2416, "(1)" + line 424, "pan.___", state 2417, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 424, "pan.___", state 2417, "else" + line 424, "pan.___", state 2420, "(1)" + line 424, "pan.___", state 2421, "(1)" + line 424, "pan.___", state 2421, "(1)" + line 422, "pan.___", state 2426, "((i<2))" + line 422, "pan.___", state 2426, "((i>=2))" + line 429, "pan.___", state 2430, "(1)" + line 429, "pan.___", state 2430, "(1)" + line 622, "pan.___", state 2433, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 622, "pan.___", state 2434, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 622, "pan.___", state 2435, "(1)" + line 249, "pan.___", state 2439, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 2450, "(1)" + line 257, "pan.___", state 2461, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 2470, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 2486, "(1)" + line 230, "pan.___", state 2494, "(1)" + line 234, "pan.___", state 2506, "(1)" + line 238, "pan.___", state 2514, "(1)" + line 394, "pan.___", state 2532, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 2546, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 2564, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 2578, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 2597, "(1)" + line 415, "pan.___", state 2610, "(1)" + line 420, "pan.___", state 2627, "(1)" + line 424, "pan.___", state 2640, "(1)" + line 249, "pan.___", state 2664, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 2673, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 2686, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 2695, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 2711, "(1)" + line 230, "pan.___", state 2719, "(1)" + line 234, "pan.___", state 2731, "(1)" + line 238, "pan.___", state 2739, "(1)" + line 394, "pan.___", state 2757, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 2771, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 2789, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 2803, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 2822, "(1)" + line 415, "pan.___", state 2835, "(1)" + line 420, "pan.___", state 2852, "(1)" + line 424, "pan.___", state 2865, "(1)" + line 394, "pan.___", state 2886, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 2900, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 2918, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 2932, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 2951, "(1)" + line 415, "pan.___", state 2964, "(1)" + line 420, "pan.___", state 2981, "(1)" + line 424, "pan.___", state 2994, "(1)" + line 226, "pan.___", state 3027, "(1)" + line 234, "pan.___", state 3047, "(1)" + line 238, "pan.___", state 3055, "(1)" + line 226, "pan.___", state 3070, "(1)" + line 230, "pan.___", state 3078, "(1)" + line 234, "pan.___", state 3090, "(1)" + line 238, "pan.___", state 3098, "(1)" + line 876, "pan.___", state 3115, "-end-" + (318 of 3115 states) +unreached in proctype urcu_writer + line 394, "pan.___", state 18, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 32, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 50, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 411, "pan.___", state 83, "(1)" + line 415, "pan.___", state 96, "(1)" + line 420, "pan.___", state 113, "(1)" + line 249, "pan.___", state 149, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 158, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 171, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 394, "pan.___", state 211, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 398, "pan.___", state 225, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 243, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 257, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 411, "pan.___", state 276, "(1)" + line 415, "pan.___", state 289, "(1)" + line 420, "pan.___", state 306, "(1)" + line 424, "pan.___", state 319, "(1)" + line 398, "pan.___", state 356, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 374, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 388, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 415, "pan.___", state 420, "(1)" + line 420, "pan.___", state 437, "(1)" + line 424, "pan.___", state 450, "(1)" + line 398, "pan.___", state 494, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 512, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 526, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 415, "pan.___", state 558, "(1)" + line 420, "pan.___", state 575, "(1)" + line 424, "pan.___", state 588, "(1)" + line 398, "pan.___", state 623, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 641, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 655, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 415, "pan.___", state 687, "(1)" + line 420, "pan.___", state 704, "(1)" + line 424, "pan.___", state 717, "(1)" + line 398, "pan.___", state 754, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 403, "pan.___", state 772, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 407, "pan.___", state 786, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 415, "pan.___", state 818, "(1)" + line 420, "pan.___", state 835, "(1)" + line 424, "pan.___", state 848, "(1)" + line 249, "pan.___", state 903, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 912, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 927, "(1)" + line 261, "pan.___", state 934, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 950, "(1)" + line 230, "pan.___", state 958, "(1)" + line 234, "pan.___", state 970, "(1)" + line 238, "pan.___", state 978, "(1)" + line 253, "pan.___", state 1003, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 1016, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1025, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 1041, "(1)" + line 230, "pan.___", state 1049, "(1)" + line 234, "pan.___", state 1061, "(1)" + line 238, "pan.___", state 1069, "(1)" + line 253, "pan.___", state 1094, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 1107, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1116, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 1132, "(1)" + line 230, "pan.___", state 1140, "(1)" + line 234, "pan.___", state 1152, "(1)" + line 238, "pan.___", state 1160, "(1)" + line 253, "pan.___", state 1185, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 257, "pan.___", state 1198, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1207, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 226, "pan.___", state 1223, "(1)" + line 230, "pan.___", state 1231, "(1)" + line 234, "pan.___", state 1243, "(1)" + line 238, "pan.___", state 1251, "(1)" + line 1203, "pan.___", state 1266, "-end-" + (71 of 1266 states) +unreached in proctype :init: + (0 of 78 states) +unreached in proctype :never: + line 1262, "pan.___", state 8, "-end-" + (1 of 8 states) + +pan: elapsed time 1.16e+03 seconds +pan: rate 1618.1151 states/second +pan: avg transition delay 1.2841e-06 usec +cp .input.spin urcu_free.spin.input +cp .input.spin.trail urcu_free.spin.input.trail diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free.ltl b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free.ltl new file mode 100644 index 0000000..6be1be9 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free.ltl @@ -0,0 +1 @@ +[] (!read_poison) diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free.spin.input b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free.spin.input new file mode 100644 index 0000000..542625d --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free.spin.input @@ -0,0 +1,1239 @@ + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +//#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_nested.define b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_nested.define new file mode 100644 index 0000000..0fb59bd --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_nested.define @@ -0,0 +1 @@ +#define READER_NEST_LEVEL 2 diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_mb.define b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_mb.define new file mode 100644 index 0000000..d99d793 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_mb.define @@ -0,0 +1 @@ +#define NO_MB diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_mb.log b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_mb.log new file mode 100644 index 0000000..b27c022 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_mb.log @@ -0,0 +1,884 @@ +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define >> pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_free.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_free_no_mb.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1258) +Depth= 11321 States= 1e+06 Transitions= 3.42e+08 Memory= 550.432 t= 421 R= 2e+03 +pan: claim violated! (at depth 1224) +pan: wrote .input.spin.trail + +(Spin Version 5.1.7 -- 23 December 2008) +Warning: Search not completed + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness disabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 11321, errors: 1 + 1661452 states, stored +5.1024872e+08 states, matched +5.1191017e+08 transitions (= stored+matched) +2.8514789e+09 atomic steps +hash conflicts: 2.0792287e+08 (resolved) + +Stats on memory usage (in Megabytes): + 183.800 equivalent memory usage for states (stored*(State-vector + overhead)) + 140.372 actual memory usage for states (compression: 76.37%) + state-vector as stored = 61 byte + 28 byte overhead + 8.000 memory used for hash table (-w20) + 457.764 memory used for DFS stack (-m10000000) + 605.998 total actual memory usage + +unreached in proctype urcu_reader + line 395, "pan.___", state 21, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 53, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 67, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 86, "(1)" + line 421, "pan.___", state 116, "(1)" + line 425, "pan.___", state 129, "(1)" + line 582, "pan.___", state 150, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 395, "pan.___", state 157, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 189, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 203, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 222, "(1)" + line 421, "pan.___", state 252, "(1)" + line 425, "pan.___", state 265, "(1)" + line 395, "pan.___", state 286, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 318, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 332, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 351, "(1)" + line 421, "pan.___", state 381, "(1)" + line 425, "pan.___", state 394, "(1)" + line 395, "pan.___", state 417, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 419, "(1)" + line 395, "pan.___", state 420, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 420, "else" + line 395, "pan.___", state 423, "(1)" + line 399, "pan.___", state 431, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 433, "(1)" + line 399, "pan.___", state 434, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 434, "else" + line 399, "pan.___", state 437, "(1)" + line 399, "pan.___", state 438, "(1)" + line 399, "pan.___", state 438, "(1)" + line 397, "pan.___", state 443, "((i<1))" + line 397, "pan.___", state 443, "((i>=1))" + line 404, "pan.___", state 449, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 451, "(1)" + line 404, "pan.___", state 452, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 452, "else" + line 404, "pan.___", state 455, "(1)" + line 404, "pan.___", state 456, "(1)" + line 404, "pan.___", state 456, "(1)" + line 408, "pan.___", state 463, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 465, "(1)" + line 408, "pan.___", state 466, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 466, "else" + line 408, "pan.___", state 469, "(1)" + line 408, "pan.___", state 470, "(1)" + line 408, "pan.___", state 470, "(1)" + line 406, "pan.___", state 475, "((i<2))" + line 406, "pan.___", state 475, "((i>=2))" + line 412, "pan.___", state 482, "(1)" + line 412, "pan.___", state 483, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 483, "else" + line 412, "pan.___", state 486, "(1)" + line 412, "pan.___", state 487, "(1)" + line 412, "pan.___", state 487, "(1)" + line 416, "pan.___", state 495, "(1)" + line 416, "pan.___", state 496, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 496, "else" + line 416, "pan.___", state 499, "(1)" + line 416, "pan.___", state 500, "(1)" + line 416, "pan.___", state 500, "(1)" + line 414, "pan.___", state 505, "((i<1))" + line 414, "pan.___", state 505, "((i>=1))" + line 421, "pan.___", state 512, "(1)" + line 421, "pan.___", state 513, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 513, "else" + line 421, "pan.___", state 516, "(1)" + line 421, "pan.___", state 517, "(1)" + line 421, "pan.___", state 517, "(1)" + line 425, "pan.___", state 525, "(1)" + line 425, "pan.___", state 526, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 526, "else" + line 425, "pan.___", state 529, "(1)" + line 425, "pan.___", state 530, "(1)" + line 425, "pan.___", state 530, "(1)" + line 423, "pan.___", state 535, "((i<2))" + line 423, "pan.___", state 535, "((i>=2))" + line 430, "pan.___", state 539, "(1)" + line 430, "pan.___", state 539, "(1)" + line 582, "pan.___", state 542, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 582, "pan.___", state 543, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 582, "pan.___", state 544, "(1)" + line 250, "pan.___", state 548, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 550, "(1)" + line 254, "pan.___", state 557, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 559, "(1)" + line 254, "pan.___", state 560, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 560, "else" + line 252, "pan.___", state 565, "((i<1))" + line 252, "pan.___", state 565, "((i>=1))" + line 258, "pan.___", state 570, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 572, "(1)" + line 258, "pan.___", state 573, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 573, "else" + line 262, "pan.___", state 579, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 581, "(1)" + line 262, "pan.___", state 582, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 582, "else" + line 260, "pan.___", state 587, "((i<2))" + line 260, "pan.___", state 587, "((i>=2))" + line 227, "pan.___", state 595, "(1)" + line 231, "pan.___", state 603, "(1)" + line 231, "pan.___", state 604, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 604, "else" + line 229, "pan.___", state 609, "((i<1))" + line 229, "pan.___", state 609, "((i>=1))" + line 235, "pan.___", state 615, "(1)" + line 235, "pan.___", state 616, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 616, "else" + line 239, "pan.___", state 623, "(1)" + line 239, "pan.___", state 624, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 624, "else" + line 244, "pan.___", state 633, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 633, "else" + line 277, "pan.___", state 635, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 635, "else" + line 395, "pan.___", state 641, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 673, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 687, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 706, "(1)" + line 421, "pan.___", state 736, "(1)" + line 425, "pan.___", state 749, "(1)" + line 395, "pan.___", state 777, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 779, "(1)" + line 395, "pan.___", state 780, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 780, "else" + line 395, "pan.___", state 783, "(1)" + line 399, "pan.___", state 791, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 793, "(1)" + line 399, "pan.___", state 794, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 794, "else" + line 399, "pan.___", state 797, "(1)" + line 399, "pan.___", state 798, "(1)" + line 399, "pan.___", state 798, "(1)" + line 397, "pan.___", state 803, "((i<1))" + line 397, "pan.___", state 803, "((i>=1))" + line 404, "pan.___", state 809, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 811, "(1)" + line 404, "pan.___", state 812, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 812, "else" + line 404, "pan.___", state 815, "(1)" + line 404, "pan.___", state 816, "(1)" + line 404, "pan.___", state 816, "(1)" + line 408, "pan.___", state 823, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 825, "(1)" + line 408, "pan.___", state 826, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 826, "else" + line 408, "pan.___", state 829, "(1)" + line 408, "pan.___", state 830, "(1)" + line 408, "pan.___", state 830, "(1)" + line 406, "pan.___", state 835, "((i<2))" + line 406, "pan.___", state 835, "((i>=2))" + line 412, "pan.___", state 842, "(1)" + line 412, "pan.___", state 843, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 843, "else" + line 412, "pan.___", state 846, "(1)" + line 412, "pan.___", state 847, "(1)" + line 412, "pan.___", state 847, "(1)" + line 416, "pan.___", state 855, "(1)" + line 416, "pan.___", state 856, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 856, "else" + line 416, "pan.___", state 859, "(1)" + line 416, "pan.___", state 860, "(1)" + line 416, "pan.___", state 860, "(1)" + line 414, "pan.___", state 865, "((i<1))" + line 414, "pan.___", state 865, "((i>=1))" + line 421, "pan.___", state 872, "(1)" + line 421, "pan.___", state 873, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 873, "else" + line 421, "pan.___", state 876, "(1)" + line 421, "pan.___", state 877, "(1)" + line 421, "pan.___", state 877, "(1)" + line 425, "pan.___", state 885, "(1)" + line 425, "pan.___", state 886, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 886, "else" + line 425, "pan.___", state 889, "(1)" + line 425, "pan.___", state 890, "(1)" + line 425, "pan.___", state 890, "(1)" + line 430, "pan.___", state 899, "(1)" + line 430, "pan.___", state 899, "(1)" + line 395, "pan.___", state 906, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 908, "(1)" + line 395, "pan.___", state 909, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 909, "else" + line 395, "pan.___", state 912, "(1)" + line 399, "pan.___", state 920, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 922, "(1)" + line 399, "pan.___", state 923, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 923, "else" + line 399, "pan.___", state 926, "(1)" + line 399, "pan.___", state 927, "(1)" + line 399, "pan.___", state 927, "(1)" + line 397, "pan.___", state 932, "((i<1))" + line 397, "pan.___", state 932, "((i>=1))" + line 404, "pan.___", state 938, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 940, "(1)" + line 404, "pan.___", state 941, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 941, "else" + line 404, "pan.___", state 944, "(1)" + line 404, "pan.___", state 945, "(1)" + line 404, "pan.___", state 945, "(1)" + line 408, "pan.___", state 952, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 954, "(1)" + line 408, "pan.___", state 955, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 955, "else" + line 408, "pan.___", state 958, "(1)" + line 408, "pan.___", state 959, "(1)" + line 408, "pan.___", state 959, "(1)" + line 406, "pan.___", state 964, "((i<2))" + line 406, "pan.___", state 964, "((i>=2))" + line 412, "pan.___", state 971, "(1)" + line 412, "pan.___", state 972, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 972, "else" + line 412, "pan.___", state 975, "(1)" + line 412, "pan.___", state 976, "(1)" + line 412, "pan.___", state 976, "(1)" + line 416, "pan.___", state 984, "(1)" + line 416, "pan.___", state 985, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 985, "else" + line 416, "pan.___", state 988, "(1)" + line 416, "pan.___", state 989, "(1)" + line 416, "pan.___", state 989, "(1)" + line 414, "pan.___", state 994, "((i<1))" + line 414, "pan.___", state 994, "((i>=1))" + line 421, "pan.___", state 1001, "(1)" + line 421, "pan.___", state 1002, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 1002, "else" + line 421, "pan.___", state 1005, "(1)" + line 421, "pan.___", state 1006, "(1)" + line 421, "pan.___", state 1006, "(1)" + line 425, "pan.___", state 1014, "(1)" + line 425, "pan.___", state 1015, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 1015, "else" + line 425, "pan.___", state 1018, "(1)" + line 425, "pan.___", state 1019, "(1)" + line 425, "pan.___", state 1019, "(1)" + line 423, "pan.___", state 1024, "((i<2))" + line 423, "pan.___", state 1024, "((i>=2))" + line 430, "pan.___", state 1028, "(1)" + line 430, "pan.___", state 1028, "(1)" + line 590, "pan.___", state 1032, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 395, "pan.___", state 1037, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1069, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1083, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1102, "(1)" + line 421, "pan.___", state 1132, "(1)" + line 425, "pan.___", state 1145, "(1)" + line 395, "pan.___", state 1169, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1201, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1215, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1234, "(1)" + line 421, "pan.___", state 1264, "(1)" + line 425, "pan.___", state 1277, "(1)" + line 395, "pan.___", state 1302, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1334, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1348, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1367, "(1)" + line 421, "pan.___", state 1397, "(1)" + line 425, "pan.___", state 1410, "(1)" + line 395, "pan.___", state 1431, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1463, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1477, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1496, "(1)" + line 421, "pan.___", state 1526, "(1)" + line 425, "pan.___", state 1539, "(1)" + line 250, "pan.___", state 1562, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1564, "(1)" + line 254, "pan.___", state 1571, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1573, "(1)" + line 254, "pan.___", state 1574, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1574, "else" + line 252, "pan.___", state 1579, "((i<1))" + line 252, "pan.___", state 1579, "((i>=1))" + line 258, "pan.___", state 1584, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1586, "(1)" + line 258, "pan.___", state 1587, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1587, "else" + line 262, "pan.___", state 1593, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1595, "(1)" + line 262, "pan.___", state 1596, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1596, "else" + line 260, "pan.___", state 1601, "((i<2))" + line 260, "pan.___", state 1601, "((i>=2))" + line 227, "pan.___", state 1609, "(1)" + line 231, "pan.___", state 1617, "(1)" + line 231, "pan.___", state 1618, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1618, "else" + line 229, "pan.___", state 1623, "((i<1))" + line 229, "pan.___", state 1623, "((i>=1))" + line 235, "pan.___", state 1629, "(1)" + line 235, "pan.___", state 1630, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1630, "else" + line 239, "pan.___", state 1637, "(1)" + line 239, "pan.___", state 1638, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1638, "else" + line 244, "pan.___", state 1647, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1647, "else" + line 277, "pan.___", state 1649, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 1649, "else" + line 395, "pan.___", state 1655, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1687, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1701, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1720, "(1)" + line 421, "pan.___", state 1750, "(1)" + line 425, "pan.___", state 1763, "(1)" + line 395, "pan.___", state 1784, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1816, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1830, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1849, "(1)" + line 421, "pan.___", state 1879, "(1)" + line 425, "pan.___", state 1892, "(1)" + line 395, "pan.___", state 1916, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1948, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1962, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1981, "(1)" + line 421, "pan.___", state 2011, "(1)" + line 425, "pan.___", state 2024, "(1)" + line 629, "pan.___", state 2045, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 395, "pan.___", state 2052, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2084, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2098, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2117, "(1)" + line 421, "pan.___", state 2147, "(1)" + line 425, "pan.___", state 2160, "(1)" + line 395, "pan.___", state 2181, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2213, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2227, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2246, "(1)" + line 421, "pan.___", state 2276, "(1)" + line 425, "pan.___", state 2289, "(1)" + line 395, "pan.___", state 2312, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 2314, "(1)" + line 395, "pan.___", state 2315, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 2315, "else" + line 395, "pan.___", state 2318, "(1)" + line 399, "pan.___", state 2326, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2328, "(1)" + line 399, "pan.___", state 2329, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 2329, "else" + line 399, "pan.___", state 2332, "(1)" + line 399, "pan.___", state 2333, "(1)" + line 399, "pan.___", state 2333, "(1)" + line 397, "pan.___", state 2338, "((i<1))" + line 397, "pan.___", state 2338, "((i>=1))" + line 404, "pan.___", state 2344, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2346, "(1)" + line 404, "pan.___", state 2347, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 2347, "else" + line 404, "pan.___", state 2350, "(1)" + line 404, "pan.___", state 2351, "(1)" + line 404, "pan.___", state 2351, "(1)" + line 408, "pan.___", state 2358, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2360, "(1)" + line 408, "pan.___", state 2361, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 2361, "else" + line 408, "pan.___", state 2364, "(1)" + line 408, "pan.___", state 2365, "(1)" + line 408, "pan.___", state 2365, "(1)" + line 406, "pan.___", state 2370, "((i<2))" + line 406, "pan.___", state 2370, "((i>=2))" + line 412, "pan.___", state 2377, "(1)" + line 412, "pan.___", state 2378, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 2378, "else" + line 412, "pan.___", state 2381, "(1)" + line 412, "pan.___", state 2382, "(1)" + line 412, "pan.___", state 2382, "(1)" + line 416, "pan.___", state 2390, "(1)" + line 416, "pan.___", state 2391, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 2391, "else" + line 416, "pan.___", state 2394, "(1)" + line 416, "pan.___", state 2395, "(1)" + line 416, "pan.___", state 2395, "(1)" + line 414, "pan.___", state 2400, "((i<1))" + line 414, "pan.___", state 2400, "((i>=1))" + line 421, "pan.___", state 2407, "(1)" + line 421, "pan.___", state 2408, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 2408, "else" + line 421, "pan.___", state 2411, "(1)" + line 421, "pan.___", state 2412, "(1)" + line 421, "pan.___", state 2412, "(1)" + line 425, "pan.___", state 2420, "(1)" + line 425, "pan.___", state 2421, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 2421, "else" + line 425, "pan.___", state 2424, "(1)" + line 425, "pan.___", state 2425, "(1)" + line 425, "pan.___", state 2425, "(1)" + line 423, "pan.___", state 2430, "((i<2))" + line 423, "pan.___", state 2430, "((i>=2))" + line 430, "pan.___", state 2434, "(1)" + line 430, "pan.___", state 2434, "(1)" + line 629, "pan.___", state 2437, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 629, "pan.___", state 2438, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 629, "pan.___", state 2439, "(1)" + line 250, "pan.___", state 2443, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 2445, "(1)" + line 254, "pan.___", state 2452, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 2454, "(1)" + line 254, "pan.___", state 2455, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 2455, "else" + line 252, "pan.___", state 2460, "((i<1))" + line 252, "pan.___", state 2460, "((i>=1))" + line 258, "pan.___", state 2465, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 2467, "(1)" + line 258, "pan.___", state 2468, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 2468, "else" + line 262, "pan.___", state 2474, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 2476, "(1)" + line 262, "pan.___", state 2477, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 2477, "else" + line 260, "pan.___", state 2482, "((i<2))" + line 260, "pan.___", state 2482, "((i>=2))" + line 227, "pan.___", state 2490, "(1)" + line 231, "pan.___", state 2498, "(1)" + line 231, "pan.___", state 2499, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 2499, "else" + line 229, "pan.___", state 2504, "((i<1))" + line 229, "pan.___", state 2504, "((i>=1))" + line 235, "pan.___", state 2510, "(1)" + line 235, "pan.___", state 2511, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 2511, "else" + line 239, "pan.___", state 2518, "(1)" + line 239, "pan.___", state 2519, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 2519, "else" + line 244, "pan.___", state 2528, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 2528, "else" + line 277, "pan.___", state 2530, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 2530, "else" + line 395, "pan.___", state 2536, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2568, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2582, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2601, "(1)" + line 421, "pan.___", state 2631, "(1)" + line 425, "pan.___", state 2644, "(1)" + line 250, "pan.___", state 2668, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 2670, "(1)" + line 254, "pan.___", state 2677, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 2679, "(1)" + line 254, "pan.___", state 2680, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 2680, "else" + line 252, "pan.___", state 2685, "((i<1))" + line 252, "pan.___", state 2685, "((i>=1))" + line 258, "pan.___", state 2690, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 2692, "(1)" + line 258, "pan.___", state 2693, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 2693, "else" + line 262, "pan.___", state 2699, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 2701, "(1)" + line 262, "pan.___", state 2702, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 2702, "else" + line 260, "pan.___", state 2707, "((i<2))" + line 260, "pan.___", state 2707, "((i>=2))" + line 227, "pan.___", state 2715, "(1)" + line 231, "pan.___", state 2723, "(1)" + line 231, "pan.___", state 2724, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 2724, "else" + line 229, "pan.___", state 2729, "((i<1))" + line 229, "pan.___", state 2729, "((i>=1))" + line 235, "pan.___", state 2735, "(1)" + line 235, "pan.___", state 2736, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 2736, "else" + line 239, "pan.___", state 2743, "(1)" + line 239, "pan.___", state 2744, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 2744, "else" + line 244, "pan.___", state 2753, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 2753, "else" + line 277, "pan.___", state 2755, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 2755, "else" + line 395, "pan.___", state 2761, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2793, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2807, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2826, "(1)" + line 421, "pan.___", state 2856, "(1)" + line 425, "pan.___", state 2869, "(1)" + line 395, "pan.___", state 2890, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2922, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2936, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2955, "(1)" + line 421, "pan.___", state 2985, "(1)" + line 425, "pan.___", state 2998, "(1)" + line 227, "pan.___", state 3031, "(1)" + line 235, "pan.___", state 3051, "(1)" + line 239, "pan.___", state 3059, "(1)" + line 227, "pan.___", state 3074, "(1)" + line 235, "pan.___", state 3094, "(1)" + line 239, "pan.___", state 3102, "(1)" + line 877, "pan.___", state 3119, "-end-" + (363 of 3119 states) +unreached in proctype urcu_writer + line 395, "pan.___", state 20, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 26, "(1)" + line 399, "pan.___", state 34, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 40, "(1)" + line 399, "pan.___", state 41, "(1)" + line 399, "pan.___", state 41, "(1)" + line 397, "pan.___", state 46, "((i<1))" + line 397, "pan.___", state 46, "((i>=1))" + line 404, "pan.___", state 52, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 58, "(1)" + line 404, "pan.___", state 59, "(1)" + line 404, "pan.___", state 59, "(1)" + line 408, "pan.___", state 72, "(1)" + line 408, "pan.___", state 73, "(1)" + line 408, "pan.___", state 73, "(1)" + line 406, "pan.___", state 78, "((i<2))" + line 406, "pan.___", state 78, "((i>=2))" + line 412, "pan.___", state 85, "(1)" + line 412, "pan.___", state 86, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 86, "else" + line 412, "pan.___", state 89, "(1)" + line 412, "pan.___", state 90, "(1)" + line 412, "pan.___", state 90, "(1)" + line 416, "pan.___", state 98, "(1)" + line 416, "pan.___", state 99, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 99, "else" + line 416, "pan.___", state 102, "(1)" + line 416, "pan.___", state 103, "(1)" + line 416, "pan.___", state 103, "(1)" + line 414, "pan.___", state 108, "((i<1))" + line 414, "pan.___", state 108, "((i>=1))" + line 421, "pan.___", state 115, "(1)" + line 421, "pan.___", state 116, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 116, "else" + line 421, "pan.___", state 119, "(1)" + line 421, "pan.___", state 120, "(1)" + line 421, "pan.___", state 120, "(1)" + line 425, "pan.___", state 128, "(1)" + line 425, "pan.___", state 129, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 129, "else" + line 425, "pan.___", state 132, "(1)" + line 425, "pan.___", state 133, "(1)" + line 425, "pan.___", state 133, "(1)" + line 423, "pan.___", state 138, "((i<2))" + line 423, "pan.___", state 138, "((i>=2))" + line 430, "pan.___", state 142, "(1)" + line 430, "pan.___", state 142, "(1)" + line 250, "pan.___", state 151, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 160, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 252, "pan.___", state 168, "((i<1))" + line 252, "pan.___", state 168, "((i>=1))" + line 258, "pan.___", state 173, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 1000, "pan.___", state 201, "old_data = cached_rcu_ptr.val[_pid]" + line 1011, "pan.___", state 205, "_proc_urcu_writer = (_proc_urcu_writer|(1<<4))" + line 395, "pan.___", state 213, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 219, "(1)" + line 399, "pan.___", state 227, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 233, "(1)" + line 399, "pan.___", state 234, "(1)" + line 399, "pan.___", state 234, "(1)" + line 397, "pan.___", state 239, "((i<1))" + line 397, "pan.___", state 239, "((i>=1))" + line 404, "pan.___", state 247, "(1)" + line 404, "pan.___", state 248, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 248, "else" + line 404, "pan.___", state 251, "(1)" + line 404, "pan.___", state 252, "(1)" + line 404, "pan.___", state 252, "(1)" + line 408, "pan.___", state 259, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 265, "(1)" + line 408, "pan.___", state 266, "(1)" + line 408, "pan.___", state 266, "(1)" + line 406, "pan.___", state 271, "((i<2))" + line 406, "pan.___", state 271, "((i>=2))" + line 412, "pan.___", state 278, "(1)" + line 412, "pan.___", state 279, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 279, "else" + line 412, "pan.___", state 282, "(1)" + line 412, "pan.___", state 283, "(1)" + line 412, "pan.___", state 283, "(1)" + line 416, "pan.___", state 291, "(1)" + line 416, "pan.___", state 292, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 292, "else" + line 416, "pan.___", state 295, "(1)" + line 416, "pan.___", state 296, "(1)" + line 416, "pan.___", state 296, "(1)" + line 414, "pan.___", state 301, "((i<1))" + line 414, "pan.___", state 301, "((i>=1))" + line 421, "pan.___", state 308, "(1)" + line 421, "pan.___", state 309, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 309, "else" + line 421, "pan.___", state 312, "(1)" + line 421, "pan.___", state 313, "(1)" + line 421, "pan.___", state 313, "(1)" + line 425, "pan.___", state 321, "(1)" + line 425, "pan.___", state 322, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 322, "else" + line 425, "pan.___", state 325, "(1)" + line 425, "pan.___", state 326, "(1)" + line 425, "pan.___", state 326, "(1)" + line 423, "pan.___", state 331, "((i<2))" + line 423, "pan.___", state 331, "((i>=2))" + line 430, "pan.___", state 335, "(1)" + line 430, "pan.___", state 335, "(1)" + line 395, "pan.___", state 346, "(1)" + line 395, "pan.___", state 347, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 347, "else" + line 395, "pan.___", state 350, "(1)" + line 399, "pan.___", state 358, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 364, "(1)" + line 399, "pan.___", state 365, "(1)" + line 399, "pan.___", state 365, "(1)" + line 397, "pan.___", state 370, "((i<1))" + line 397, "pan.___", state 370, "((i>=1))" + line 404, "pan.___", state 376, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 382, "(1)" + line 404, "pan.___", state 383, "(1)" + line 404, "pan.___", state 383, "(1)" + line 408, "pan.___", state 390, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 396, "(1)" + line 408, "pan.___", state 397, "(1)" + line 408, "pan.___", state 397, "(1)" + line 406, "pan.___", state 402, "((i<2))" + line 406, "pan.___", state 402, "((i>=2))" + line 412, "pan.___", state 409, "(1)" + line 412, "pan.___", state 410, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 410, "else" + line 412, "pan.___", state 413, "(1)" + line 412, "pan.___", state 414, "(1)" + line 412, "pan.___", state 414, "(1)" + line 416, "pan.___", state 422, "(1)" + line 416, "pan.___", state 423, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 423, "else" + line 416, "pan.___", state 426, "(1)" + line 416, "pan.___", state 427, "(1)" + line 416, "pan.___", state 427, "(1)" + line 414, "pan.___", state 432, "((i<1))" + line 414, "pan.___", state 432, "((i>=1))" + line 421, "pan.___", state 439, "(1)" + line 421, "pan.___", state 440, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 440, "else" + line 421, "pan.___", state 443, "(1)" + line 421, "pan.___", state 444, "(1)" + line 421, "pan.___", state 444, "(1)" + line 425, "pan.___", state 452, "(1)" + line 425, "pan.___", state 453, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 453, "else" + line 425, "pan.___", state 456, "(1)" + line 425, "pan.___", state 457, "(1)" + line 425, "pan.___", state 457, "(1)" + line 423, "pan.___", state 462, "((i<2))" + line 423, "pan.___", state 462, "((i>=2))" + line 430, "pan.___", state 466, "(1)" + line 430, "pan.___", state 466, "(1)" + line 1063, "pan.___", state 477, "_proc_urcu_writer = (_proc_urcu_writer&~(((1<<8)|(1<<7))))" + line 395, "pan.___", state 482, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 488, "(1)" + line 399, "pan.___", state 496, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 502, "(1)" + line 399, "pan.___", state 503, "(1)" + line 399, "pan.___", state 503, "(1)" + line 397, "pan.___", state 508, "((i<1))" + line 397, "pan.___", state 508, "((i>=1))" + line 404, "pan.___", state 514, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 520, "(1)" + line 404, "pan.___", state 521, "(1)" + line 404, "pan.___", state 521, "(1)" + line 408, "pan.___", state 528, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 534, "(1)" + line 408, "pan.___", state 535, "(1)" + line 408, "pan.___", state 535, "(1)" + line 406, "pan.___", state 540, "((i<2))" + line 406, "pan.___", state 540, "((i>=2))" + line 412, "pan.___", state 547, "(1)" + line 412, "pan.___", state 548, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 548, "else" + line 412, "pan.___", state 551, "(1)" + line 412, "pan.___", state 552, "(1)" + line 412, "pan.___", state 552, "(1)" + line 416, "pan.___", state 560, "(1)" + line 416, "pan.___", state 561, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 561, "else" + line 416, "pan.___", state 564, "(1)" + line 416, "pan.___", state 565, "(1)" + line 416, "pan.___", state 565, "(1)" + line 414, "pan.___", state 570, "((i<1))" + line 414, "pan.___", state 570, "((i>=1))" + line 421, "pan.___", state 577, "(1)" + line 421, "pan.___", state 578, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 578, "else" + line 421, "pan.___", state 581, "(1)" + line 421, "pan.___", state 582, "(1)" + line 421, "pan.___", state 582, "(1)" + line 425, "pan.___", state 590, "(1)" + line 425, "pan.___", state 591, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 591, "else" + line 425, "pan.___", state 594, "(1)" + line 425, "pan.___", state 595, "(1)" + line 425, "pan.___", state 595, "(1)" + line 430, "pan.___", state 604, "(1)" + line 430, "pan.___", state 604, "(1)" + line 395, "pan.___", state 611, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 625, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 643, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 412, "pan.___", state 676, "(1)" + line 416, "pan.___", state 689, "(1)" + line 421, "pan.___", state 706, "(1)" + line 425, "pan.___", state 719, "(1)" + line 399, "pan.___", state 756, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 774, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 788, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 820, "(1)" + line 421, "pan.___", state 837, "(1)" + line 425, "pan.___", state 850, "(1)" + line 1135, "pan.___", state 877, "_proc_urcu_writer = (_proc_urcu_writer|(1<<13))" + line 250, "pan.___", state 905, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 907, "(1)" + line 254, "pan.___", state 914, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 916, "(1)" + line 254, "pan.___", state 917, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 917, "else" + line 252, "pan.___", state 922, "((i<1))" + line 252, "pan.___", state 922, "((i>=1))" + line 258, "pan.___", state 927, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 929, "(1)" + line 258, "pan.___", state 930, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 930, "else" + line 262, "pan.___", state 936, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 938, "(1)" + line 262, "pan.___", state 939, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 939, "else" + line 260, "pan.___", state 944, "((i<2))" + line 260, "pan.___", state 944, "((i>=2))" + line 227, "pan.___", state 952, "(1)" + line 231, "pan.___", state 960, "(1)" + line 231, "pan.___", state 961, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 961, "else" + line 229, "pan.___", state 966, "((i<1))" + line 229, "pan.___", state 966, "((i>=1))" + line 235, "pan.___", state 972, "(1)" + line 235, "pan.___", state 973, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 973, "else" + line 239, "pan.___", state 980, "(1)" + line 239, "pan.___", state 981, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 981, "else" + line 244, "pan.___", state 990, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 990, "else" + line 277, "pan.___", state 992, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 992, "else" + line 250, "pan.___", state 996, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 998, "(1)" + line 254, "pan.___", state 1005, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1007, "(1)" + line 254, "pan.___", state 1008, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1008, "else" + line 252, "pan.___", state 1013, "((i<1))" + line 252, "pan.___", state 1013, "((i>=1))" + line 258, "pan.___", state 1018, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1020, "(1)" + line 258, "pan.___", state 1021, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1021, "else" + line 262, "pan.___", state 1027, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1029, "(1)" + line 262, "pan.___", state 1030, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1030, "else" + line 260, "pan.___", state 1035, "((i<2))" + line 260, "pan.___", state 1035, "((i>=2))" + line 227, "pan.___", state 1043, "(1)" + line 231, "pan.___", state 1051, "(1)" + line 231, "pan.___", state 1052, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1052, "else" + line 229, "pan.___", state 1057, "((i<1))" + line 229, "pan.___", state 1057, "((i>=1))" + line 235, "pan.___", state 1063, "(1)" + line 235, "pan.___", state 1064, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1064, "else" + line 239, "pan.___", state 1071, "(1)" + line 239, "pan.___", state 1072, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1072, "else" + line 244, "pan.___", state 1081, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1081, "else" + line 277, "pan.___", state 1083, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 1083, "else" + line 254, "pan.___", state 1096, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1109, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1118, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1134, "(1)" + line 231, "pan.___", state 1142, "(1)" + line 235, "pan.___", state 1154, "(1)" + line 239, "pan.___", state 1162, "(1)" + line 250, "pan.___", state 1178, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1180, "(1)" + line 254, "pan.___", state 1187, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1189, "(1)" + line 254, "pan.___", state 1190, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1190, "else" + line 252, "pan.___", state 1195, "((i<1))" + line 252, "pan.___", state 1195, "((i>=1))" + line 258, "pan.___", state 1200, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1202, "(1)" + line 258, "pan.___", state 1203, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1203, "else" + line 262, "pan.___", state 1209, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1211, "(1)" + line 262, "pan.___", state 1212, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1212, "else" + line 260, "pan.___", state 1217, "((i<2))" + line 260, "pan.___", state 1217, "((i>=2))" + line 227, "pan.___", state 1225, "(1)" + line 231, "pan.___", state 1233, "(1)" + line 231, "pan.___", state 1234, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1234, "else" + line 229, "pan.___", state 1239, "((i<1))" + line 229, "pan.___", state 1239, "((i>=1))" + line 235, "pan.___", state 1245, "(1)" + line 235, "pan.___", state 1246, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1246, "else" + line 239, "pan.___", state 1253, "(1)" + line 239, "pan.___", state 1254, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1254, "else" + line 244, "pan.___", state 1263, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1263, "else" + line 277, "pan.___", state 1265, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 1265, "else" + line 1204, "pan.___", state 1268, "-end-" + (226 of 1268 states) +unreached in proctype :init: + line 1215, "pan.___", state 9, "((j<2))" + line 1215, "pan.___", state 9, "((j>=2))" + line 1216, "pan.___", state 20, "((j<2))" + line 1216, "pan.___", state 20, "((j>=2))" + line 1221, "pan.___", state 33, "((j<2))" + line 1221, "pan.___", state 33, "((j>=2))" + line 1219, "pan.___", state 43, "((i<1))" + line 1219, "pan.___", state 43, "((i>=1))" + line 1229, "pan.___", state 54, "((j<2))" + line 1229, "pan.___", state 54, "((j>=2))" + line 1233, "pan.___", state 67, "((j<2))" + line 1233, "pan.___", state 67, "((j>=2))" + (6 of 78 states) +unreached in proctype :never: + line 1263, "pan.___", state 8, "-end-" + (1 of 8 states) + +pan: elapsed time 632 seconds +pan: rate 2628.547 states/second +pan: avg transition delay 1.2347e-06 usec +cp .input.spin urcu_free_no_mb.spin.input +cp .input.spin.trail urcu_free_no_mb.spin.input.trail diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_mb.spin.input b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_mb.spin.input new file mode 100644 index 0000000..77b6cf8 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_mb.spin.input @@ -0,0 +1,1240 @@ +#define NO_MB + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +//#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_mb.spin.input.trail b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_mb.spin.input.trail new file mode 100644 index 0000000..ea8ed03 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_mb.spin.input.trail @@ -0,0 +1,1227 @@ +-2:3:-2 +-4:-4:-4 +1:0:4467 +2:3:4387 +3:3:4390 +4:3:4390 +5:3:4393 +6:3:4401 +7:3:4401 +8:3:4404 +9:3:4410 +10:3:4414 +11:3:4414 +12:3:4417 +13:3:4427 +14:3:4435 +15:3:4435 +16:3:4438 +17:3:4444 +18:3:4448 +19:3:4448 +20:3:4451 +21:3:4457 +22:3:4461 +23:3:4462 +24:0:4467 +25:3:4464 +26:0:4467 +27:2:3121 +28:0:4467 +29:2:3127 +30:0:4467 +31:2:3128 +32:0:4467 +33:2:3130 +34:0:4467 +35:2:3131 +36:0:4467 +37:2:3132 +38:0:4467 +39:2:3133 +40:0:4467 +41:2:3134 +42:2:3135 +43:2:3139 +44:2:3140 +45:2:3148 +46:2:3149 +47:2:3153 +48:2:3154 +49:2:3162 +50:2:3167 +51:2:3171 +52:2:3172 +53:2:3180 +54:2:3181 +55:2:3185 +56:2:3186 +57:2:3180 +58:2:3181 +59:2:3185 +60:2:3186 +61:2:3194 +62:2:3199 +63:2:3200 +64:2:3211 +65:2:3212 +66:2:3213 +67:2:3224 +68:2:3229 +69:2:3230 +70:2:3241 +71:2:3242 +72:2:3243 +73:2:3241 +74:2:3242 +75:2:3243 +76:2:3254 +77:2:3262 +78:0:4467 +79:2:3133 +80:0:4467 +81:2:3266 +82:2:3270 +83:2:3271 +84:2:3275 +85:2:3279 +86:2:3280 +87:2:3284 +88:2:3292 +89:2:3293 +90:2:3297 +91:2:3301 +92:2:3302 +93:2:3297 +94:2:3298 +95:2:3306 +96:0:4467 +97:2:3133 +98:0:4467 +99:2:3314 +100:2:3315 +101:2:3316 +102:0:4467 +103:2:3133 +104:0:4467 +105:2:3324 +106:0:4467 +107:2:3133 +108:0:4467 +109:2:3327 +110:2:3328 +111:2:3332 +112:2:3333 +113:2:3341 +114:2:3342 +115:2:3346 +116:2:3347 +117:2:3355 +118:2:3360 +119:2:3361 +120:2:3373 +121:2:3374 +122:2:3378 +123:2:3379 +124:2:3373 +125:2:3374 +126:2:3378 +127:2:3379 +128:2:3387 +129:2:3392 +130:2:3393 +131:2:3404 +132:2:3405 +133:2:3406 +134:2:3417 +135:2:3422 +136:2:3423 +137:2:3434 +138:2:3435 +139:2:3436 +140:2:3434 +141:2:3435 +142:2:3436 +143:2:3447 +144:2:3454 +145:0:4467 +146:2:3133 +147:0:4467 +148:2:3458 +149:2:3459 +150:2:3460 +151:2:3472 +152:2:3473 +153:2:3477 +154:2:3478 +155:2:3486 +156:2:3491 +157:2:3495 +158:2:3496 +159:2:3504 +160:2:3505 +161:2:3509 +162:2:3510 +163:2:3504 +164:2:3505 +165:2:3509 +166:2:3510 +167:2:3518 +168:2:3523 +169:2:3524 +170:2:3535 +171:2:3536 +172:2:3537 +173:2:3548 +174:2:3553 +175:2:3554 +176:2:3565 +177:2:3566 +178:2:3567 +179:2:3565 +180:2:3566 +181:2:3567 +182:2:3578 +183:2:3589 +184:2:3590 +185:0:4467 +186:2:3133 +187:0:4467 +188:2:3596 +189:2:3597 +190:2:3601 +191:2:3602 +192:2:3610 +193:2:3611 +194:2:3615 +195:2:3616 +196:2:3624 +197:2:3629 +198:2:3633 +199:2:3634 +200:2:3642 +201:2:3643 +202:2:3647 +203:2:3648 +204:2:3642 +205:2:3643 +206:2:3647 +207:2:3648 +208:2:3656 +209:2:3661 +210:2:3662 +211:2:3673 +212:2:3674 +213:2:3675 +214:2:3686 +215:2:3691 +216:2:3692 +217:2:3703 +218:2:3704 +219:2:3705 +220:2:3703 +221:2:3704 +222:2:3705 +223:2:3716 +224:0:4467 +225:2:3133 +226:0:4467 +227:2:3725 +228:2:3726 +229:2:3730 +230:2:3731 +231:2:3739 +232:2:3740 +233:2:3744 +234:2:3745 +235:2:3753 +236:2:3758 +237:2:3762 +238:2:3763 +239:2:3771 +240:2:3772 +241:2:3776 +242:2:3777 +243:2:3771 +244:2:3772 +245:2:3776 +246:2:3777 +247:2:3785 +248:2:3790 +249:2:3791 +250:2:3802 +251:2:3803 +252:2:3804 +253:2:3815 +254:2:3820 +255:2:3821 +256:2:3832 +257:2:3833 +258:2:3834 +259:2:3832 +260:2:3833 +261:2:3834 +262:2:3845 +263:2:3852 +264:0:4467 +265:2:3133 +266:0:4467 +267:2:3856 +268:2:3857 +269:2:3858 +270:2:3870 +271:2:3871 +272:2:3875 +273:2:3876 +274:2:3884 +275:2:3889 +276:2:3893 +277:2:3894 +278:2:3902 +279:2:3903 +280:2:3907 +281:2:3908 +282:2:3902 +283:2:3903 +284:2:3907 +285:2:3908 +286:2:3916 +287:2:3921 +288:2:3922 +289:2:3933 +290:2:3934 +291:2:3935 +292:2:3946 +293:2:3951 +294:2:3952 +295:2:3963 +296:2:3964 +297:2:3965 +298:2:3963 +299:2:3964 +300:2:3965 +301:2:3976 +302:2:3986 +303:2:3987 +304:0:4467 +305:2:3133 +306:0:4467 +307:2:3996 +308:2:3997 +309:0:4467 +310:2:3133 +311:0:4467 +312:2:4001 +313:0:4467 +314:2:4009 +315:0:4467 +316:2:3128 +317:0:4467 +318:2:3130 +319:0:4467 +320:2:3131 +321:0:4467 +322:2:3132 +323:0:4467 +324:2:3133 +325:0:4467 +326:2:3134 +327:2:3135 +328:2:3139 +329:2:3140 +330:2:3148 +331:2:3149 +332:2:3153 +333:2:3154 +334:2:3162 +335:2:3167 +336:2:3171 +337:2:3172 +338:2:3180 +339:2:3181 +340:2:3182 +341:2:3180 +342:2:3181 +343:2:3185 +344:2:3186 +345:2:3194 +346:2:3199 +347:2:3200 +348:2:3211 +349:2:3212 +350:2:3213 +351:2:3224 +352:2:3229 +353:2:3230 +354:2:3241 +355:2:3242 +356:2:3243 +357:2:3241 +358:2:3242 +359:2:3243 +360:2:3254 +361:2:3262 +362:0:4467 +363:2:3133 +364:0:4467 +365:2:3266 +366:2:3270 +367:2:3271 +368:2:3275 +369:2:3279 +370:2:3280 +371:2:3284 +372:2:3292 +373:2:3293 +374:2:3297 +375:2:3298 +376:2:3297 +377:2:3301 +378:2:3302 +379:2:3306 +380:0:4467 +381:2:3133 +382:0:4467 +383:2:3314 +384:2:3315 +385:2:3316 +386:0:4467 +387:2:3133 +388:0:4467 +389:2:3324 +390:0:4467 +391:2:3133 +392:0:4467 +393:2:3327 +394:2:3328 +395:2:3332 +396:2:3333 +397:2:3341 +398:2:3342 +399:2:3346 +400:2:3347 +401:2:3355 +402:2:3360 +403:2:3361 +404:2:3373 +405:2:3374 +406:2:3378 +407:2:3379 +408:2:3373 +409:2:3374 +410:2:3378 +411:2:3379 +412:2:3387 +413:2:3392 +414:2:3393 +415:2:3404 +416:2:3405 +417:2:3406 +418:2:3417 +419:2:3422 +420:2:3423 +421:2:3434 +422:2:3435 +423:2:3436 +424:2:3434 +425:2:3435 +426:2:3436 +427:2:3447 +428:2:3454 +429:0:4467 +430:2:3133 +431:0:4467 +432:2:3458 +433:2:3459 +434:2:3460 +435:2:3472 +436:2:3473 +437:2:3477 +438:2:3478 +439:2:3486 +440:2:3491 +441:2:3495 +442:2:3496 +443:2:3504 +444:2:3505 +445:2:3509 +446:2:3510 +447:2:3504 +448:2:3505 +449:2:3509 +450:2:3510 +451:2:3518 +452:2:3523 +453:2:3524 +454:2:3535 +455:2:3536 +456:2:3537 +457:2:3548 +458:2:3553 +459:2:3554 +460:2:3565 +461:2:3566 +462:2:3567 +463:2:3565 +464:2:3566 +465:2:3567 +466:2:3578 +467:2:3589 +468:2:3590 +469:0:4467 +470:2:3133 +471:0:4467 +472:2:3596 +473:2:3597 +474:2:3601 +475:2:3602 +476:2:3610 +477:2:3611 +478:2:3615 +479:2:3616 +480:2:3624 +481:2:3629 +482:2:3633 +483:2:3634 +484:2:3642 +485:2:3643 +486:2:3647 +487:2:3648 +488:2:3642 +489:2:3643 +490:2:3647 +491:2:3648 +492:2:3656 +493:2:3661 +494:2:3662 +495:2:3673 +496:2:3674 +497:2:3675 +498:2:3686 +499:2:3691 +500:2:3692 +501:2:3703 +502:2:3704 +503:2:3705 +504:2:3703 +505:2:3704 +506:2:3705 +507:2:3716 +508:0:4467 +509:2:3133 +510:0:4467 +511:2:3725 +512:2:3726 +513:2:3730 +514:2:3731 +515:2:3739 +516:2:3740 +517:2:3744 +518:2:3745 +519:2:3753 +520:2:3758 +521:2:3762 +522:2:3763 +523:2:3771 +524:2:3772 +525:2:3776 +526:2:3777 +527:2:3771 +528:2:3772 +529:2:3776 +530:2:3777 +531:2:3785 +532:2:3790 +533:2:3791 +534:2:3802 +535:2:3803 +536:2:3804 +537:2:3815 +538:2:3820 +539:2:3821 +540:2:3832 +541:2:3833 +542:2:3834 +543:2:3832 +544:2:3833 +545:2:3834 +546:2:3845 +547:2:3852 +548:0:4467 +549:2:3133 +550:0:4467 +551:2:3856 +552:2:3857 +553:2:3858 +554:2:3870 +555:2:3871 +556:2:3875 +557:2:3876 +558:2:3884 +559:2:3889 +560:2:3893 +561:2:3894 +562:2:3902 +563:2:3903 +564:2:3907 +565:2:3908 +566:2:3902 +567:2:3903 +568:2:3907 +569:2:3908 +570:2:3916 +571:2:3921 +572:2:3922 +573:2:3933 +574:2:3934 +575:2:3935 +576:2:3946 +577:2:3951 +578:2:3952 +579:2:3963 +580:2:3964 +581:2:3965 +582:2:3963 +583:2:3964 +584:2:3965 +585:2:3976 +586:2:3986 +587:2:3987 +588:0:4467 +589:2:3133 +590:0:4467 +591:2:3996 +592:2:3997 +593:0:4467 +594:2:3133 +595:0:4467 +596:2:4001 +597:0:4467 +598:2:4009 +599:0:4467 +600:2:3128 +601:0:4467 +602:2:3130 +603:0:4467 +604:2:3131 +605:0:4467 +606:2:3132 +607:0:4467 +608:2:3133 +609:0:4467 +610:2:3134 +611:2:3135 +612:2:3139 +613:2:3140 +614:2:3148 +615:2:3149 +616:2:3153 +617:2:3154 +618:2:3162 +619:2:3167 +620:2:3171 +621:2:3172 +622:2:3180 +623:2:3181 +624:2:3185 +625:2:3186 +626:2:3180 +627:2:3181 +628:2:3182 +629:2:3194 +630:2:3199 +631:2:3200 +632:2:3211 +633:2:3212 +634:2:3213 +635:2:3224 +636:2:3229 +637:2:3230 +638:2:3241 +639:2:3242 +640:2:3243 +641:2:3241 +642:2:3242 +643:2:3243 +644:2:3254 +645:2:3262 +646:0:4467 +647:2:3133 +648:0:4467 +649:2:3266 +650:2:3270 +651:2:3271 +652:2:3275 +653:2:3279 +654:2:3280 +655:2:3284 +656:2:3292 +657:2:3293 +658:2:3297 +659:2:3301 +660:2:3302 +661:2:3297 +662:2:3298 +663:2:3306 +664:0:4467 +665:2:3133 +666:0:4467 +667:2:3314 +668:2:3315 +669:2:3316 +670:0:4467 +671:2:3133 +672:0:4467 +673:2:3324 +674:0:4467 +675:2:3133 +676:0:4467 +677:2:3327 +678:2:3328 +679:2:3332 +680:2:3333 +681:2:3341 +682:2:3342 +683:2:3346 +684:2:3347 +685:2:3355 +686:2:3360 +687:2:3361 +688:2:3373 +689:2:3374 +690:2:3378 +691:2:3379 +692:2:3373 +693:2:3374 +694:2:3378 +695:2:3379 +696:2:3387 +697:2:3392 +698:2:3393 +699:2:3404 +700:2:3405 +701:2:3406 +702:2:3417 +703:2:3422 +704:2:3423 +705:2:3434 +706:2:3435 +707:2:3436 +708:2:3434 +709:2:3435 +710:2:3436 +711:2:3447 +712:2:3454 +713:0:4467 +714:2:3133 +715:0:4467 +716:2:3458 +717:2:3459 +718:2:3460 +719:2:3472 +720:2:3473 +721:2:3477 +722:2:3478 +723:2:3486 +724:2:3491 +725:2:3495 +726:2:3496 +727:2:3504 +728:2:3505 +729:2:3509 +730:2:3510 +731:2:3504 +732:2:3505 +733:2:3509 +734:2:3510 +735:2:3518 +736:2:3523 +737:2:3524 +738:2:3535 +739:2:3536 +740:2:3537 +741:2:3548 +742:2:3553 +743:2:3554 +744:2:3565 +745:2:3566 +746:2:3567 +747:2:3565 +748:2:3566 +749:2:3567 +750:2:3578 +751:2:3589 +752:2:3590 +753:0:4467 +754:2:3133 +755:0:4467 +756:2:3596 +757:2:3597 +758:2:3601 +759:2:3602 +760:2:3610 +761:2:3611 +762:2:3615 +763:2:3616 +764:2:3624 +765:2:3629 +766:2:3633 +767:2:3634 +768:2:3642 +769:2:3643 +770:2:3647 +771:2:3648 +772:2:3642 +773:2:3643 +774:2:3647 +775:2:3648 +776:2:3656 +777:2:3661 +778:2:3662 +779:2:3673 +780:2:3674 +781:2:3675 +782:2:3686 +783:2:3691 +784:2:3692 +785:2:3703 +786:2:3704 +787:2:3705 +788:2:3703 +789:2:3704 +790:2:3705 +791:2:3716 +792:0:4467 +793:2:3133 +794:0:4467 +795:2:3856 +796:2:3857 +797:2:3861 +798:2:3862 +799:2:3870 +800:2:3871 +801:2:3875 +802:2:3876 +803:2:3884 +804:2:3889 +805:2:3893 +806:2:3894 +807:2:3902 +808:2:3903 +809:2:3907 +810:2:3908 +811:2:3902 +812:2:3903 +813:2:3907 +814:2:3908 +815:2:3916 +816:2:3921 +817:2:3922 +818:2:3933 +819:2:3934 +820:2:3935 +821:2:3946 +822:2:3951 +823:2:3952 +824:2:3963 +825:2:3964 +826:2:3965 +827:2:3963 +828:2:3964 +829:2:3965 +830:2:3976 +831:2:3986 +832:2:3987 +833:0:4467 +834:2:3133 +835:0:4467 +836:2:3996 +837:2:3997 +838:0:4467 +839:2:3133 +840:0:4467 +841:2:3725 +842:2:3726 +843:2:3730 +844:2:3731 +845:2:3739 +846:2:3740 +847:2:3744 +848:2:3745 +849:2:3753 +850:2:3758 +851:2:3762 +852:2:3763 +853:2:3771 +854:2:3772 +855:2:3773 +856:2:3771 +857:2:3772 +858:2:3776 +859:2:3777 +860:2:3785 +861:2:3790 +862:2:3791 +863:2:3802 +864:2:3803 +865:2:3804 +866:2:3815 +867:2:3820 +868:2:3821 +869:2:3832 +870:2:3833 +871:2:3834 +872:2:3832 +873:2:3833 +874:2:3834 +875:2:3845 +876:2:3852 +877:0:4467 +878:2:3133 +879:0:4467 +880:2:4001 +881:0:4467 +882:2:4009 +883:0:4467 +884:2:4010 +885:0:4467 +886:2:4015 +887:0:4467 +888:1:2 +889:0:4467 +890:2:4016 +891:0:4467 +892:1:8 +893:0:4467 +894:2:4015 +895:0:4467 +896:1:9 +897:0:4467 +898:2:4016 +899:0:4467 +900:1:10 +901:0:4467 +902:2:4015 +903:0:4467 +904:1:11 +905:0:4467 +906:2:4016 +907:0:4467 +908:1:12 +909:0:4467 +910:2:4015 +911:0:4467 +912:1:13 +913:0:4467 +914:2:4016 +915:0:4467 +916:1:14 +917:0:4467 +918:2:4015 +919:0:4467 +920:1:15 +921:0:4467 +922:2:4016 +923:0:4467 +924:1:16 +925:1:17 +926:1:21 +927:1:22 +928:1:30 +929:1:31 +930:1:35 +931:1:36 +932:1:44 +933:1:49 +934:1:53 +935:1:54 +936:1:62 +937:1:63 +938:1:67 +939:1:68 +940:1:62 +941:1:63 +942:1:67 +943:1:68 +944:1:76 +945:1:81 +946:1:82 +947:1:93 +948:1:94 +949:1:95 +950:1:106 +951:1:118 +952:1:119 +953:1:123 +954:1:124 +955:1:125 +956:1:123 +957:1:124 +958:1:125 +959:1:136 +960:0:4467 +961:2:4015 +962:0:4467 +963:1:15 +964:0:4467 +965:2:4016 +966:0:4467 +967:1:145 +968:1:146 +969:0:4467 +970:2:4015 +971:0:4467 +972:1:15 +973:0:4467 +974:2:4016 +975:0:4467 +976:1:152 +977:1:153 +978:1:157 +979:1:158 +980:1:166 +981:1:167 +982:1:171 +983:1:172 +984:1:180 +985:1:185 +986:1:189 +987:1:190 +988:1:198 +989:1:199 +990:1:203 +991:1:204 +992:1:198 +993:1:199 +994:1:203 +995:1:204 +996:1:212 +997:1:217 +998:1:218 +999:1:229 +1000:1:230 +1001:1:231 +1002:1:242 +1003:1:254 +1004:1:255 +1005:1:259 +1006:1:260 +1007:1:261 +1008:1:259 +1009:1:260 +1010:1:261 +1011:1:272 +1012:0:4467 +1013:2:4015 +1014:0:4467 +1015:1:15 +1016:0:4467 +1017:2:4016 +1018:0:4467 +1019:1:281 +1020:1:282 +1021:1:286 +1022:1:287 +1023:1:295 +1024:1:296 +1025:1:300 +1026:1:301 +1027:1:309 +1028:1:314 +1029:1:318 +1030:1:319 +1031:1:327 +1032:1:328 +1033:1:332 +1034:1:333 +1035:1:327 +1036:1:328 +1037:1:332 +1038:1:333 +1039:1:341 +1040:1:346 +1041:1:347 +1042:1:358 +1043:1:359 +1044:1:360 +1045:1:371 +1046:1:383 +1047:1:384 +1048:1:388 +1049:1:389 +1050:1:390 +1051:1:388 +1052:1:389 +1053:1:390 +1054:1:401 +1055:1:408 +1056:0:4467 +1057:2:4015 +1058:0:4467 +1059:1:15 +1060:0:4467 +1061:2:4016 +1062:0:4467 +1063:1:636 +1064:1:637 +1065:1:641 +1066:1:642 +1067:1:650 +1068:1:651 +1069:1:652 +1070:1:664 +1071:1:669 +1072:1:673 +1073:1:674 +1074:1:682 +1075:1:683 +1076:1:687 +1077:1:688 +1078:1:682 +1079:1:683 +1080:1:687 +1081:1:688 +1082:1:696 +1083:1:701 +1084:1:702 +1085:1:713 +1086:1:714 +1087:1:715 +1088:1:726 +1089:1:738 +1090:1:739 +1091:1:743 +1092:1:744 +1093:1:745 +1094:1:743 +1095:1:744 +1096:1:745 +1097:1:756 +1098:0:4467 +1099:2:4015 +1100:0:4467 +1101:1:15 +1102:0:4467 +1103:2:4016 +1104:0:4467 +1105:1:765 +1106:1:768 +1107:1:769 +1108:0:4467 +1109:2:4015 +1110:0:4467 +1111:1:15 +1112:0:4467 +1113:2:4016 +1114:0:4467 +1115:1:1032 +1116:1:1033 +1117:1:1037 +1118:1:1038 +1119:1:1046 +1120:1:1047 +1121:1:1051 +1122:1:1052 +1123:1:1060 +1124:1:1065 +1125:1:1069 +1126:1:1070 +1127:1:1078 +1128:1:1079 +1129:1:1083 +1130:1:1084 +1131:1:1078 +1132:1:1079 +1133:1:1083 +1134:1:1084 +1135:1:1092 +1136:1:1097 +1137:1:1098 +1138:1:1109 +1139:1:1110 +1140:1:1111 +1141:1:1122 +1142:1:1134 +1143:1:1135 +1144:1:1139 +1145:1:1140 +1146:1:1141 +1147:1:1139 +1148:1:1140 +1149:1:1141 +1150:1:1152 +1151:1:1159 +1152:1:1163 +1153:0:4467 +1154:2:4015 +1155:0:4467 +1156:1:15 +1157:0:4467 +1158:2:4016 +1159:0:4467 +1160:1:1164 +1161:1:1165 +1162:1:1169 +1163:1:1170 +1164:1:1178 +1165:1:1179 +1166:1:1180 +1167:1:1192 +1168:1:1197 +1169:1:1201 +1170:1:1202 +1171:1:1210 +1172:1:1211 +1173:1:1215 +1174:1:1216 +1175:1:1210 +1176:1:1211 +1177:1:1215 +1178:1:1216 +1179:1:1224 +1180:1:1229 +1181:1:1230 +1182:1:1241 +1183:1:1242 +1184:1:1243 +1185:1:1254 +1186:1:1266 +1187:1:1267 +1188:1:1271 +1189:1:1272 +1190:1:1273 +1191:1:1271 +1192:1:1272 +1193:1:1273 +1194:1:1284 +1195:0:4467 +1196:2:4015 +1197:0:4467 +1198:1:15 +1199:0:4467 +1200:2:4016 +1201:0:4467 +1202:1:1293 +1203:0:4467 +1204:2:4015 +1205:0:4467 +1206:1:3027 +1207:1:3034 +1208:1:3035 +1209:1:3042 +1210:1:3047 +1211:1:3054 +1212:1:3055 +1213:1:3054 +1214:1:3055 +1215:1:3062 +1216:1:3066 +1217:0:4467 +1218:2:4016 +1219:0:4467 +1220:1:1295 +1221:1:1296 +1222:0:4465 +1223:2:4015 +1224:0:4471 +1225:1:1135 diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_rmb.define b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_rmb.define new file mode 100644 index 0000000..73e61a4 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_rmb.define @@ -0,0 +1 @@ +#define NO_RMB diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_rmb.log b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_rmb.log new file mode 100644 index 0000000..c1be1de --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_rmb.log @@ -0,0 +1,588 @@ +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define >> pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_free.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_free_no_rmb.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1258) +pan: claim violated! (at depth 1714) +pan: wrote .input.spin.trail + +(Spin Version 5.1.7 -- 23 December 2008) +Warning: Search not completed + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness disabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 4557, errors: 1 + 191938 states, stored + 81734116 states, matched + 81926054 transitions (= stored+matched) +4.8026893e+08 atomic steps +hash conflicts: 5624584 (resolved) + +Stats on memory usage (in Megabytes): + 21.233 equivalent memory usage for states (stored*(State-vector + overhead)) + 16.849 actual memory usage for states (compression: 79.35%) + state-vector as stored = 64 byte + 28 byte overhead + 8.000 memory used for hash table (-w20) + 457.764 memory used for DFS stack (-m10000000) + 482.561 total actual memory usage + +unreached in proctype urcu_reader + line 395, "pan.___", state 17, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 49, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 63, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 82, "(1)" + line 421, "pan.___", state 112, "(1)" + line 425, "pan.___", state 125, "(1)" + line 576, "pan.___", state 146, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 395, "pan.___", state 153, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 185, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 199, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 218, "(1)" + line 421, "pan.___", state 248, "(1)" + line 425, "pan.___", state 261, "(1)" + line 395, "pan.___", state 282, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 314, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 328, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 347, "(1)" + line 421, "pan.___", state 377, "(1)" + line 425, "pan.___", state 390, "(1)" + line 395, "pan.___", state 413, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 415, "(1)" + line 395, "pan.___", state 416, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 416, "else" + line 395, "pan.___", state 419, "(1)" + line 399, "pan.___", state 427, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 429, "(1)" + line 399, "pan.___", state 430, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 430, "else" + line 399, "pan.___", state 433, "(1)" + line 399, "pan.___", state 434, "(1)" + line 399, "pan.___", state 434, "(1)" + line 397, "pan.___", state 439, "((i<1))" + line 397, "pan.___", state 439, "((i>=1))" + line 404, "pan.___", state 445, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 447, "(1)" + line 404, "pan.___", state 448, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 448, "else" + line 404, "pan.___", state 451, "(1)" + line 404, "pan.___", state 452, "(1)" + line 404, "pan.___", state 452, "(1)" + line 408, "pan.___", state 459, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 461, "(1)" + line 408, "pan.___", state 462, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 462, "else" + line 408, "pan.___", state 465, "(1)" + line 408, "pan.___", state 466, "(1)" + line 408, "pan.___", state 466, "(1)" + line 406, "pan.___", state 471, "((i<2))" + line 406, "pan.___", state 471, "((i>=2))" + line 412, "pan.___", state 478, "(1)" + line 412, "pan.___", state 479, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 479, "else" + line 412, "pan.___", state 482, "(1)" + line 412, "pan.___", state 483, "(1)" + line 412, "pan.___", state 483, "(1)" + line 416, "pan.___", state 491, "(1)" + line 416, "pan.___", state 492, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 492, "else" + line 416, "pan.___", state 495, "(1)" + line 416, "pan.___", state 496, "(1)" + line 416, "pan.___", state 496, "(1)" + line 414, "pan.___", state 501, "((i<1))" + line 414, "pan.___", state 501, "((i>=1))" + line 421, "pan.___", state 508, "(1)" + line 421, "pan.___", state 509, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 509, "else" + line 421, "pan.___", state 512, "(1)" + line 421, "pan.___", state 513, "(1)" + line 421, "pan.___", state 513, "(1)" + line 425, "pan.___", state 521, "(1)" + line 425, "pan.___", state 522, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 522, "else" + line 425, "pan.___", state 525, "(1)" + line 425, "pan.___", state 526, "(1)" + line 425, "pan.___", state 526, "(1)" + line 423, "pan.___", state 531, "((i<2))" + line 423, "pan.___", state 531, "((i>=2))" + line 430, "pan.___", state 535, "(1)" + line 430, "pan.___", state 535, "(1)" + line 576, "pan.___", state 538, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 576, "pan.___", state 539, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 576, "pan.___", state 540, "(1)" + line 250, "pan.___", state 544, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 555, "(1)" + line 258, "pan.___", state 566, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 575, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 591, "(1)" + line 231, "pan.___", state 599, "(1)" + line 235, "pan.___", state 611, "(1)" + line 239, "pan.___", state 619, "(1)" + line 395, "pan.___", state 637, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 651, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 669, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 683, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 702, "(1)" + line 416, "pan.___", state 715, "(1)" + line 421, "pan.___", state 732, "(1)" + line 425, "pan.___", state 745, "(1)" + line 395, "pan.___", state 773, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 775, "(1)" + line 395, "pan.___", state 776, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 776, "else" + line 395, "pan.___", state 779, "(1)" + line 399, "pan.___", state 787, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 789, "(1)" + line 399, "pan.___", state 790, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 790, "else" + line 399, "pan.___", state 793, "(1)" + line 399, "pan.___", state 794, "(1)" + line 399, "pan.___", state 794, "(1)" + line 397, "pan.___", state 799, "((i<1))" + line 397, "pan.___", state 799, "((i>=1))" + line 404, "pan.___", state 805, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 807, "(1)" + line 404, "pan.___", state 808, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 808, "else" + line 404, "pan.___", state 811, "(1)" + line 404, "pan.___", state 812, "(1)" + line 404, "pan.___", state 812, "(1)" + line 408, "pan.___", state 819, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 821, "(1)" + line 408, "pan.___", state 822, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 822, "else" + line 408, "pan.___", state 825, "(1)" + line 408, "pan.___", state 826, "(1)" + line 408, "pan.___", state 826, "(1)" + line 406, "pan.___", state 831, "((i<2))" + line 406, "pan.___", state 831, "((i>=2))" + line 412, "pan.___", state 838, "(1)" + line 412, "pan.___", state 839, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 839, "else" + line 412, "pan.___", state 842, "(1)" + line 412, "pan.___", state 843, "(1)" + line 412, "pan.___", state 843, "(1)" + line 416, "pan.___", state 851, "(1)" + line 416, "pan.___", state 852, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 852, "else" + line 416, "pan.___", state 855, "(1)" + line 416, "pan.___", state 856, "(1)" + line 416, "pan.___", state 856, "(1)" + line 414, "pan.___", state 861, "((i<1))" + line 414, "pan.___", state 861, "((i>=1))" + line 421, "pan.___", state 868, "(1)" + line 421, "pan.___", state 869, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 869, "else" + line 421, "pan.___", state 872, "(1)" + line 421, "pan.___", state 873, "(1)" + line 421, "pan.___", state 873, "(1)" + line 425, "pan.___", state 881, "(1)" + line 425, "pan.___", state 882, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 882, "else" + line 425, "pan.___", state 885, "(1)" + line 425, "pan.___", state 886, "(1)" + line 425, "pan.___", state 886, "(1)" + line 430, "pan.___", state 895, "(1)" + line 430, "pan.___", state 895, "(1)" + line 395, "pan.___", state 902, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 904, "(1)" + line 395, "pan.___", state 905, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 905, "else" + line 395, "pan.___", state 908, "(1)" + line 399, "pan.___", state 916, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 918, "(1)" + line 399, "pan.___", state 919, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 919, "else" + line 399, "pan.___", state 922, "(1)" + line 399, "pan.___", state 923, "(1)" + line 399, "pan.___", state 923, "(1)" + line 397, "pan.___", state 928, "((i<1))" + line 397, "pan.___", state 928, "((i>=1))" + line 404, "pan.___", state 934, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 936, "(1)" + line 404, "pan.___", state 937, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 937, "else" + line 404, "pan.___", state 940, "(1)" + line 404, "pan.___", state 941, "(1)" + line 404, "pan.___", state 941, "(1)" + line 408, "pan.___", state 948, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 950, "(1)" + line 408, "pan.___", state 951, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 951, "else" + line 408, "pan.___", state 954, "(1)" + line 408, "pan.___", state 955, "(1)" + line 408, "pan.___", state 955, "(1)" + line 406, "pan.___", state 960, "((i<2))" + line 406, "pan.___", state 960, "((i>=2))" + line 412, "pan.___", state 967, "(1)" + line 412, "pan.___", state 968, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 968, "else" + line 412, "pan.___", state 971, "(1)" + line 412, "pan.___", state 972, "(1)" + line 412, "pan.___", state 972, "(1)" + line 416, "pan.___", state 980, "(1)" + line 416, "pan.___", state 981, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 981, "else" + line 416, "pan.___", state 984, "(1)" + line 416, "pan.___", state 985, "(1)" + line 416, "pan.___", state 985, "(1)" + line 414, "pan.___", state 990, "((i<1))" + line 414, "pan.___", state 990, "((i>=1))" + line 421, "pan.___", state 997, "(1)" + line 421, "pan.___", state 998, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 998, "else" + line 421, "pan.___", state 1001, "(1)" + line 421, "pan.___", state 1002, "(1)" + line 421, "pan.___", state 1002, "(1)" + line 425, "pan.___", state 1010, "(1)" + line 425, "pan.___", state 1011, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 1011, "else" + line 425, "pan.___", state 1014, "(1)" + line 425, "pan.___", state 1015, "(1)" + line 425, "pan.___", state 1015, "(1)" + line 423, "pan.___", state 1020, "((i<2))" + line 423, "pan.___", state 1020, "((i>=2))" + line 430, "pan.___", state 1024, "(1)" + line 430, "pan.___", state 1024, "(1)" + line 584, "pan.___", state 1028, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 395, "pan.___", state 1033, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1047, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1065, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1079, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1098, "(1)" + line 416, "pan.___", state 1111, "(1)" + line 421, "pan.___", state 1128, "(1)" + line 425, "pan.___", state 1141, "(1)" + line 395, "pan.___", state 1165, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1197, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1211, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1230, "(1)" + line 421, "pan.___", state 1260, "(1)" + line 425, "pan.___", state 1273, "(1)" + line 395, "pan.___", state 1298, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1330, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1344, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1363, "(1)" + line 421, "pan.___", state 1393, "(1)" + line 425, "pan.___", state 1406, "(1)" + line 395, "pan.___", state 1427, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1459, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1473, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1492, "(1)" + line 421, "pan.___", state 1522, "(1)" + line 425, "pan.___", state 1535, "(1)" + line 250, "pan.___", state 1558, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1580, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1589, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1605, "(1)" + line 231, "pan.___", state 1613, "(1)" + line 235, "pan.___", state 1625, "(1)" + line 239, "pan.___", state 1633, "(1)" + line 395, "pan.___", state 1651, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1665, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1683, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1697, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1716, "(1)" + line 416, "pan.___", state 1729, "(1)" + line 421, "pan.___", state 1746, "(1)" + line 425, "pan.___", state 1759, "(1)" + line 395, "pan.___", state 1780, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1794, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1812, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1826, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1845, "(1)" + line 416, "pan.___", state 1858, "(1)" + line 421, "pan.___", state 1875, "(1)" + line 425, "pan.___", state 1888, "(1)" + line 395, "pan.___", state 1912, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1928, "(1)" + line 404, "pan.___", state 1944, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1958, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1977, "(1)" + line 421, "pan.___", state 2007, "(1)" + line 425, "pan.___", state 2020, "(1)" + line 623, "pan.___", state 2041, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 395, "pan.___", state 2048, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2080, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2094, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2113, "(1)" + line 421, "pan.___", state 2143, "(1)" + line 425, "pan.___", state 2156, "(1)" + line 395, "pan.___", state 2177, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2209, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2223, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2242, "(1)" + line 421, "pan.___", state 2272, "(1)" + line 425, "pan.___", state 2285, "(1)" + line 395, "pan.___", state 2308, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 2310, "(1)" + line 395, "pan.___", state 2311, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 2311, "else" + line 395, "pan.___", state 2314, "(1)" + line 399, "pan.___", state 2322, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2324, "(1)" + line 399, "pan.___", state 2325, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 2325, "else" + line 399, "pan.___", state 2328, "(1)" + line 399, "pan.___", state 2329, "(1)" + line 399, "pan.___", state 2329, "(1)" + line 397, "pan.___", state 2334, "((i<1))" + line 397, "pan.___", state 2334, "((i>=1))" + line 404, "pan.___", state 2340, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2342, "(1)" + line 404, "pan.___", state 2343, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 2343, "else" + line 404, "pan.___", state 2346, "(1)" + line 404, "pan.___", state 2347, "(1)" + line 404, "pan.___", state 2347, "(1)" + line 408, "pan.___", state 2354, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2356, "(1)" + line 408, "pan.___", state 2357, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 2357, "else" + line 408, "pan.___", state 2360, "(1)" + line 408, "pan.___", state 2361, "(1)" + line 408, "pan.___", state 2361, "(1)" + line 406, "pan.___", state 2366, "((i<2))" + line 406, "pan.___", state 2366, "((i>=2))" + line 412, "pan.___", state 2373, "(1)" + line 412, "pan.___", state 2374, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 2374, "else" + line 412, "pan.___", state 2377, "(1)" + line 412, "pan.___", state 2378, "(1)" + line 412, "pan.___", state 2378, "(1)" + line 416, "pan.___", state 2386, "(1)" + line 416, "pan.___", state 2387, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 2387, "else" + line 416, "pan.___", state 2390, "(1)" + line 416, "pan.___", state 2391, "(1)" + line 416, "pan.___", state 2391, "(1)" + line 414, "pan.___", state 2396, "((i<1))" + line 414, "pan.___", state 2396, "((i>=1))" + line 421, "pan.___", state 2403, "(1)" + line 421, "pan.___", state 2404, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 2404, "else" + line 421, "pan.___", state 2407, "(1)" + line 421, "pan.___", state 2408, "(1)" + line 421, "pan.___", state 2408, "(1)" + line 425, "pan.___", state 2416, "(1)" + line 425, "pan.___", state 2417, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 2417, "else" + line 425, "pan.___", state 2420, "(1)" + line 425, "pan.___", state 2421, "(1)" + line 425, "pan.___", state 2421, "(1)" + line 423, "pan.___", state 2426, "((i<2))" + line 423, "pan.___", state 2426, "((i>=2))" + line 430, "pan.___", state 2430, "(1)" + line 430, "pan.___", state 2430, "(1)" + line 623, "pan.___", state 2433, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 623, "pan.___", state 2434, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 623, "pan.___", state 2435, "(1)" + line 250, "pan.___", state 2439, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 2450, "(1)" + line 258, "pan.___", state 2461, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 2470, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 2486, "(1)" + line 231, "pan.___", state 2494, "(1)" + line 235, "pan.___", state 2506, "(1)" + line 239, "pan.___", state 2514, "(1)" + line 395, "pan.___", state 2532, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2546, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2564, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2578, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2597, "(1)" + line 416, "pan.___", state 2610, "(1)" + line 421, "pan.___", state 2627, "(1)" + line 425, "pan.___", state 2640, "(1)" + line 250, "pan.___", state 2664, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 2673, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 2686, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 2695, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 2711, "(1)" + line 231, "pan.___", state 2719, "(1)" + line 235, "pan.___", state 2731, "(1)" + line 239, "pan.___", state 2739, "(1)" + line 395, "pan.___", state 2757, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2771, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2789, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2803, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2822, "(1)" + line 416, "pan.___", state 2835, "(1)" + line 421, "pan.___", state 2852, "(1)" + line 425, "pan.___", state 2865, "(1)" + line 395, "pan.___", state 2886, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2900, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2918, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2932, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2951, "(1)" + line 416, "pan.___", state 2964, "(1)" + line 421, "pan.___", state 2981, "(1)" + line 425, "pan.___", state 2994, "(1)" + line 395, "pan.___", state 3027, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 3059, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 3073, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 3092, "(1)" + line 421, "pan.___", state 3122, "(1)" + line 425, "pan.___", state 3135, "(1)" + line 395, "pan.___", state 3154, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 3168, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 3186, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 3200, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 3219, "(1)" + line 416, "pan.___", state 3232, "(1)" + line 421, "pan.___", state 3249, "(1)" + line 425, "pan.___", state 3262, "(1)" + line 877, "pan.___", state 3283, "-end-" + (325 of 3283 states) +unreached in proctype urcu_writer + line 395, "pan.___", state 18, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 24, "(1)" + line 399, "pan.___", state 32, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 38, "(1)" + line 399, "pan.___", state 39, "(1)" + line 399, "pan.___", state 39, "(1)" + line 397, "pan.___", state 44, "((i<1))" + line 397, "pan.___", state 44, "((i>=1))" + line 404, "pan.___", state 50, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 56, "(1)" + line 404, "pan.___", state 57, "(1)" + line 404, "pan.___", state 57, "(1)" + line 408, "pan.___", state 70, "(1)" + line 408, "pan.___", state 71, "(1)" + line 408, "pan.___", state 71, "(1)" + line 406, "pan.___", state 76, "((i<2))" + line 406, "pan.___", state 76, "((i>=2))" + line 412, "pan.___", state 83, "(1)" + line 412, "pan.___", state 84, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 84, "else" + line 412, "pan.___", state 87, "(1)" + line 412, "pan.___", state 88, "(1)" + line 412, "pan.___", state 88, "(1)" + line 416, "pan.___", state 96, "(1)" + line 416, "pan.___", state 97, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 97, "else" + line 416, "pan.___", state 100, "(1)" + line 416, "pan.___", state 101, "(1)" + line 416, "pan.___", state 101, "(1)" + line 414, "pan.___", state 106, "((i<1))" + line 414, "pan.___", state 106, "((i>=1))" + line 421, "pan.___", state 113, "(1)" + line 421, "pan.___", state 114, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 114, "else" + line 421, "pan.___", state 117, "(1)" + line 421, "pan.___", state 118, "(1)" + line 421, "pan.___", state 118, "(1)" + line 425, "pan.___", state 126, "(1)" + line 425, "pan.___", state 127, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 127, "else" + line 425, "pan.___", state 130, "(1)" + line 425, "pan.___", state 131, "(1)" + line 425, "pan.___", state 131, "(1)" + line 423, "pan.___", state 136, "((i<2))" + line 423, "pan.___", state 136, "((i>=2))" + line 430, "pan.___", state 140, "(1)" + line 430, "pan.___", state 140, "(1)" + line 250, "pan.___", state 149, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 158, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 171, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 211, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 225, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 243, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 257, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 276, "(1)" + line 416, "pan.___", state 289, "(1)" + line 421, "pan.___", state 306, "(1)" + line 425, "pan.___", state 319, "(1)" + line 399, "pan.___", state 356, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 374, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 388, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 420, "(1)" + line 421, "pan.___", state 437, "(1)" + line 425, "pan.___", state 450, "(1)" + line 399, "pan.___", state 494, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 512, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 526, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 558, "(1)" + line 421, "pan.___", state 575, "(1)" + line 425, "pan.___", state 588, "(1)" + line 399, "pan.___", state 623, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 641, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 655, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 687, "(1)" + line 421, "pan.___", state 704, "(1)" + line 425, "pan.___", state 717, "(1)" + line 399, "pan.___", state 754, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 772, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 786, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 818, "(1)" + line 421, "pan.___", state 835, "(1)" + line 425, "pan.___", state 848, "(1)" + line 250, "pan.___", state 903, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 912, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 927, "(1)" + line 262, "pan.___", state 934, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 950, "(1)" + line 231, "pan.___", state 958, "(1)" + line 235, "pan.___", state 970, "(1)" + line 239, "pan.___", state 978, "(1)" + line 254, "pan.___", state 1003, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1016, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1025, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1041, "(1)" + line 231, "pan.___", state 1049, "(1)" + line 235, "pan.___", state 1061, "(1)" + line 239, "pan.___", state 1069, "(1)" + line 254, "pan.___", state 1094, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1107, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1116, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1132, "(1)" + line 231, "pan.___", state 1140, "(1)" + line 235, "pan.___", state 1152, "(1)" + line 239, "pan.___", state 1160, "(1)" + line 254, "pan.___", state 1185, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1198, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1207, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1223, "(1)" + line 231, "pan.___", state 1231, "(1)" + line 235, "pan.___", state 1243, "(1)" + line 239, "pan.___", state 1251, "(1)" + line 1204, "pan.___", state 1266, "-end-" + (96 of 1266 states) +unreached in proctype :init: + line 1215, "pan.___", state 9, "((j<2))" + line 1215, "pan.___", state 9, "((j>=2))" + line 1216, "pan.___", state 20, "((j<2))" + line 1216, "pan.___", state 20, "((j>=2))" + line 1221, "pan.___", state 33, "((j<2))" + line 1221, "pan.___", state 33, "((j>=2))" + line 1219, "pan.___", state 43, "((i<1))" + line 1219, "pan.___", state 43, "((i>=1))" + line 1229, "pan.___", state 54, "((j<2))" + line 1229, "pan.___", state 54, "((j>=2))" + line 1233, "pan.___", state 67, "((j<2))" + line 1233, "pan.___", state 67, "((j>=2))" + (6 of 78 states) +unreached in proctype :never: + line 1263, "pan.___", state 8, "-end-" + (1 of 8 states) + +pan: elapsed time 102 seconds +pan: rate 1874.9438 states/second +pan: avg transition delay 1.2495e-06 usec +cp .input.spin urcu_free_no_rmb.spin.input +cp .input.spin.trail urcu_free_no_rmb.spin.input.trail diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_rmb.spin.input b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_rmb.spin.input new file mode 100644 index 0000000..2d07e51 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_rmb.spin.input @@ -0,0 +1,1240 @@ +#define NO_RMB + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +//#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_rmb.spin.input.trail b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_rmb.spin.input.trail new file mode 100644 index 0000000..e179cd5 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_rmb.spin.input.trail @@ -0,0 +1,1717 @@ +-2:3:-2 +-4:-4:-4 +1:0:4629 +2:3:4549 +3:3:4552 +4:3:4552 +5:3:4555 +6:3:4563 +7:3:4563 +8:3:4566 +9:3:4572 +10:3:4576 +11:3:4576 +12:3:4579 +13:3:4589 +14:3:4597 +15:3:4597 +16:3:4600 +17:3:4606 +18:3:4610 +19:3:4610 +20:3:4613 +21:3:4619 +22:3:4623 +23:3:4624 +24:0:4629 +25:3:4626 +26:0:4629 +27:2:3285 +28:0:4629 +29:2:3291 +30:0:4629 +31:2:3292 +32:0:4629 +33:2:3294 +34:0:4629 +35:2:3295 +36:0:4629 +37:2:3296 +38:2:3297 +39:2:3301 +40:2:3302 +41:2:3310 +42:2:3311 +43:2:3315 +44:2:3316 +45:2:3324 +46:2:3329 +47:2:3333 +48:2:3334 +49:2:3342 +50:2:3343 +51:2:3347 +52:2:3348 +53:2:3342 +54:2:3343 +55:2:3347 +56:2:3348 +57:2:3356 +58:2:3361 +59:2:3362 +60:2:3373 +61:2:3374 +62:2:3375 +63:2:3386 +64:2:3391 +65:2:3392 +66:2:3403 +67:2:3404 +68:2:3405 +69:2:3403 +70:2:3404 +71:2:3405 +72:2:3416 +73:2:3424 +74:0:4629 +75:2:3295 +76:0:4629 +77:2:3428 +78:2:3432 +79:2:3433 +80:2:3437 +81:2:3441 +82:2:3442 +83:2:3446 +84:2:3454 +85:2:3455 +86:2:3459 +87:2:3463 +88:2:3464 +89:2:3459 +90:2:3460 +91:2:3468 +92:0:4629 +93:2:3295 +94:0:4629 +95:2:3476 +96:2:3477 +97:2:3478 +98:0:4629 +99:2:3295 +100:0:4629 +101:2:3483 +102:0:4629 +103:2:4186 +104:2:4187 +105:2:4191 +106:2:4195 +107:2:4196 +108:2:4200 +109:2:4205 +110:2:4213 +111:2:4217 +112:2:4218 +113:2:4213 +114:2:4217 +115:2:4218 +116:2:4222 +117:2:4229 +118:2:4236 +119:2:4237 +120:2:4244 +121:2:4249 +122:2:4256 +123:2:4257 +124:2:4256 +125:2:4257 +126:2:4264 +127:2:4268 +128:0:4629 +129:2:3485 +130:2:4167 +131:0:4629 +132:2:3295 +133:0:4629 +134:2:3486 +135:0:4629 +136:2:3295 +137:0:4629 +138:2:3489 +139:2:3490 +140:2:3494 +141:2:3495 +142:2:3503 +143:2:3504 +144:2:3508 +145:2:3509 +146:2:3517 +147:2:3522 +148:2:3526 +149:2:3527 +150:2:3535 +151:2:3536 +152:2:3540 +153:2:3541 +154:2:3535 +155:2:3536 +156:2:3540 +157:2:3541 +158:2:3549 +159:2:3554 +160:2:3555 +161:2:3566 +162:2:3567 +163:2:3568 +164:2:3579 +165:2:3584 +166:2:3585 +167:2:3596 +168:2:3597 +169:2:3598 +170:2:3596 +171:2:3597 +172:2:3598 +173:2:3609 +174:2:3616 +175:0:4629 +176:2:3295 +177:0:4629 +178:2:3620 +179:2:3621 +180:2:3622 +181:2:3634 +182:2:3635 +183:2:3639 +184:2:3640 +185:2:3648 +186:2:3653 +187:2:3657 +188:2:3658 +189:2:3666 +190:2:3667 +191:2:3671 +192:2:3672 +193:2:3666 +194:2:3667 +195:2:3671 +196:2:3672 +197:2:3680 +198:2:3685 +199:2:3686 +200:2:3697 +201:2:3698 +202:2:3699 +203:2:3710 +204:2:3715 +205:2:3716 +206:2:3727 +207:2:3728 +208:2:3729 +209:2:3727 +210:2:3728 +211:2:3729 +212:2:3740 +213:2:3751 +214:2:3752 +215:0:4629 +216:2:3295 +217:0:4629 +218:2:3758 +219:2:3759 +220:2:3763 +221:2:3764 +222:2:3772 +223:2:3773 +224:2:3777 +225:2:3778 +226:2:3786 +227:2:3791 +228:2:3795 +229:2:3796 +230:2:3804 +231:2:3805 +232:2:3809 +233:2:3810 +234:2:3804 +235:2:3805 +236:2:3809 +237:2:3810 +238:2:3818 +239:2:3823 +240:2:3824 +241:2:3835 +242:2:3836 +243:2:3837 +244:2:3848 +245:2:3853 +246:2:3854 +247:2:3865 +248:2:3866 +249:2:3867 +250:2:3865 +251:2:3866 +252:2:3867 +253:2:3878 +254:0:4629 +255:2:3295 +256:0:4629 +257:2:3887 +258:2:3888 +259:2:3892 +260:2:3893 +261:2:3901 +262:2:3902 +263:2:3906 +264:2:3907 +265:2:3915 +266:2:3920 +267:2:3924 +268:2:3925 +269:2:3933 +270:2:3934 +271:2:3938 +272:2:3939 +273:2:3933 +274:2:3934 +275:2:3938 +276:2:3939 +277:2:3947 +278:2:3952 +279:2:3953 +280:2:3964 +281:2:3965 +282:2:3966 +283:2:3977 +284:2:3982 +285:2:3983 +286:2:3994 +287:2:3995 +288:2:3996 +289:2:3994 +290:2:3995 +291:2:3996 +292:2:4007 +293:2:4014 +294:0:4629 +295:2:3295 +296:0:4629 +297:2:4018 +298:2:4019 +299:2:4020 +300:2:4032 +301:2:4033 +302:2:4037 +303:2:4038 +304:2:4046 +305:2:4051 +306:2:4055 +307:2:4056 +308:2:4064 +309:2:4065 +310:2:4069 +311:2:4070 +312:2:4064 +313:2:4065 +314:2:4069 +315:2:4070 +316:2:4078 +317:2:4083 +318:2:4084 +319:2:4095 +320:2:4096 +321:2:4097 +322:2:4108 +323:2:4113 +324:2:4114 +325:2:4125 +326:2:4126 +327:2:4127 +328:2:4125 +329:2:4126 +330:2:4127 +331:2:4138 +332:2:4148 +333:2:4149 +334:0:4629 +335:2:3295 +336:0:4629 +337:2:4155 +338:0:4629 +339:2:4459 +340:2:4460 +341:2:4464 +342:2:4468 +343:2:4469 +344:2:4473 +345:2:4481 +346:2:4482 +347:2:4486 +348:2:4490 +349:2:4491 +350:2:4486 +351:2:4490 +352:2:4491 +353:2:4495 +354:2:4502 +355:2:4509 +356:2:4510 +357:2:4517 +358:2:4522 +359:2:4529 +360:2:4530 +361:2:4529 +362:2:4530 +363:2:4537 +364:2:4541 +365:0:4629 +366:2:4157 +367:2:4167 +368:0:4629 +369:2:3295 +370:0:4629 +371:2:4158 +372:2:4159 +373:0:4629 +374:2:3295 +375:0:4629 +376:2:4163 +377:0:4629 +378:2:4171 +379:0:4629 +380:2:3292 +381:0:4629 +382:2:3294 +383:0:4629 +384:2:3295 +385:0:4629 +386:2:3296 +387:2:3297 +388:2:3301 +389:2:3302 +390:2:3310 +391:2:3311 +392:2:3315 +393:2:3316 +394:2:3324 +395:2:3329 +396:2:3333 +397:2:3334 +398:2:3342 +399:2:3343 +400:2:3344 +401:2:3342 +402:2:3343 +403:2:3347 +404:2:3348 +405:2:3356 +406:2:3361 +407:2:3362 +408:2:3373 +409:2:3374 +410:2:3375 +411:2:3386 +412:2:3391 +413:2:3392 +414:2:3403 +415:2:3404 +416:2:3405 +417:2:3403 +418:2:3404 +419:2:3405 +420:2:3416 +421:2:3424 +422:0:4629 +423:2:3295 +424:0:4629 +425:2:3428 +426:2:3432 +427:2:3433 +428:2:3437 +429:2:3441 +430:2:3442 +431:2:3446 +432:2:3454 +433:2:3455 +434:2:3459 +435:2:3460 +436:2:3459 +437:2:3463 +438:2:3464 +439:2:3468 +440:0:4629 +441:2:3295 +442:0:4629 +443:2:3476 +444:2:3477 +445:2:3478 +446:0:4629 +447:2:3295 +448:0:4629 +449:2:3483 +450:0:4629 +451:2:4186 +452:2:4187 +453:2:4191 +454:2:4195 +455:2:4196 +456:2:4200 +457:2:4205 +458:2:4213 +459:2:4217 +460:2:4218 +461:2:4213 +462:2:4217 +463:2:4218 +464:2:4222 +465:2:4229 +466:2:4236 +467:2:4237 +468:2:4244 +469:2:4249 +470:2:4256 +471:2:4257 +472:2:4256 +473:2:4257 +474:2:4264 +475:2:4268 +476:0:4629 +477:2:3485 +478:2:4167 +479:0:4629 +480:2:3295 +481:0:4629 +482:2:3486 +483:0:4629 +484:2:3295 +485:0:4629 +486:2:3489 +487:2:3490 +488:2:3494 +489:2:3495 +490:2:3503 +491:2:3504 +492:2:3508 +493:2:3509 +494:2:3517 +495:2:3522 +496:2:3526 +497:2:3527 +498:2:3535 +499:2:3536 +500:2:3540 +501:2:3541 +502:2:3535 +503:2:3536 +504:2:3540 +505:2:3541 +506:2:3549 +507:2:3554 +508:2:3555 +509:2:3566 +510:2:3567 +511:2:3568 +512:2:3579 +513:2:3584 +514:2:3585 +515:2:3596 +516:2:3597 +517:2:3598 +518:2:3596 +519:2:3597 +520:2:3598 +521:2:3609 +522:2:3616 +523:0:4629 +524:2:3295 +525:0:4629 +526:2:3620 +527:2:3621 +528:2:3622 +529:2:3634 +530:2:3635 +531:2:3639 +532:2:3640 +533:2:3648 +534:2:3653 +535:2:3657 +536:2:3658 +537:2:3666 +538:2:3667 +539:2:3671 +540:2:3672 +541:2:3666 +542:2:3667 +543:2:3671 +544:2:3672 +545:2:3680 +546:2:3685 +547:2:3686 +548:2:3697 +549:2:3698 +550:2:3699 +551:2:3710 +552:2:3715 +553:2:3716 +554:2:3727 +555:2:3728 +556:2:3729 +557:2:3727 +558:2:3728 +559:2:3729 +560:2:3740 +561:2:3751 +562:2:3752 +563:0:4629 +564:2:3295 +565:0:4629 +566:2:3758 +567:2:3759 +568:2:3763 +569:2:3764 +570:2:3772 +571:2:3773 +572:2:3777 +573:2:3778 +574:2:3786 +575:2:3791 +576:2:3795 +577:2:3796 +578:2:3804 +579:2:3805 +580:2:3809 +581:2:3810 +582:2:3804 +583:2:3805 +584:2:3809 +585:2:3810 +586:2:3818 +587:2:3823 +588:2:3824 +589:2:3835 +590:2:3836 +591:2:3837 +592:2:3848 +593:2:3853 +594:2:3854 +595:2:3865 +596:2:3866 +597:2:3867 +598:2:3865 +599:2:3866 +600:2:3867 +601:2:3878 +602:0:4629 +603:2:3295 +604:0:4629 +605:2:3887 +606:2:3888 +607:2:3892 +608:2:3893 +609:2:3901 +610:2:3902 +611:2:3906 +612:2:3907 +613:2:3915 +614:2:3920 +615:2:3924 +616:2:3925 +617:2:3933 +618:2:3934 +619:2:3938 +620:2:3939 +621:2:3933 +622:2:3934 +623:2:3938 +624:2:3939 +625:2:3947 +626:2:3952 +627:2:3953 +628:2:3964 +629:2:3965 +630:2:3966 +631:2:3977 +632:2:3982 +633:2:3983 +634:2:3994 +635:2:3995 +636:2:3996 +637:2:3994 +638:2:3995 +639:2:3996 +640:2:4007 +641:2:4014 +642:0:4629 +643:2:3295 +644:0:4629 +645:2:4018 +646:2:4019 +647:2:4020 +648:2:4032 +649:2:4033 +650:2:4037 +651:2:4038 +652:2:4046 +653:2:4051 +654:2:4055 +655:2:4056 +656:2:4064 +657:2:4065 +658:2:4069 +659:2:4070 +660:2:4064 +661:2:4065 +662:2:4069 +663:2:4070 +664:2:4078 +665:2:4083 +666:2:4084 +667:2:4095 +668:2:4096 +669:2:4097 +670:2:4108 +671:2:4113 +672:2:4114 +673:2:4125 +674:2:4126 +675:2:4127 +676:2:4125 +677:2:4126 +678:2:4127 +679:2:4138 +680:2:4148 +681:2:4149 +682:0:4629 +683:2:3295 +684:0:4629 +685:2:4155 +686:0:4629 +687:2:4459 +688:2:4460 +689:2:4464 +690:2:4468 +691:2:4469 +692:2:4473 +693:2:4481 +694:2:4482 +695:2:4486 +696:2:4490 +697:2:4491 +698:2:4486 +699:2:4490 +700:2:4491 +701:2:4495 +702:2:4502 +703:2:4509 +704:2:4510 +705:2:4517 +706:2:4522 +707:2:4529 +708:2:4530 +709:2:4529 +710:2:4530 +711:2:4537 +712:2:4541 +713:0:4629 +714:2:4157 +715:2:4167 +716:0:4629 +717:2:3295 +718:0:4629 +719:2:4158 +720:2:4159 +721:0:4629 +722:2:3295 +723:0:4629 +724:2:4163 +725:0:4629 +726:2:4171 +727:0:4629 +728:2:3292 +729:0:4629 +730:2:3294 +731:0:4629 +732:2:3295 +733:0:4629 +734:2:3296 +735:2:3297 +736:2:3301 +737:2:3302 +738:2:3310 +739:2:3311 +740:2:3315 +741:2:3316 +742:2:3324 +743:2:3329 +744:2:3333 +745:2:3334 +746:2:3342 +747:2:3343 +748:2:3347 +749:2:3348 +750:2:3342 +751:2:3343 +752:2:3344 +753:2:3356 +754:2:3361 +755:2:3362 +756:2:3373 +757:2:3374 +758:2:3375 +759:2:3386 +760:2:3391 +761:2:3392 +762:2:3403 +763:2:3404 +764:2:3405 +765:2:3403 +766:2:3404 +767:2:3405 +768:2:3416 +769:2:3424 +770:0:4629 +771:2:3295 +772:0:4629 +773:1:2 +774:0:4629 +775:1:8 +776:0:4629 +777:1:9 +778:0:4629 +779:1:10 +780:0:4629 +781:1:11 +782:0:4629 +783:1:12 +784:1:13 +785:1:17 +786:1:18 +787:1:26 +788:1:27 +789:1:31 +790:1:32 +791:1:40 +792:1:45 +793:1:49 +794:1:50 +795:1:58 +796:1:59 +797:1:63 +798:1:64 +799:1:58 +800:1:59 +801:1:63 +802:1:64 +803:1:72 +804:1:77 +805:1:78 +806:1:89 +807:1:90 +808:1:91 +809:1:102 +810:1:107 +811:1:108 +812:1:119 +813:1:120 +814:1:121 +815:1:119 +816:1:120 +817:1:121 +818:1:132 +819:0:4629 +820:1:11 +821:0:4629 +822:1:141 +823:1:142 +824:0:4629 +825:1:11 +826:0:4629 +827:1:148 +828:1:149 +829:1:153 +830:1:154 +831:1:162 +832:1:163 +833:1:167 +834:1:168 +835:1:176 +836:1:181 +837:1:185 +838:1:186 +839:1:194 +840:1:195 +841:1:199 +842:1:200 +843:1:194 +844:1:195 +845:1:199 +846:1:200 +847:1:208 +848:1:213 +849:1:214 +850:1:225 +851:1:226 +852:1:227 +853:1:238 +854:1:243 +855:1:244 +856:1:255 +857:1:256 +858:1:257 +859:1:255 +860:1:256 +861:1:257 +862:1:268 +863:0:4629 +864:1:11 +865:0:4629 +866:1:277 +867:1:278 +868:1:282 +869:1:283 +870:1:291 +871:1:292 +872:1:296 +873:1:297 +874:1:305 +875:1:310 +876:1:314 +877:1:315 +878:1:323 +879:1:324 +880:1:328 +881:1:329 +882:1:323 +883:1:324 +884:1:328 +885:1:329 +886:1:337 +887:1:342 +888:1:343 +889:1:354 +890:1:355 +891:1:356 +892:1:367 +893:1:372 +894:1:373 +895:1:384 +896:1:385 +897:1:386 +898:1:384 +899:1:385 +900:1:386 +901:1:397 +902:1:404 +903:0:4629 +904:1:11 +905:0:4629 +906:1:540 +907:1:544 +908:1:545 +909:1:549 +910:1:550 +911:1:558 +912:1:566 +913:1:567 +914:1:571 +915:1:575 +916:1:576 +917:1:571 +918:1:575 +919:1:576 +920:1:580 +921:1:587 +922:1:594 +923:1:595 +924:1:602 +925:1:607 +926:1:614 +927:1:615 +928:1:614 +929:1:615 +930:1:622 +931:0:4629 +932:1:11 +933:0:4629 +934:2:3428 +935:2:3432 +936:2:3433 +937:2:3437 +938:2:3441 +939:2:3442 +940:2:3446 +941:2:3454 +942:2:3455 +943:2:3459 +944:2:3463 +945:2:3464 +946:2:3459 +947:2:3460 +948:2:3468 +949:0:4629 +950:2:3295 +951:0:4629 +952:2:3476 +953:2:3477 +954:2:3478 +955:0:4629 +956:2:3295 +957:0:4629 +958:2:3483 +959:0:4629 +960:2:4186 +961:2:4187 +962:2:4191 +963:2:4195 +964:2:4196 +965:2:4200 +966:2:4205 +967:2:4213 +968:2:4217 +969:2:4218 +970:2:4213 +971:2:4217 +972:2:4218 +973:2:4222 +974:2:4229 +975:2:4236 +976:2:4237 +977:2:4244 +978:2:4249 +979:2:4256 +980:2:4257 +981:2:4256 +982:2:4257 +983:2:4264 +984:2:4268 +985:0:4629 +986:2:3485 +987:2:4167 +988:0:4629 +989:2:3295 +990:0:4629 +991:2:3486 +992:0:4629 +993:2:3295 +994:0:4629 +995:2:3489 +996:2:3490 +997:2:3494 +998:2:3495 +999:2:3503 +1000:2:3504 +1001:2:3508 +1002:2:3509 +1003:2:3517 +1004:2:3522 +1005:2:3526 +1006:2:3527 +1007:2:3535 +1008:2:3536 +1009:2:3540 +1010:2:3541 +1011:2:3535 +1012:2:3536 +1013:2:3540 +1014:2:3541 +1015:2:3549 +1016:2:3554 +1017:2:3555 +1018:2:3566 +1019:2:3567 +1020:2:3568 +1021:2:3579 +1022:2:3584 +1023:2:3585 +1024:2:3596 +1025:2:3597 +1026:2:3598 +1027:2:3596 +1028:2:3597 +1029:2:3598 +1030:2:3609 +1031:2:3616 +1032:0:4629 +1033:2:3295 +1034:0:4629 +1035:2:3620 +1036:2:3621 +1037:2:3622 +1038:2:3634 +1039:2:3635 +1040:2:3639 +1041:2:3640 +1042:2:3648 +1043:2:3653 +1044:2:3657 +1045:2:3658 +1046:2:3666 +1047:2:3667 +1048:2:3671 +1049:2:3672 +1050:2:3666 +1051:2:3667 +1052:2:3671 +1053:2:3672 +1054:2:3680 +1055:2:3685 +1056:2:3686 +1057:2:3697 +1058:2:3698 +1059:2:3699 +1060:2:3710 +1061:2:3715 +1062:2:3716 +1063:2:3727 +1064:2:3728 +1065:2:3729 +1066:2:3727 +1067:2:3728 +1068:2:3729 +1069:2:3740 +1070:2:3749 +1071:0:4629 +1072:2:3295 +1073:0:4629 +1074:2:3755 +1075:0:4629 +1076:2:4277 +1077:2:4278 +1078:2:4282 +1079:2:4286 +1080:2:4287 +1081:2:4291 +1082:2:4299 +1083:2:4300 +1084:2:4304 +1085:2:4308 +1086:2:4309 +1087:2:4304 +1088:2:4308 +1089:2:4309 +1090:2:4313 +1091:2:4320 +1092:2:4327 +1093:2:4328 +1094:2:4335 +1095:2:4340 +1096:2:4347 +1097:2:4348 +1098:2:4347 +1099:2:4348 +1100:2:4355 +1101:2:4359 +1102:0:4629 +1103:2:3757 +1104:2:4167 +1105:0:4629 +1106:2:3295 +1107:0:4629 +1108:1:632 +1109:1:633 +1110:1:637 +1111:1:638 +1112:1:646 +1113:1:647 +1114:1:651 +1115:1:652 +1116:1:660 +1117:1:665 +1118:1:669 +1119:1:670 +1120:1:678 +1121:1:679 +1122:1:683 +1123:1:684 +1124:1:678 +1125:1:679 +1126:1:683 +1127:1:684 +1128:1:692 +1129:1:697 +1130:1:698 +1131:1:709 +1132:1:710 +1133:1:711 +1134:1:722 +1135:1:727 +1136:1:728 +1137:1:739 +1138:1:740 +1139:1:741 +1140:1:739 +1141:1:747 +1142:1:748 +1143:1:752 +1144:0:4629 +1145:1:11 +1146:0:4629 +1147:2:3620 +1148:2:3621 +1149:2:3625 +1150:2:3626 +1151:2:3634 +1152:2:3635 +1153:2:3639 +1154:2:3640 +1155:2:3648 +1156:2:3653 +1157:2:3657 +1158:2:3658 +1159:2:3666 +1160:2:3667 +1161:2:3671 +1162:2:3672 +1163:2:3666 +1164:2:3667 +1165:2:3671 +1166:2:3672 +1167:2:3680 +1168:2:3685 +1169:2:3686 +1170:2:3697 +1171:2:3698 +1172:2:3699 +1173:2:3710 +1174:2:3715 +1175:2:3716 +1176:2:3727 +1177:2:3728 +1178:2:3729 +1179:2:3727 +1180:2:3728 +1181:2:3729 +1182:2:3740 +1183:2:3749 +1184:0:4629 +1185:2:3295 +1186:0:4629 +1187:2:3755 +1188:0:4629 +1189:2:4277 +1190:2:4278 +1191:2:4282 +1192:2:4286 +1193:2:4287 +1194:2:4291 +1195:2:4299 +1196:2:4300 +1197:2:4304 +1198:2:4308 +1199:2:4309 +1200:2:4304 +1201:2:4308 +1202:2:4309 +1203:2:4313 +1204:2:4320 +1205:2:4327 +1206:2:4328 +1207:2:4335 +1208:2:4340 +1209:2:4347 +1210:2:4348 +1211:2:4347 +1212:2:4348 +1213:2:4355 +1214:2:4359 +1215:0:4629 +1216:2:3757 +1217:2:4167 +1218:0:4629 +1219:1:761 +1220:1:764 +1221:1:765 +1222:0:4629 +1223:2:3295 +1224:0:4629 +1225:1:11 +1226:0:4629 +1227:2:3620 +1228:2:3621 +1229:2:3625 +1230:2:3626 +1231:2:3634 +1232:2:3635 +1233:2:3639 +1234:2:3640 +1235:2:3648 +1236:2:3653 +1237:2:3657 +1238:2:3658 +1239:2:3666 +1240:2:3667 +1241:2:3671 +1242:2:3672 +1243:2:3666 +1244:2:3667 +1245:2:3671 +1246:2:3672 +1247:2:3680 +1248:2:3685 +1249:2:3686 +1250:2:3697 +1251:2:3698 +1252:2:3699 +1253:2:3710 +1254:2:3715 +1255:2:3716 +1256:2:3727 +1257:2:3728 +1258:2:3729 +1259:2:3727 +1260:2:3728 +1261:2:3729 +1262:2:3740 +1263:2:3749 +1264:0:4629 +1265:2:3295 +1266:0:4629 +1267:2:3755 +1268:0:4629 +1269:2:4277 +1270:2:4278 +1271:2:4282 +1272:2:4286 +1273:2:4287 +1274:2:4291 +1275:2:4299 +1276:2:4300 +1277:2:4304 +1278:2:4308 +1279:2:4309 +1280:2:4304 +1281:2:4308 +1282:2:4309 +1283:2:4313 +1284:2:4320 +1285:2:4327 +1286:2:4328 +1287:2:4335 +1288:2:4340 +1289:2:4347 +1290:2:4348 +1291:2:4347 +1292:2:4348 +1293:2:4355 +1294:2:4359 +1295:0:4629 +1296:2:3757 +1297:2:4167 +1298:0:4629 +1299:1:1028 +1300:1:1029 +1301:1:1033 +1302:1:1034 +1303:1:1042 +1304:1:1043 +1305:1:1047 +1306:1:1048 +1307:1:1056 +1308:1:1061 +1309:1:1065 +1310:1:1066 +1311:1:1074 +1312:1:1075 +1313:1:1079 +1314:1:1080 +1315:1:1074 +1316:1:1075 +1317:1:1079 +1318:1:1080 +1319:1:1088 +1320:1:1093 +1321:1:1094 +1322:1:1105 +1323:1:1106 +1324:1:1107 +1325:1:1118 +1326:1:1123 +1327:1:1124 +1328:1:1135 +1329:1:1136 +1330:1:1137 +1331:1:1135 +1332:1:1143 +1333:1:1144 +1334:1:1148 +1335:1:1155 +1336:1:1159 +1337:0:4629 +1338:2:3295 +1339:0:4629 +1340:1:11 +1341:0:4629 +1342:2:3620 +1343:2:3621 +1344:2:3625 +1345:2:3626 +1346:2:3634 +1347:2:3635 +1348:2:3639 +1349:2:3640 +1350:2:3648 +1351:2:3653 +1352:2:3657 +1353:2:3658 +1354:2:3666 +1355:2:3667 +1356:2:3671 +1357:2:3672 +1358:2:3666 +1359:2:3667 +1360:2:3671 +1361:2:3672 +1362:2:3680 +1363:2:3685 +1364:2:3686 +1365:2:3697 +1366:2:3698 +1367:2:3699 +1368:2:3710 +1369:2:3715 +1370:2:3716 +1371:2:3727 +1372:2:3728 +1373:2:3729 +1374:2:3727 +1375:2:3728 +1376:2:3729 +1377:2:3740 +1378:2:3749 +1379:0:4629 +1380:2:3295 +1381:0:4629 +1382:2:3755 +1383:0:4629 +1384:2:4277 +1385:2:4278 +1386:2:4282 +1387:2:4286 +1388:2:4287 +1389:2:4291 +1390:2:4299 +1391:2:4300 +1392:2:4304 +1393:2:4308 +1394:2:4309 +1395:2:4304 +1396:2:4308 +1397:2:4309 +1398:2:4313 +1399:2:4320 +1400:2:4327 +1401:2:4328 +1402:2:4335 +1403:2:4340 +1404:2:4347 +1405:2:4348 +1406:2:4347 +1407:2:4348 +1408:2:4355 +1409:2:4359 +1410:0:4629 +1411:2:3757 +1412:2:4167 +1413:0:4629 +1414:1:1160 +1415:1:1161 +1416:1:1165 +1417:1:1166 +1418:1:1174 +1419:1:1175 +1420:1:1176 +1421:1:1188 +1422:1:1193 +1423:1:1197 +1424:1:1198 +1425:1:1206 +1426:1:1207 +1427:1:1211 +1428:1:1212 +1429:1:1206 +1430:1:1207 +1431:1:1211 +1432:1:1212 +1433:1:1220 +1434:1:1225 +1435:1:1226 +1436:1:1237 +1437:1:1238 +1438:1:1239 +1439:1:1250 +1440:1:1255 +1441:1:1256 +1442:1:1267 +1443:1:1268 +1444:1:1269 +1445:1:1267 +1446:1:1275 +1447:1:1276 +1448:1:1280 +1449:0:4629 +1450:2:3295 +1451:0:4629 +1452:1:11 +1453:0:4629 +1454:2:3620 +1455:2:3621 +1456:2:3625 +1457:2:3626 +1458:2:3634 +1459:2:3635 +1460:2:3639 +1461:2:3640 +1462:2:3648 +1463:2:3653 +1464:2:3657 +1465:2:3658 +1466:2:3666 +1467:2:3667 +1468:2:3671 +1469:2:3672 +1470:2:3666 +1471:2:3667 +1472:2:3671 +1473:2:3672 +1474:2:3680 +1475:2:3685 +1476:2:3686 +1477:2:3697 +1478:2:3698 +1479:2:3699 +1480:2:3710 +1481:2:3715 +1482:2:3716 +1483:2:3727 +1484:2:3728 +1485:2:3729 +1486:2:3727 +1487:2:3728 +1488:2:3729 +1489:2:3740 +1490:2:3749 +1491:0:4629 +1492:2:3295 +1493:0:4629 +1494:2:3755 +1495:0:4629 +1496:2:4277 +1497:2:4278 +1498:2:4282 +1499:2:4286 +1500:2:4287 +1501:2:4291 +1502:2:4299 +1503:2:4300 +1504:2:4304 +1505:2:4308 +1506:2:4309 +1507:2:4304 +1508:2:4308 +1509:2:4309 +1510:2:4313 +1511:2:4320 +1512:2:4327 +1513:2:4328 +1514:2:4335 +1515:2:4340 +1516:2:4347 +1517:2:4348 +1518:2:4347 +1519:2:4348 +1520:2:4355 +1521:2:4359 +1522:0:4629 +1523:2:3757 +1524:2:4167 +1525:0:4629 +1526:2:3295 +1527:0:4629 +1528:1:1289 +1529:0:4629 +1530:2:3620 +1531:2:3621 +1532:2:3625 +1533:2:3626 +1534:2:3634 +1535:2:3635 +1536:2:3639 +1537:2:3640 +1538:2:3648 +1539:2:3653 +1540:2:3657 +1541:2:3658 +1542:2:3666 +1543:2:3667 +1544:2:3671 +1545:2:3672 +1546:2:3666 +1547:2:3667 +1548:2:3671 +1549:2:3672 +1550:2:3680 +1551:2:3685 +1552:2:3686 +1553:2:3697 +1554:2:3698 +1555:2:3699 +1556:2:3710 +1557:2:3715 +1558:2:3716 +1559:2:3727 +1560:2:3728 +1561:2:3729 +1562:2:3727 +1563:2:3728 +1564:2:3729 +1565:2:3740 +1566:2:3749 +1567:0:4629 +1568:2:3295 +1569:0:4629 +1570:2:3755 +1571:0:4629 +1572:2:4277 +1573:2:4278 +1574:2:4282 +1575:2:4286 +1576:2:4287 +1577:2:4291 +1578:2:4299 +1579:2:4300 +1580:2:4304 +1581:2:4308 +1582:2:4309 +1583:2:4304 +1584:2:4308 +1585:2:4309 +1586:2:4313 +1587:2:4320 +1588:2:4327 +1589:2:4328 +1590:2:4335 +1591:2:4340 +1592:2:4347 +1593:2:4348 +1594:2:4347 +1595:2:4348 +1596:2:4355 +1597:2:4359 +1598:0:4629 +1599:2:3757 +1600:2:4167 +1601:0:4629 +1602:1:3023 +1603:1:3027 +1604:1:3028 +1605:1:3036 +1606:1:3037 +1607:1:3041 +1608:1:3042 +1609:1:3050 +1610:1:3055 +1611:1:3059 +1612:1:3060 +1613:1:3068 +1614:1:3069 +1615:1:3073 +1616:1:3074 +1617:1:3068 +1618:1:3069 +1619:1:3073 +1620:1:3074 +1621:1:3082 +1622:1:3087 +1623:1:3088 +1624:1:3099 +1625:1:3100 +1626:1:3101 +1627:1:3112 +1628:1:3117 +1629:1:3118 +1630:1:3129 +1631:1:3130 +1632:1:3131 +1633:1:3129 +1634:1:3137 +1635:1:3138 +1636:1:3142 +1637:1:3146 +1638:0:4629 +1639:2:3295 +1640:0:4629 +1641:2:3620 +1642:2:3621 +1643:2:3625 +1644:2:3626 +1645:2:3634 +1646:2:3635 +1647:2:3639 +1648:2:3640 +1649:2:3648 +1650:2:3653 +1651:2:3657 +1652:2:3658 +1653:2:3666 +1654:2:3667 +1655:2:3671 +1656:2:3672 +1657:2:3666 +1658:2:3667 +1659:2:3671 +1660:2:3672 +1661:2:3680 +1662:2:3685 +1663:2:3686 +1664:2:3697 +1665:2:3698 +1666:2:3699 +1667:2:3710 +1668:2:3715 +1669:2:3716 +1670:2:3727 +1671:2:3728 +1672:2:3729 +1673:2:3727 +1674:2:3728 +1675:2:3729 +1676:2:3740 +1677:2:3749 +1678:0:4629 +1679:2:3295 +1680:0:4629 +1681:2:3755 +1682:0:4629 +1683:2:4277 +1684:2:4278 +1685:2:4282 +1686:2:4286 +1687:2:4287 +1688:2:4291 +1689:2:4299 +1690:2:4300 +1691:2:4304 +1692:2:4308 +1693:2:4309 +1694:2:4304 +1695:2:4308 +1696:2:4309 +1697:2:4313 +1698:2:4320 +1699:2:4327 +1700:2:4328 +1701:2:4335 +1702:2:4340 +1703:2:4347 +1704:2:4348 +1705:2:4347 +1706:2:4348 +1707:2:4355 +1708:2:4359 +1709:0:4629 +1710:1:1291 +1711:1:1292 +1712:0:4627 +1713:1:11 +1714:0:4633 +1715:1:208 diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_wmb.define b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_wmb.define new file mode 100644 index 0000000..710f29d --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_wmb.define @@ -0,0 +1 @@ +#define NO_WMB diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_wmb.log b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_wmb.log new file mode 100644 index 0000000..4f2bfe6 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_wmb.log @@ -0,0 +1,552 @@ +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define >> pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_free.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_free_no_wmb.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1258) +Depth= 4637 States= 1e+06 Transitions= 4.63e+08 Memory= 550.432 t= 580 R= 2e+03 +pan: claim violated! (at depth 1199) +pan: wrote .input.spin.trail + +(Spin Version 5.1.7 -- 23 December 2008) +Warning: Search not completed + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness disabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 4637, errors: 1 + 1676215 states, stored +7.6378297e+08 states, matched +7.6545918e+08 transitions (= stored+matched) +4.5297646e+09 atomic steps +hash conflicts: 3.184152e+08 (resolved) + +Stats on memory usage (in Megabytes): + 185.433 equivalent memory usage for states (stored*(State-vector + overhead)) + 141.544 actual memory usage for states (compression: 76.33%) + state-vector as stored = 61 byte + 28 byte overhead + 8.000 memory used for hash table (-w20) + 457.764 memory used for DFS stack (-m10000000) + 607.170 total actual memory usage + +unreached in proctype urcu_reader + line 395, "pan.___", state 17, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 49, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 63, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 82, "(1)" + line 421, "pan.___", state 112, "(1)" + line 425, "pan.___", state 125, "(1)" + line 576, "pan.___", state 146, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 395, "pan.___", state 153, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 185, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 199, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 218, "(1)" + line 421, "pan.___", state 248, "(1)" + line 425, "pan.___", state 261, "(1)" + line 395, "pan.___", state 282, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 314, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 328, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 347, "(1)" + line 421, "pan.___", state 377, "(1)" + line 425, "pan.___", state 390, "(1)" + line 395, "pan.___", state 413, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 415, "(1)" + line 395, "pan.___", state 416, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 416, "else" + line 395, "pan.___", state 419, "(1)" + line 399, "pan.___", state 427, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 429, "(1)" + line 399, "pan.___", state 430, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 430, "else" + line 399, "pan.___", state 433, "(1)" + line 399, "pan.___", state 434, "(1)" + line 399, "pan.___", state 434, "(1)" + line 397, "pan.___", state 439, "((i<1))" + line 397, "pan.___", state 439, "((i>=1))" + line 404, "pan.___", state 445, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 447, "(1)" + line 404, "pan.___", state 448, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 448, "else" + line 404, "pan.___", state 451, "(1)" + line 404, "pan.___", state 452, "(1)" + line 404, "pan.___", state 452, "(1)" + line 408, "pan.___", state 459, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 461, "(1)" + line 408, "pan.___", state 462, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 462, "else" + line 408, "pan.___", state 465, "(1)" + line 408, "pan.___", state 466, "(1)" + line 408, "pan.___", state 466, "(1)" + line 406, "pan.___", state 471, "((i<2))" + line 406, "pan.___", state 471, "((i>=2))" + line 412, "pan.___", state 478, "(1)" + line 412, "pan.___", state 479, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 479, "else" + line 412, "pan.___", state 482, "(1)" + line 412, "pan.___", state 483, "(1)" + line 412, "pan.___", state 483, "(1)" + line 416, "pan.___", state 491, "(1)" + line 416, "pan.___", state 492, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 492, "else" + line 416, "pan.___", state 495, "(1)" + line 416, "pan.___", state 496, "(1)" + line 416, "pan.___", state 496, "(1)" + line 414, "pan.___", state 501, "((i<1))" + line 414, "pan.___", state 501, "((i>=1))" + line 421, "pan.___", state 508, "(1)" + line 421, "pan.___", state 509, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 509, "else" + line 421, "pan.___", state 512, "(1)" + line 421, "pan.___", state 513, "(1)" + line 421, "pan.___", state 513, "(1)" + line 425, "pan.___", state 521, "(1)" + line 425, "pan.___", state 522, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 522, "else" + line 425, "pan.___", state 525, "(1)" + line 425, "pan.___", state 526, "(1)" + line 425, "pan.___", state 526, "(1)" + line 423, "pan.___", state 531, "((i<2))" + line 423, "pan.___", state 531, "((i>=2))" + line 430, "pan.___", state 535, "(1)" + line 430, "pan.___", state 535, "(1)" + line 576, "pan.___", state 538, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 576, "pan.___", state 539, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 576, "pan.___", state 540, "(1)" + line 250, "pan.___", state 544, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 555, "(1)" + line 258, "pan.___", state 566, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 575, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 591, "(1)" + line 231, "pan.___", state 599, "(1)" + line 235, "pan.___", state 611, "(1)" + line 239, "pan.___", state 619, "(1)" + line 395, "pan.___", state 637, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 651, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 669, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 683, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 702, "(1)" + line 416, "pan.___", state 715, "(1)" + line 421, "pan.___", state 732, "(1)" + line 425, "pan.___", state 745, "(1)" + line 395, "pan.___", state 773, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 775, "(1)" + line 395, "pan.___", state 776, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 776, "else" + line 395, "pan.___", state 779, "(1)" + line 399, "pan.___", state 787, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 789, "(1)" + line 399, "pan.___", state 790, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 790, "else" + line 399, "pan.___", state 793, "(1)" + line 399, "pan.___", state 794, "(1)" + line 399, "pan.___", state 794, "(1)" + line 397, "pan.___", state 799, "((i<1))" + line 397, "pan.___", state 799, "((i>=1))" + line 404, "pan.___", state 805, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 807, "(1)" + line 404, "pan.___", state 808, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 808, "else" + line 404, "pan.___", state 811, "(1)" + line 404, "pan.___", state 812, "(1)" + line 404, "pan.___", state 812, "(1)" + line 408, "pan.___", state 819, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 821, "(1)" + line 408, "pan.___", state 822, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 822, "else" + line 408, "pan.___", state 825, "(1)" + line 408, "pan.___", state 826, "(1)" + line 408, "pan.___", state 826, "(1)" + line 406, "pan.___", state 831, "((i<2))" + line 406, "pan.___", state 831, "((i>=2))" + line 412, "pan.___", state 838, "(1)" + line 412, "pan.___", state 839, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 839, "else" + line 412, "pan.___", state 842, "(1)" + line 412, "pan.___", state 843, "(1)" + line 412, "pan.___", state 843, "(1)" + line 416, "pan.___", state 851, "(1)" + line 416, "pan.___", state 852, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 852, "else" + line 416, "pan.___", state 855, "(1)" + line 416, "pan.___", state 856, "(1)" + line 416, "pan.___", state 856, "(1)" + line 414, "pan.___", state 861, "((i<1))" + line 414, "pan.___", state 861, "((i>=1))" + line 421, "pan.___", state 868, "(1)" + line 421, "pan.___", state 869, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 869, "else" + line 421, "pan.___", state 872, "(1)" + line 421, "pan.___", state 873, "(1)" + line 421, "pan.___", state 873, "(1)" + line 425, "pan.___", state 881, "(1)" + line 425, "pan.___", state 882, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 882, "else" + line 425, "pan.___", state 885, "(1)" + line 425, "pan.___", state 886, "(1)" + line 425, "pan.___", state 886, "(1)" + line 430, "pan.___", state 895, "(1)" + line 430, "pan.___", state 895, "(1)" + line 395, "pan.___", state 902, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 904, "(1)" + line 395, "pan.___", state 905, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 905, "else" + line 395, "pan.___", state 908, "(1)" + line 399, "pan.___", state 916, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 918, "(1)" + line 399, "pan.___", state 919, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 919, "else" + line 399, "pan.___", state 922, "(1)" + line 399, "pan.___", state 923, "(1)" + line 399, "pan.___", state 923, "(1)" + line 397, "pan.___", state 928, "((i<1))" + line 397, "pan.___", state 928, "((i>=1))" + line 404, "pan.___", state 934, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 936, "(1)" + line 404, "pan.___", state 937, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 937, "else" + line 404, "pan.___", state 940, "(1)" + line 404, "pan.___", state 941, "(1)" + line 404, "pan.___", state 941, "(1)" + line 408, "pan.___", state 948, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 950, "(1)" + line 408, "pan.___", state 951, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 951, "else" + line 408, "pan.___", state 954, "(1)" + line 408, "pan.___", state 955, "(1)" + line 408, "pan.___", state 955, "(1)" + line 406, "pan.___", state 960, "((i<2))" + line 406, "pan.___", state 960, "((i>=2))" + line 412, "pan.___", state 967, "(1)" + line 412, "pan.___", state 968, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 968, "else" + line 412, "pan.___", state 971, "(1)" + line 412, "pan.___", state 972, "(1)" + line 412, "pan.___", state 972, "(1)" + line 416, "pan.___", state 980, "(1)" + line 416, "pan.___", state 981, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 981, "else" + line 416, "pan.___", state 984, "(1)" + line 416, "pan.___", state 985, "(1)" + line 416, "pan.___", state 985, "(1)" + line 414, "pan.___", state 990, "((i<1))" + line 414, "pan.___", state 990, "((i>=1))" + line 421, "pan.___", state 997, "(1)" + line 421, "pan.___", state 998, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 998, "else" + line 421, "pan.___", state 1001, "(1)" + line 421, "pan.___", state 1002, "(1)" + line 421, "pan.___", state 1002, "(1)" + line 425, "pan.___", state 1010, "(1)" + line 425, "pan.___", state 1011, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 1011, "else" + line 425, "pan.___", state 1014, "(1)" + line 425, "pan.___", state 1015, "(1)" + line 425, "pan.___", state 1015, "(1)" + line 423, "pan.___", state 1020, "((i<2))" + line 423, "pan.___", state 1020, "((i>=2))" + line 430, "pan.___", state 1024, "(1)" + line 430, "pan.___", state 1024, "(1)" + line 584, "pan.___", state 1028, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 395, "pan.___", state 1033, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1047, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1065, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1079, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1098, "(1)" + line 416, "pan.___", state 1111, "(1)" + line 421, "pan.___", state 1128, "(1)" + line 425, "pan.___", state 1141, "(1)" + line 395, "pan.___", state 1165, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1197, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1211, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1230, "(1)" + line 421, "pan.___", state 1260, "(1)" + line 425, "pan.___", state 1273, "(1)" + line 395, "pan.___", state 1298, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1330, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1344, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1363, "(1)" + line 421, "pan.___", state 1393, "(1)" + line 425, "pan.___", state 1406, "(1)" + line 395, "pan.___", state 1427, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1459, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1473, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1492, "(1)" + line 421, "pan.___", state 1522, "(1)" + line 425, "pan.___", state 1535, "(1)" + line 250, "pan.___", state 1558, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1580, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1589, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1605, "(1)" + line 231, "pan.___", state 1613, "(1)" + line 235, "pan.___", state 1625, "(1)" + line 239, "pan.___", state 1633, "(1)" + line 395, "pan.___", state 1651, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1665, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1683, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1697, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1716, "(1)" + line 416, "pan.___", state 1729, "(1)" + line 421, "pan.___", state 1746, "(1)" + line 425, "pan.___", state 1759, "(1)" + line 395, "pan.___", state 1780, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1794, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1812, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1826, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1845, "(1)" + line 416, "pan.___", state 1858, "(1)" + line 421, "pan.___", state 1875, "(1)" + line 425, "pan.___", state 1888, "(1)" + line 395, "pan.___", state 1912, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1928, "(1)" + line 404, "pan.___", state 1944, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1958, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1977, "(1)" + line 421, "pan.___", state 2007, "(1)" + line 425, "pan.___", state 2020, "(1)" + line 623, "pan.___", state 2041, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 395, "pan.___", state 2048, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2080, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2094, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2113, "(1)" + line 421, "pan.___", state 2143, "(1)" + line 425, "pan.___", state 2156, "(1)" + line 395, "pan.___", state 2177, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2209, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2223, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2242, "(1)" + line 421, "pan.___", state 2272, "(1)" + line 425, "pan.___", state 2285, "(1)" + line 395, "pan.___", state 2308, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 2310, "(1)" + line 395, "pan.___", state 2311, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 2311, "else" + line 395, "pan.___", state 2314, "(1)" + line 399, "pan.___", state 2322, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2324, "(1)" + line 399, "pan.___", state 2325, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 2325, "else" + line 399, "pan.___", state 2328, "(1)" + line 399, "pan.___", state 2329, "(1)" + line 399, "pan.___", state 2329, "(1)" + line 397, "pan.___", state 2334, "((i<1))" + line 397, "pan.___", state 2334, "((i>=1))" + line 404, "pan.___", state 2340, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2342, "(1)" + line 404, "pan.___", state 2343, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 2343, "else" + line 404, "pan.___", state 2346, "(1)" + line 404, "pan.___", state 2347, "(1)" + line 404, "pan.___", state 2347, "(1)" + line 408, "pan.___", state 2354, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2356, "(1)" + line 408, "pan.___", state 2357, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 2357, "else" + line 408, "pan.___", state 2360, "(1)" + line 408, "pan.___", state 2361, "(1)" + line 408, "pan.___", state 2361, "(1)" + line 406, "pan.___", state 2366, "((i<2))" + line 406, "pan.___", state 2366, "((i>=2))" + line 412, "pan.___", state 2373, "(1)" + line 412, "pan.___", state 2374, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 2374, "else" + line 412, "pan.___", state 2377, "(1)" + line 412, "pan.___", state 2378, "(1)" + line 412, "pan.___", state 2378, "(1)" + line 416, "pan.___", state 2386, "(1)" + line 416, "pan.___", state 2387, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 2387, "else" + line 416, "pan.___", state 2390, "(1)" + line 416, "pan.___", state 2391, "(1)" + line 416, "pan.___", state 2391, "(1)" + line 414, "pan.___", state 2396, "((i<1))" + line 414, "pan.___", state 2396, "((i>=1))" + line 421, "pan.___", state 2403, "(1)" + line 421, "pan.___", state 2404, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 2404, "else" + line 421, "pan.___", state 2407, "(1)" + line 421, "pan.___", state 2408, "(1)" + line 421, "pan.___", state 2408, "(1)" + line 425, "pan.___", state 2416, "(1)" + line 425, "pan.___", state 2417, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 2417, "else" + line 425, "pan.___", state 2420, "(1)" + line 425, "pan.___", state 2421, "(1)" + line 425, "pan.___", state 2421, "(1)" + line 423, "pan.___", state 2426, "((i<2))" + line 423, "pan.___", state 2426, "((i>=2))" + line 430, "pan.___", state 2430, "(1)" + line 430, "pan.___", state 2430, "(1)" + line 623, "pan.___", state 2433, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 623, "pan.___", state 2434, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 623, "pan.___", state 2435, "(1)" + line 250, "pan.___", state 2439, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 2450, "(1)" + line 258, "pan.___", state 2461, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 2470, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 2486, "(1)" + line 231, "pan.___", state 2494, "(1)" + line 235, "pan.___", state 2506, "(1)" + line 239, "pan.___", state 2514, "(1)" + line 395, "pan.___", state 2532, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2546, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2564, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2578, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2597, "(1)" + line 416, "pan.___", state 2610, "(1)" + line 421, "pan.___", state 2627, "(1)" + line 425, "pan.___", state 2640, "(1)" + line 250, "pan.___", state 2664, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 2673, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 2686, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 2695, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 2711, "(1)" + line 231, "pan.___", state 2719, "(1)" + line 235, "pan.___", state 2731, "(1)" + line 239, "pan.___", state 2739, "(1)" + line 395, "pan.___", state 2757, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2771, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2789, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2803, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2822, "(1)" + line 416, "pan.___", state 2835, "(1)" + line 421, "pan.___", state 2852, "(1)" + line 425, "pan.___", state 2865, "(1)" + line 395, "pan.___", state 2886, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2900, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2918, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2932, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2951, "(1)" + line 416, "pan.___", state 2964, "(1)" + line 421, "pan.___", state 2981, "(1)" + line 425, "pan.___", state 2994, "(1)" + line 227, "pan.___", state 3027, "(1)" + line 235, "pan.___", state 3047, "(1)" + line 239, "pan.___", state 3055, "(1)" + line 227, "pan.___", state 3070, "(1)" + line 231, "pan.___", state 3078, "(1)" + line 235, "pan.___", state 3090, "(1)" + line 239, "pan.___", state 3098, "(1)" + line 877, "pan.___", state 3115, "-end-" + (318 of 3115 states) +unreached in proctype urcu_writer + line 395, "pan.___", state 19, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 33, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 412, "pan.___", state 84, "(1)" + line 416, "pan.___", state 97, "(1)" + line 250, "pan.___", state 150, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 152, "(1)" + line 254, "pan.___", state 159, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 161, "(1)" + line 254, "pan.___", state 162, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 162, "else" + line 252, "pan.___", state 167, "((i<1))" + line 252, "pan.___", state 167, "((i>=1))" + line 258, "pan.___", state 172, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 174, "(1)" + line 258, "pan.___", state 175, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 175, "else" + line 262, "pan.___", state 181, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 183, "(1)" + line 262, "pan.___", state 184, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 184, "else" + line 267, "pan.___", state 193, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 267, "pan.___", state 193, "else" + line 395, "pan.___", state 212, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 226, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 244, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 258, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 277, "(1)" + line 416, "pan.___", state 290, "(1)" + line 421, "pan.___", state 307, "(1)" + line 425, "pan.___", state 320, "(1)" + line 399, "pan.___", state 357, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 375, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 389, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 421, "(1)" + line 421, "pan.___", state 438, "(1)" + line 425, "pan.___", state 451, "(1)" + line 399, "pan.___", state 495, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 513, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 527, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 559, "(1)" + line 421, "pan.___", state 576, "(1)" + line 425, "pan.___", state 589, "(1)" + line 399, "pan.___", state 624, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 642, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 656, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 688, "(1)" + line 421, "pan.___", state 705, "(1)" + line 425, "pan.___", state 718, "(1)" + line 399, "pan.___", state 755, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 773, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 787, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 819, "(1)" + line 421, "pan.___", state 836, "(1)" + line 425, "pan.___", state 849, "(1)" + line 250, "pan.___", state 904, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 913, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 227, "pan.___", state 951, "(1)" + line 231, "pan.___", state 959, "(1)" + line 235, "pan.___", state 971, "(1)" + line 239, "pan.___", state 979, "(1)" + line 254, "pan.___", state 1004, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1017, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1026, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1042, "(1)" + line 231, "pan.___", state 1050, "(1)" + line 235, "pan.___", state 1062, "(1)" + line 239, "pan.___", state 1070, "(1)" + line 254, "pan.___", state 1095, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1108, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1117, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1133, "(1)" + line 231, "pan.___", state 1141, "(1)" + line 235, "pan.___", state 1153, "(1)" + line 239, "pan.___", state 1161, "(1)" + line 254, "pan.___", state 1186, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1199, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1208, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1224, "(1)" + line 231, "pan.___", state 1232, "(1)" + line 235, "pan.___", state 1244, "(1)" + line 239, "pan.___", state 1252, "(1)" + line 1204, "pan.___", state 1267, "-end-" + (77 of 1267 states) +unreached in proctype :init: + line 1215, "pan.___", state 9, "((j<2))" + line 1215, "pan.___", state 9, "((j>=2))" + line 1216, "pan.___", state 20, "((j<2))" + line 1216, "pan.___", state 20, "((j>=2))" + line 1221, "pan.___", state 33, "((j<2))" + line 1221, "pan.___", state 33, "((j>=2))" + line 1219, "pan.___", state 43, "((i<1))" + line 1219, "pan.___", state 43, "((i>=1))" + line 1229, "pan.___", state 54, "((j<2))" + line 1229, "pan.___", state 54, "((j>=2))" + line 1233, "pan.___", state 67, "((j<2))" + line 1233, "pan.___", state 67, "((j>=2))" + (6 of 78 states) +unreached in proctype :never: + line 1263, "pan.___", state 8, "-end-" + (1 of 8 states) + +pan: elapsed time 966 seconds +pan: rate 1735.7692 states/second +pan: avg transition delay 1.2616e-06 usec +cp .input.spin urcu_free_no_wmb.spin.input +cp .input.spin.trail urcu_free_no_wmb.spin.input.trail diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_wmb.spin.input b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_wmb.spin.input new file mode 100644 index 0000000..e552903 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_wmb.spin.input @@ -0,0 +1,1240 @@ +#define NO_WMB + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +//#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_wmb.spin.input.trail b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_wmb.spin.input.trail new file mode 100644 index 0000000..0908988 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_no_wmb.spin.input.trail @@ -0,0 +1,1202 @@ +-2:3:-2 +-4:-4:-4 +1:0:4462 +2:3:4382 +3:3:4385 +4:3:4385 +5:3:4388 +6:3:4396 +7:3:4396 +8:3:4399 +9:3:4405 +10:3:4409 +11:3:4409 +12:3:4412 +13:3:4422 +14:3:4430 +15:3:4430 +16:3:4433 +17:3:4439 +18:3:4443 +19:3:4443 +20:3:4446 +21:3:4452 +22:3:4456 +23:3:4457 +24:0:4462 +25:3:4459 +26:0:4462 +27:2:3117 +28:0:4462 +29:2:3123 +30:0:4462 +31:2:3124 +32:0:4462 +33:2:3126 +34:0:4462 +35:2:3127 +36:0:4462 +37:2:3128 +38:0:4462 +39:2:3129 +40:2:3130 +41:2:3134 +42:2:3135 +43:2:3143 +44:2:3144 +45:2:3148 +46:2:3149 +47:2:3157 +48:2:3162 +49:2:3166 +50:2:3167 +51:2:3175 +52:2:3176 +53:2:3180 +54:2:3181 +55:2:3175 +56:2:3176 +57:2:3180 +58:2:3181 +59:2:3189 +60:2:3194 +61:2:3195 +62:2:3206 +63:2:3207 +64:2:3208 +65:2:3219 +66:2:3224 +67:2:3225 +68:2:3236 +69:2:3237 +70:2:3238 +71:2:3236 +72:2:3237 +73:2:3238 +74:2:3249 +75:2:3257 +76:0:4462 +77:2:3128 +78:0:4462 +79:2:3309 +80:2:3310 +81:2:3311 +82:0:4462 +83:2:3128 +84:0:4462 +85:2:3316 +86:0:4462 +87:2:4019 +88:2:4020 +89:2:4024 +90:2:4028 +91:2:4029 +92:2:4033 +93:2:4038 +94:2:4046 +95:2:4050 +96:2:4051 +97:2:4046 +98:2:4047 +99:2:4055 +100:2:4062 +101:2:4069 +102:2:4070 +103:2:4077 +104:2:4082 +105:2:4089 +106:2:4090 +107:2:4089 +108:2:4090 +109:2:4097 +110:2:4101 +111:0:4462 +112:2:3318 +113:2:4000 +114:0:4462 +115:2:3128 +116:0:4462 +117:2:3319 +118:0:4462 +119:2:3128 +120:0:4462 +121:2:3322 +122:2:3323 +123:2:3327 +124:2:3328 +125:2:3336 +126:2:3337 +127:2:3341 +128:2:3342 +129:2:3350 +130:2:3355 +131:2:3359 +132:2:3360 +133:2:3368 +134:2:3369 +135:2:3373 +136:2:3374 +137:2:3368 +138:2:3369 +139:2:3373 +140:2:3374 +141:2:3382 +142:2:3387 +143:2:3388 +144:2:3399 +145:2:3400 +146:2:3401 +147:2:3412 +148:2:3417 +149:2:3418 +150:2:3429 +151:2:3430 +152:2:3431 +153:2:3429 +154:2:3430 +155:2:3431 +156:2:3442 +157:2:3449 +158:0:4462 +159:2:3128 +160:0:4462 +161:2:3453 +162:2:3454 +163:2:3455 +164:2:3467 +165:2:3468 +166:2:3472 +167:2:3473 +168:2:3481 +169:2:3486 +170:2:3490 +171:2:3491 +172:2:3499 +173:2:3500 +174:2:3504 +175:2:3505 +176:2:3499 +177:2:3500 +178:2:3504 +179:2:3505 +180:2:3513 +181:2:3518 +182:2:3519 +183:2:3530 +184:2:3531 +185:2:3532 +186:2:3543 +187:2:3548 +188:2:3549 +189:2:3560 +190:2:3561 +191:2:3562 +192:2:3560 +193:2:3561 +194:2:3562 +195:2:3573 +196:2:3584 +197:2:3585 +198:0:4462 +199:2:3128 +200:0:4462 +201:2:3591 +202:2:3592 +203:2:3596 +204:2:3597 +205:2:3605 +206:2:3606 +207:2:3610 +208:2:3611 +209:2:3619 +210:2:3624 +211:2:3628 +212:2:3629 +213:2:3637 +214:2:3638 +215:2:3642 +216:2:3643 +217:2:3637 +218:2:3638 +219:2:3642 +220:2:3643 +221:2:3651 +222:2:3656 +223:2:3657 +224:2:3668 +225:2:3669 +226:2:3670 +227:2:3681 +228:2:3686 +229:2:3687 +230:2:3698 +231:2:3699 +232:2:3700 +233:2:3698 +234:2:3699 +235:2:3700 +236:2:3711 +237:0:4462 +238:2:3128 +239:0:4462 +240:2:3720 +241:2:3721 +242:2:3725 +243:2:3726 +244:2:3734 +245:2:3735 +246:2:3739 +247:2:3740 +248:2:3748 +249:2:3753 +250:2:3757 +251:2:3758 +252:2:3766 +253:2:3767 +254:2:3771 +255:2:3772 +256:2:3766 +257:2:3767 +258:2:3771 +259:2:3772 +260:2:3780 +261:2:3785 +262:2:3786 +263:2:3797 +264:2:3798 +265:2:3799 +266:2:3810 +267:2:3815 +268:2:3816 +269:2:3827 +270:2:3828 +271:2:3829 +272:2:3827 +273:2:3828 +274:2:3829 +275:2:3840 +276:2:3847 +277:0:4462 +278:2:3128 +279:0:4462 +280:2:3851 +281:2:3852 +282:2:3853 +283:2:3865 +284:2:3866 +285:2:3870 +286:2:3871 +287:2:3879 +288:2:3884 +289:2:3888 +290:2:3889 +291:2:3897 +292:2:3898 +293:2:3902 +294:2:3903 +295:2:3897 +296:2:3898 +297:2:3902 +298:2:3903 +299:2:3911 +300:2:3916 +301:2:3917 +302:2:3928 +303:2:3929 +304:2:3930 +305:2:3941 +306:2:3946 +307:2:3947 +308:2:3958 +309:2:3959 +310:2:3960 +311:2:3958 +312:2:3959 +313:2:3960 +314:2:3971 +315:2:3981 +316:2:3982 +317:0:4462 +318:2:3128 +319:0:4462 +320:2:3988 +321:0:4462 +322:2:4292 +323:2:4293 +324:2:4297 +325:2:4301 +326:2:4302 +327:2:4306 +328:2:4314 +329:2:4315 +330:2:4319 +331:2:4323 +332:2:4324 +333:2:4319 +334:2:4323 +335:2:4324 +336:2:4328 +337:2:4335 +338:2:4342 +339:2:4343 +340:2:4350 +341:2:4355 +342:2:4362 +343:2:4363 +344:2:4362 +345:2:4363 +346:2:4370 +347:2:4374 +348:0:4462 +349:2:3990 +350:2:4000 +351:0:4462 +352:2:3128 +353:0:4462 +354:2:3991 +355:2:3992 +356:0:4462 +357:2:3128 +358:0:4462 +359:2:3996 +360:0:4462 +361:2:4004 +362:0:4462 +363:2:3124 +364:0:4462 +365:2:3126 +366:0:4462 +367:2:3127 +368:0:4462 +369:2:3128 +370:0:4462 +371:2:3309 +372:2:3310 +373:2:3311 +374:0:4462 +375:2:3128 +376:0:4462 +377:2:3129 +378:2:3130 +379:2:3134 +380:2:3135 +381:2:3143 +382:2:3144 +383:2:3148 +384:2:3149 +385:2:3157 +386:2:3162 +387:2:3163 +388:2:3175 +389:2:3176 +390:2:3177 +391:2:3175 +392:2:3176 +393:2:3180 +394:2:3181 +395:2:3189 +396:2:3194 +397:2:3195 +398:2:3206 +399:2:3207 +400:2:3208 +401:2:3219 +402:2:3224 +403:2:3225 +404:2:3236 +405:2:3237 +406:2:3238 +407:2:3236 +408:2:3237 +409:2:3238 +410:2:3249 +411:2:3257 +412:0:4462 +413:2:3128 +414:0:4462 +415:2:3316 +416:0:4462 +417:2:4019 +418:2:4020 +419:2:4024 +420:2:4028 +421:2:4029 +422:2:4033 +423:2:4041 +424:2:4042 +425:2:4046 +426:2:4047 +427:2:4046 +428:2:4050 +429:2:4051 +430:2:4055 +431:2:4062 +432:2:4069 +433:2:4070 +434:2:4077 +435:2:4082 +436:2:4089 +437:2:4090 +438:2:4089 +439:2:4090 +440:2:4097 +441:2:4101 +442:0:4462 +443:2:3318 +444:2:4000 +445:0:4462 +446:2:3128 +447:0:4462 +448:2:3319 +449:0:4462 +450:2:3128 +451:0:4462 +452:2:3322 +453:2:3323 +454:2:3327 +455:2:3328 +456:2:3336 +457:2:3337 +458:2:3341 +459:2:3342 +460:2:3350 +461:2:3355 +462:2:3359 +463:2:3360 +464:2:3368 +465:2:3369 +466:2:3373 +467:2:3374 +468:2:3368 +469:2:3369 +470:2:3373 +471:2:3374 +472:2:3382 +473:2:3387 +474:2:3388 +475:2:3399 +476:2:3400 +477:2:3401 +478:2:3412 +479:2:3417 +480:2:3418 +481:2:3429 +482:2:3430 +483:2:3431 +484:2:3429 +485:2:3430 +486:2:3431 +487:2:3442 +488:2:3449 +489:0:4462 +490:2:3128 +491:0:4462 +492:2:3453 +493:2:3454 +494:2:3455 +495:2:3467 +496:2:3468 +497:2:3472 +498:2:3473 +499:2:3481 +500:2:3486 +501:2:3490 +502:2:3491 +503:2:3499 +504:2:3500 +505:2:3504 +506:2:3505 +507:2:3499 +508:2:3500 +509:2:3504 +510:2:3505 +511:2:3513 +512:2:3518 +513:2:3519 +514:2:3530 +515:2:3531 +516:2:3532 +517:2:3543 +518:2:3548 +519:2:3549 +520:2:3560 +521:2:3561 +522:2:3562 +523:2:3560 +524:2:3561 +525:2:3562 +526:2:3573 +527:2:3584 +528:2:3585 +529:0:4462 +530:2:3128 +531:0:4462 +532:2:3591 +533:2:3592 +534:2:3596 +535:2:3597 +536:2:3605 +537:2:3606 +538:2:3610 +539:2:3611 +540:2:3619 +541:2:3624 +542:2:3628 +543:2:3629 +544:2:3637 +545:2:3638 +546:2:3642 +547:2:3643 +548:2:3637 +549:2:3638 +550:2:3642 +551:2:3643 +552:2:3651 +553:2:3656 +554:2:3657 +555:2:3668 +556:2:3669 +557:2:3670 +558:2:3681 +559:2:3686 +560:2:3687 +561:2:3698 +562:2:3699 +563:2:3700 +564:2:3698 +565:2:3699 +566:2:3700 +567:2:3711 +568:0:4462 +569:2:3128 +570:0:4462 +571:2:3720 +572:2:3721 +573:2:3725 +574:2:3726 +575:2:3734 +576:2:3735 +577:2:3739 +578:2:3740 +579:2:3748 +580:2:3753 +581:2:3757 +582:2:3758 +583:2:3766 +584:2:3767 +585:2:3771 +586:2:3772 +587:2:3766 +588:2:3767 +589:2:3771 +590:2:3772 +591:2:3780 +592:2:3785 +593:2:3786 +594:2:3797 +595:2:3798 +596:2:3799 +597:2:3810 +598:2:3815 +599:2:3816 +600:2:3827 +601:2:3828 +602:2:3829 +603:2:3827 +604:2:3828 +605:2:3829 +606:2:3840 +607:2:3847 +608:0:4462 +609:2:3128 +610:0:4462 +611:2:3851 +612:2:3852 +613:2:3853 +614:2:3865 +615:2:3866 +616:2:3870 +617:2:3871 +618:2:3879 +619:2:3884 +620:2:3888 +621:2:3889 +622:2:3897 +623:2:3898 +624:2:3902 +625:2:3903 +626:2:3897 +627:2:3898 +628:2:3902 +629:2:3903 +630:2:3911 +631:2:3916 +632:2:3917 +633:2:3928 +634:2:3929 +635:2:3930 +636:2:3941 +637:2:3946 +638:2:3947 +639:2:3958 +640:2:3959 +641:2:3960 +642:2:3958 +643:2:3959 +644:2:3960 +645:2:3971 +646:2:3981 +647:2:3982 +648:0:4462 +649:2:3128 +650:0:4462 +651:2:3988 +652:0:4462 +653:2:4292 +654:2:4293 +655:2:4297 +656:2:4301 +657:2:4302 +658:2:4306 +659:2:4314 +660:2:4315 +661:2:4319 +662:2:4323 +663:2:4324 +664:2:4319 +665:2:4323 +666:2:4324 +667:2:4328 +668:2:4335 +669:2:4342 +670:2:4343 +671:2:4350 +672:2:4355 +673:2:4362 +674:2:4363 +675:2:4362 +676:2:4363 +677:2:4370 +678:2:4374 +679:0:4462 +680:2:3990 +681:2:4000 +682:0:4462 +683:2:3128 +684:0:4462 +685:2:3991 +686:2:3992 +687:0:4462 +688:2:3128 +689:0:4462 +690:2:3996 +691:0:4462 +692:2:4004 +693:0:4462 +694:2:3124 +695:0:4462 +696:2:3126 +697:0:4462 +698:2:3127 +699:0:4462 +700:2:3128 +701:0:4462 +702:2:3129 +703:2:3130 +704:2:3134 +705:2:3135 +706:2:3143 +707:2:3144 +708:2:3148 +709:2:3149 +710:2:3157 +711:2:3162 +712:2:3166 +713:2:3167 +714:2:3175 +715:2:3176 +716:2:3180 +717:2:3181 +718:2:3175 +719:2:3176 +720:2:3177 +721:2:3189 +722:2:3194 +723:2:3195 +724:2:3206 +725:2:3207 +726:2:3208 +727:2:3219 +728:2:3224 +729:2:3225 +730:2:3236 +731:2:3237 +732:2:3238 +733:2:3236 +734:2:3237 +735:2:3238 +736:2:3249 +737:2:3257 +738:0:4462 +739:2:3128 +740:0:4462 +741:2:3309 +742:2:3310 +743:2:3311 +744:0:4462 +745:2:3128 +746:0:4462 +747:2:3316 +748:0:4462 +749:1:2 +750:0:4462 +751:1:8 +752:0:4462 +753:1:9 +754:0:4462 +755:1:10 +756:0:4462 +757:1:11 +758:0:4462 +759:1:12 +760:1:13 +761:1:17 +762:1:18 +763:1:26 +764:1:27 +765:1:31 +766:1:32 +767:1:40 +768:1:45 +769:1:49 +770:1:50 +771:1:58 +772:1:59 +773:1:63 +774:1:64 +775:1:58 +776:1:59 +777:1:63 +778:1:64 +779:1:72 +780:1:77 +781:1:78 +782:1:89 +783:1:90 +784:1:91 +785:1:102 +786:1:107 +787:1:108 +788:1:119 +789:1:120 +790:1:121 +791:1:119 +792:1:120 +793:1:121 +794:1:132 +795:0:4462 +796:1:11 +797:0:4462 +798:1:141 +799:1:142 +800:0:4462 +801:1:11 +802:0:4462 +803:1:148 +804:1:149 +805:1:153 +806:1:154 +807:1:162 +808:1:163 +809:1:167 +810:1:168 +811:1:176 +812:1:181 +813:1:185 +814:1:186 +815:1:194 +816:1:195 +817:1:199 +818:1:200 +819:1:194 +820:1:195 +821:1:199 +822:1:200 +823:1:208 +824:1:213 +825:1:214 +826:1:225 +827:1:226 +828:1:227 +829:1:238 +830:1:243 +831:1:244 +832:1:255 +833:1:256 +834:1:257 +835:1:255 +836:1:256 +837:1:257 +838:1:268 +839:0:4462 +840:1:11 +841:0:4462 +842:1:277 +843:1:278 +844:1:282 +845:1:283 +846:1:291 +847:1:292 +848:1:296 +849:1:297 +850:1:305 +851:1:310 +852:1:314 +853:1:315 +854:1:323 +855:1:324 +856:1:328 +857:1:329 +858:1:323 +859:1:324 +860:1:328 +861:1:329 +862:1:337 +863:1:342 +864:1:343 +865:1:354 +866:1:355 +867:1:356 +868:1:367 +869:1:372 +870:1:373 +871:1:384 +872:1:385 +873:1:386 +874:1:384 +875:1:385 +876:1:386 +877:1:397 +878:1:404 +879:0:4462 +880:1:11 +881:0:4462 +882:1:540 +883:1:544 +884:1:545 +885:1:549 +886:1:550 +887:1:558 +888:1:566 +889:1:567 +890:1:571 +891:1:575 +892:1:576 +893:1:571 +894:1:575 +895:1:576 +896:1:580 +897:1:587 +898:1:594 +899:1:595 +900:1:602 +901:1:607 +902:1:614 +903:1:615 +904:1:614 +905:1:615 +906:1:622 +907:0:4462 +908:1:11 +909:0:4462 +910:1:632 +911:1:633 +912:1:637 +913:1:638 +914:1:646 +915:1:647 +916:1:651 +917:1:652 +918:1:660 +919:1:665 +920:1:669 +921:1:670 +922:1:678 +923:1:679 +924:1:683 +925:1:684 +926:1:678 +927:1:679 +928:1:683 +929:1:684 +930:1:692 +931:1:697 +932:1:698 +933:1:709 +934:1:710 +935:1:711 +936:1:722 +937:1:727 +938:1:728 +939:1:739 +940:1:740 +941:1:741 +942:1:739 +943:1:740 +944:1:741 +945:1:752 +946:0:4462 +947:1:11 +948:0:4462 +949:1:761 +950:1:764 +951:1:765 +952:0:4462 +953:1:11 +954:0:4462 +955:1:1028 +956:1:1029 +957:1:1033 +958:1:1034 +959:1:1042 +960:1:1043 +961:1:1047 +962:1:1048 +963:1:1056 +964:1:1061 +965:1:1065 +966:1:1066 +967:1:1074 +968:1:1075 +969:1:1079 +970:1:1080 +971:1:1074 +972:1:1075 +973:1:1079 +974:1:1080 +975:1:1088 +976:1:1093 +977:1:1094 +978:1:1105 +979:1:1106 +980:1:1107 +981:1:1118 +982:1:1123 +983:1:1124 +984:1:1135 +985:1:1136 +986:1:1137 +987:1:1135 +988:1:1136 +989:1:1137 +990:1:1148 +991:1:1155 +992:1:1159 +993:0:4462 +994:1:11 +995:0:4462 +996:1:1160 +997:1:1161 +998:1:1165 +999:1:1166 +1000:1:1174 +1001:1:1175 +1002:1:1176 +1003:1:1188 +1004:1:1193 +1005:1:1197 +1006:1:1198 +1007:1:1206 +1008:1:1207 +1009:1:1211 +1010:1:1212 +1011:1:1206 +1012:1:1207 +1013:1:1211 +1014:1:1212 +1015:1:1220 +1016:1:1225 +1017:1:1226 +1018:1:1237 +1019:1:1238 +1020:1:1239 +1021:1:1250 +1022:1:1255 +1023:1:1256 +1024:1:1267 +1025:1:1268 +1026:1:1269 +1027:1:1267 +1028:1:1268 +1029:1:1269 +1030:1:1280 +1031:0:4462 +1032:1:11 +1033:0:4462 +1034:1:1289 +1035:0:4462 +1036:1:3023 +1037:1:3030 +1038:1:3031 +1039:1:3038 +1040:1:3043 +1041:1:3050 +1042:1:3051 +1043:1:3050 +1044:1:3051 +1045:1:3058 +1046:1:3062 +1047:0:4462 +1048:2:4019 +1049:2:4020 +1050:2:4024 +1051:2:4028 +1052:2:4029 +1053:2:4033 +1054:2:4038 +1055:2:4046 +1056:2:4050 +1057:2:4051 +1058:2:4046 +1059:2:4047 +1060:2:4055 +1061:2:4062 +1062:2:4069 +1063:2:4070 +1064:2:4077 +1065:2:4082 +1066:2:4089 +1067:2:4090 +1068:2:4089 +1069:2:4090 +1070:2:4097 +1071:2:4101 +1072:0:4462 +1073:2:3318 +1074:2:4000 +1075:0:4462 +1076:2:3128 +1077:0:4462 +1078:2:3319 +1079:0:4462 +1080:2:3128 +1081:0:4462 +1082:2:3322 +1083:2:3323 +1084:2:3327 +1085:2:3328 +1086:2:3336 +1087:2:3337 +1088:2:3341 +1089:2:3342 +1090:2:3350 +1091:2:3355 +1092:2:3359 +1093:2:3360 +1094:2:3368 +1095:2:3369 +1096:2:3373 +1097:2:3374 +1098:2:3368 +1099:2:3369 +1100:2:3373 +1101:2:3374 +1102:2:3382 +1103:2:3387 +1104:2:3388 +1105:2:3399 +1106:2:3400 +1107:2:3401 +1108:2:3412 +1109:2:3417 +1110:2:3418 +1111:2:3429 +1112:2:3430 +1113:2:3431 +1114:2:3429 +1115:2:3430 +1116:2:3431 +1117:2:3442 +1118:2:3449 +1119:0:4462 +1120:2:3128 +1121:0:4462 +1122:2:3453 +1123:2:3454 +1124:2:3455 +1125:2:3467 +1126:2:3468 +1127:2:3472 +1128:2:3473 +1129:2:3481 +1130:2:3486 +1131:2:3490 +1132:2:3491 +1133:2:3499 +1134:2:3500 +1135:2:3504 +1136:2:3505 +1137:2:3499 +1138:2:3500 +1139:2:3504 +1140:2:3505 +1141:2:3513 +1142:2:3518 +1143:2:3519 +1144:2:3530 +1145:2:3531 +1146:2:3532 +1147:2:3543 +1148:2:3548 +1149:2:3549 +1150:2:3560 +1151:2:3561 +1152:2:3562 +1153:2:3560 +1154:2:3561 +1155:2:3562 +1156:2:3573 +1157:2:3582 +1158:0:4462 +1159:2:3128 +1160:0:4462 +1161:2:3588 +1162:0:4462 +1163:2:4110 +1164:2:4111 +1165:2:4115 +1166:2:4119 +1167:2:4120 +1168:2:4124 +1169:2:4132 +1170:2:4133 +1171:2:4137 +1172:2:4141 +1173:2:4142 +1174:2:4137 +1175:2:4141 +1176:2:4142 +1177:2:4146 +1178:2:4153 +1179:2:4160 +1180:2:4161 +1181:2:4168 +1182:2:4173 +1183:2:4180 +1184:2:4181 +1185:2:4180 +1186:2:4181 +1187:2:4188 +1188:2:4192 +1189:0:4462 +1190:2:3590 +1191:2:4000 +1192:0:4462 +1193:2:3128 +1194:0:4462 +1195:1:1291 +1196:1:1292 +1197:0:4460 +1198:1:11 +1199:0:4466 +1200:2:3477 diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_single_flip.define b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_single_flip.define new file mode 100644 index 0000000..5e642ef --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_single_flip.define @@ -0,0 +1 @@ +#define SINGLE_FLIP diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_single_flip.log b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_single_flip.log new file mode 100644 index 0000000..e414670 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_single_flip.log @@ -0,0 +1,732 @@ +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define >> pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_free.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_free_single_flip.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1258) +pan: claim violated! (at depth 1036) +pan: wrote .input.spin.trail + +(Spin Version 5.1.7 -- 23 December 2008) +Warning: Search not completed + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness disabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 4474, errors: 1 + 607250 states, stored +2.1024134e+08 states, matched +2.1084859e+08 transitions (= stored+matched) +1.2498522e+09 atomic steps +hash conflicts: 36422558 (resolved) + +Stats on memory usage (in Megabytes): + 67.178 equivalent memory usage for states (stored*(State-vector + overhead)) + 51.749 actual memory usage for states (compression: 77.03%) + state-vector as stored = 61 byte + 28 byte overhead + 8.000 memory used for hash table (-w20) + 457.764 memory used for DFS stack (-m10000000) + 517.424 total actual memory usage + +unreached in proctype urcu_reader + line 395, "pan.___", state 17, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 49, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 63, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 82, "(1)" + line 421, "pan.___", state 112, "(1)" + line 425, "pan.___", state 125, "(1)" + line 576, "pan.___", state 146, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 395, "pan.___", state 153, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 185, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 199, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 218, "(1)" + line 421, "pan.___", state 248, "(1)" + line 425, "pan.___", state 261, "(1)" + line 395, "pan.___", state 282, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 314, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 328, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 347, "(1)" + line 421, "pan.___", state 377, "(1)" + line 425, "pan.___", state 390, "(1)" + line 395, "pan.___", state 413, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 415, "(1)" + line 395, "pan.___", state 416, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 416, "else" + line 395, "pan.___", state 419, "(1)" + line 399, "pan.___", state 427, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 429, "(1)" + line 399, "pan.___", state 430, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 430, "else" + line 399, "pan.___", state 433, "(1)" + line 399, "pan.___", state 434, "(1)" + line 399, "pan.___", state 434, "(1)" + line 397, "pan.___", state 439, "((i<1))" + line 397, "pan.___", state 439, "((i>=1))" + line 404, "pan.___", state 445, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 447, "(1)" + line 404, "pan.___", state 448, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 448, "else" + line 404, "pan.___", state 451, "(1)" + line 404, "pan.___", state 452, "(1)" + line 404, "pan.___", state 452, "(1)" + line 408, "pan.___", state 459, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 461, "(1)" + line 408, "pan.___", state 462, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 462, "else" + line 408, "pan.___", state 465, "(1)" + line 408, "pan.___", state 466, "(1)" + line 408, "pan.___", state 466, "(1)" + line 406, "pan.___", state 471, "((i<2))" + line 406, "pan.___", state 471, "((i>=2))" + line 412, "pan.___", state 478, "(1)" + line 412, "pan.___", state 479, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 479, "else" + line 412, "pan.___", state 482, "(1)" + line 412, "pan.___", state 483, "(1)" + line 412, "pan.___", state 483, "(1)" + line 416, "pan.___", state 491, "(1)" + line 416, "pan.___", state 492, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 492, "else" + line 416, "pan.___", state 495, "(1)" + line 416, "pan.___", state 496, "(1)" + line 416, "pan.___", state 496, "(1)" + line 414, "pan.___", state 501, "((i<1))" + line 414, "pan.___", state 501, "((i>=1))" + line 421, "pan.___", state 508, "(1)" + line 421, "pan.___", state 509, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 509, "else" + line 421, "pan.___", state 512, "(1)" + line 421, "pan.___", state 513, "(1)" + line 421, "pan.___", state 513, "(1)" + line 425, "pan.___", state 521, "(1)" + line 425, "pan.___", state 522, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 522, "else" + line 425, "pan.___", state 525, "(1)" + line 425, "pan.___", state 526, "(1)" + line 425, "pan.___", state 526, "(1)" + line 423, "pan.___", state 531, "((i<2))" + line 423, "pan.___", state 531, "((i>=2))" + line 430, "pan.___", state 535, "(1)" + line 430, "pan.___", state 535, "(1)" + line 576, "pan.___", state 538, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 576, "pan.___", state 539, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 576, "pan.___", state 540, "(1)" + line 250, "pan.___", state 544, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 555, "(1)" + line 258, "pan.___", state 566, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 575, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 591, "(1)" + line 231, "pan.___", state 599, "(1)" + line 235, "pan.___", state 611, "(1)" + line 239, "pan.___", state 619, "(1)" + line 395, "pan.___", state 637, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 651, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 669, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 683, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 702, "(1)" + line 416, "pan.___", state 715, "(1)" + line 421, "pan.___", state 732, "(1)" + line 425, "pan.___", state 745, "(1)" + line 395, "pan.___", state 773, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 775, "(1)" + line 395, "pan.___", state 776, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 776, "else" + line 395, "pan.___", state 779, "(1)" + line 399, "pan.___", state 787, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 789, "(1)" + line 399, "pan.___", state 790, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 790, "else" + line 399, "pan.___", state 793, "(1)" + line 399, "pan.___", state 794, "(1)" + line 399, "pan.___", state 794, "(1)" + line 397, "pan.___", state 799, "((i<1))" + line 397, "pan.___", state 799, "((i>=1))" + line 404, "pan.___", state 805, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 807, "(1)" + line 404, "pan.___", state 808, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 808, "else" + line 404, "pan.___", state 811, "(1)" + line 404, "pan.___", state 812, "(1)" + line 404, "pan.___", state 812, "(1)" + line 408, "pan.___", state 819, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 821, "(1)" + line 408, "pan.___", state 822, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 822, "else" + line 408, "pan.___", state 825, "(1)" + line 408, "pan.___", state 826, "(1)" + line 408, "pan.___", state 826, "(1)" + line 406, "pan.___", state 831, "((i<2))" + line 406, "pan.___", state 831, "((i>=2))" + line 412, "pan.___", state 838, "(1)" + line 412, "pan.___", state 839, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 839, "else" + line 412, "pan.___", state 842, "(1)" + line 412, "pan.___", state 843, "(1)" + line 412, "pan.___", state 843, "(1)" + line 416, "pan.___", state 851, "(1)" + line 416, "pan.___", state 852, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 852, "else" + line 416, "pan.___", state 855, "(1)" + line 416, "pan.___", state 856, "(1)" + line 416, "pan.___", state 856, "(1)" + line 414, "pan.___", state 861, "((i<1))" + line 414, "pan.___", state 861, "((i>=1))" + line 421, "pan.___", state 868, "(1)" + line 421, "pan.___", state 869, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 869, "else" + line 421, "pan.___", state 872, "(1)" + line 421, "pan.___", state 873, "(1)" + line 421, "pan.___", state 873, "(1)" + line 425, "pan.___", state 881, "(1)" + line 425, "pan.___", state 882, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 882, "else" + line 425, "pan.___", state 885, "(1)" + line 425, "pan.___", state 886, "(1)" + line 425, "pan.___", state 886, "(1)" + line 430, "pan.___", state 895, "(1)" + line 430, "pan.___", state 895, "(1)" + line 395, "pan.___", state 902, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 904, "(1)" + line 395, "pan.___", state 905, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 905, "else" + line 395, "pan.___", state 908, "(1)" + line 399, "pan.___", state 916, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 918, "(1)" + line 399, "pan.___", state 919, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 919, "else" + line 399, "pan.___", state 922, "(1)" + line 399, "pan.___", state 923, "(1)" + line 399, "pan.___", state 923, "(1)" + line 397, "pan.___", state 928, "((i<1))" + line 397, "pan.___", state 928, "((i>=1))" + line 404, "pan.___", state 934, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 936, "(1)" + line 404, "pan.___", state 937, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 937, "else" + line 404, "pan.___", state 940, "(1)" + line 404, "pan.___", state 941, "(1)" + line 404, "pan.___", state 941, "(1)" + line 408, "pan.___", state 948, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 950, "(1)" + line 408, "pan.___", state 951, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 951, "else" + line 408, "pan.___", state 954, "(1)" + line 408, "pan.___", state 955, "(1)" + line 408, "pan.___", state 955, "(1)" + line 406, "pan.___", state 960, "((i<2))" + line 406, "pan.___", state 960, "((i>=2))" + line 412, "pan.___", state 967, "(1)" + line 412, "pan.___", state 968, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 968, "else" + line 412, "pan.___", state 971, "(1)" + line 412, "pan.___", state 972, "(1)" + line 412, "pan.___", state 972, "(1)" + line 416, "pan.___", state 980, "(1)" + line 416, "pan.___", state 981, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 981, "else" + line 416, "pan.___", state 984, "(1)" + line 416, "pan.___", state 985, "(1)" + line 416, "pan.___", state 985, "(1)" + line 414, "pan.___", state 990, "((i<1))" + line 414, "pan.___", state 990, "((i>=1))" + line 421, "pan.___", state 997, "(1)" + line 421, "pan.___", state 998, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 998, "else" + line 421, "pan.___", state 1001, "(1)" + line 421, "pan.___", state 1002, "(1)" + line 421, "pan.___", state 1002, "(1)" + line 425, "pan.___", state 1010, "(1)" + line 425, "pan.___", state 1011, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 1011, "else" + line 425, "pan.___", state 1014, "(1)" + line 425, "pan.___", state 1015, "(1)" + line 425, "pan.___", state 1015, "(1)" + line 423, "pan.___", state 1020, "((i<2))" + line 423, "pan.___", state 1020, "((i>=2))" + line 430, "pan.___", state 1024, "(1)" + line 430, "pan.___", state 1024, "(1)" + line 584, "pan.___", state 1028, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 395, "pan.___", state 1033, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1047, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1065, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1079, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1098, "(1)" + line 416, "pan.___", state 1111, "(1)" + line 421, "pan.___", state 1128, "(1)" + line 425, "pan.___", state 1141, "(1)" + line 395, "pan.___", state 1165, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1197, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1211, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1230, "(1)" + line 421, "pan.___", state 1260, "(1)" + line 425, "pan.___", state 1273, "(1)" + line 395, "pan.___", state 1298, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1330, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1344, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1363, "(1)" + line 421, "pan.___", state 1393, "(1)" + line 425, "pan.___", state 1406, "(1)" + line 395, "pan.___", state 1427, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1459, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1473, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1492, "(1)" + line 421, "pan.___", state 1522, "(1)" + line 425, "pan.___", state 1535, "(1)" + line 250, "pan.___", state 1558, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1580, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1589, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1605, "(1)" + line 231, "pan.___", state 1613, "(1)" + line 235, "pan.___", state 1625, "(1)" + line 239, "pan.___", state 1633, "(1)" + line 395, "pan.___", state 1651, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1665, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1683, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1697, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1716, "(1)" + line 416, "pan.___", state 1729, "(1)" + line 421, "pan.___", state 1746, "(1)" + line 425, "pan.___", state 1759, "(1)" + line 395, "pan.___", state 1780, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1794, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1812, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1826, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1845, "(1)" + line 416, "pan.___", state 1858, "(1)" + line 421, "pan.___", state 1875, "(1)" + line 425, "pan.___", state 1888, "(1)" + line 395, "pan.___", state 1912, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1928, "(1)" + line 404, "pan.___", state 1944, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1958, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1977, "(1)" + line 421, "pan.___", state 2007, "(1)" + line 425, "pan.___", state 2020, "(1)" + line 623, "pan.___", state 2041, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 395, "pan.___", state 2048, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2080, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2094, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2113, "(1)" + line 421, "pan.___", state 2143, "(1)" + line 425, "pan.___", state 2156, "(1)" + line 395, "pan.___", state 2177, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2209, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2223, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2242, "(1)" + line 421, "pan.___", state 2272, "(1)" + line 425, "pan.___", state 2285, "(1)" + line 395, "pan.___", state 2308, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 2310, "(1)" + line 395, "pan.___", state 2311, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 2311, "else" + line 395, "pan.___", state 2314, "(1)" + line 399, "pan.___", state 2322, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2324, "(1)" + line 399, "pan.___", state 2325, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 2325, "else" + line 399, "pan.___", state 2328, "(1)" + line 399, "pan.___", state 2329, "(1)" + line 399, "pan.___", state 2329, "(1)" + line 397, "pan.___", state 2334, "((i<1))" + line 397, "pan.___", state 2334, "((i>=1))" + line 404, "pan.___", state 2340, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2342, "(1)" + line 404, "pan.___", state 2343, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 2343, "else" + line 404, "pan.___", state 2346, "(1)" + line 404, "pan.___", state 2347, "(1)" + line 404, "pan.___", state 2347, "(1)" + line 408, "pan.___", state 2354, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2356, "(1)" + line 408, "pan.___", state 2357, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 2357, "else" + line 408, "pan.___", state 2360, "(1)" + line 408, "pan.___", state 2361, "(1)" + line 408, "pan.___", state 2361, "(1)" + line 406, "pan.___", state 2366, "((i<2))" + line 406, "pan.___", state 2366, "((i>=2))" + line 412, "pan.___", state 2373, "(1)" + line 412, "pan.___", state 2374, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 2374, "else" + line 412, "pan.___", state 2377, "(1)" + line 412, "pan.___", state 2378, "(1)" + line 412, "pan.___", state 2378, "(1)" + line 416, "pan.___", state 2386, "(1)" + line 416, "pan.___", state 2387, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 2387, "else" + line 416, "pan.___", state 2390, "(1)" + line 416, "pan.___", state 2391, "(1)" + line 416, "pan.___", state 2391, "(1)" + line 414, "pan.___", state 2396, "((i<1))" + line 414, "pan.___", state 2396, "((i>=1))" + line 421, "pan.___", state 2403, "(1)" + line 421, "pan.___", state 2404, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 2404, "else" + line 421, "pan.___", state 2407, "(1)" + line 421, "pan.___", state 2408, "(1)" + line 421, "pan.___", state 2408, "(1)" + line 425, "pan.___", state 2416, "(1)" + line 425, "pan.___", state 2417, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 2417, "else" + line 425, "pan.___", state 2420, "(1)" + line 425, "pan.___", state 2421, "(1)" + line 425, "pan.___", state 2421, "(1)" + line 423, "pan.___", state 2426, "((i<2))" + line 423, "pan.___", state 2426, "((i>=2))" + line 430, "pan.___", state 2430, "(1)" + line 430, "pan.___", state 2430, "(1)" + line 623, "pan.___", state 2433, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 623, "pan.___", state 2434, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 623, "pan.___", state 2435, "(1)" + line 250, "pan.___", state 2439, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 2450, "(1)" + line 258, "pan.___", state 2461, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 2470, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 2486, "(1)" + line 231, "pan.___", state 2494, "(1)" + line 235, "pan.___", state 2506, "(1)" + line 239, "pan.___", state 2514, "(1)" + line 395, "pan.___", state 2532, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2546, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2564, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2578, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2597, "(1)" + line 416, "pan.___", state 2610, "(1)" + line 421, "pan.___", state 2627, "(1)" + line 425, "pan.___", state 2640, "(1)" + line 250, "pan.___", state 2664, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 2673, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 2686, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 2695, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 2711, "(1)" + line 231, "pan.___", state 2719, "(1)" + line 235, "pan.___", state 2731, "(1)" + line 239, "pan.___", state 2739, "(1)" + line 395, "pan.___", state 2757, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2771, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2789, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2803, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2822, "(1)" + line 416, "pan.___", state 2835, "(1)" + line 421, "pan.___", state 2852, "(1)" + line 425, "pan.___", state 2865, "(1)" + line 395, "pan.___", state 2886, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2900, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2918, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2932, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2951, "(1)" + line 416, "pan.___", state 2964, "(1)" + line 421, "pan.___", state 2981, "(1)" + line 425, "pan.___", state 2994, "(1)" + line 227, "pan.___", state 3027, "(1)" + line 235, "pan.___", state 3047, "(1)" + line 239, "pan.___", state 3055, "(1)" + line 227, "pan.___", state 3070, "(1)" + line 231, "pan.___", state 3078, "(1)" + line 235, "pan.___", state 3090, "(1)" + line 239, "pan.___", state 3098, "(1)" + line 877, "pan.___", state 3115, "-end-" + (318 of 3115 states) +unreached in proctype urcu_writer + line 395, "pan.___", state 22, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 36, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 54, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 412, "pan.___", state 87, "(1)" + line 416, "pan.___", state 100, "(1)" + line 421, "pan.___", state 117, "(1)" + line 250, "pan.___", state 153, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 162, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 175, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 215, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 229, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 247, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 261, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 280, "(1)" + line 416, "pan.___", state 293, "(1)" + line 421, "pan.___", state 310, "(1)" + line 425, "pan.___", state 323, "(1)" + line 399, "pan.___", state 360, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 378, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 392, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 424, "(1)" + line 421, "pan.___", state 441, "(1)" + line 425, "pan.___", state 454, "(1)" + line 395, "pan.___", state 483, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 485, "(1)" + line 395, "pan.___", state 486, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 486, "else" + line 395, "pan.___", state 489, "(1)" + line 399, "pan.___", state 497, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 499, "(1)" + line 399, "pan.___", state 500, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 500, "else" + line 399, "pan.___", state 503, "(1)" + line 399, "pan.___", state 504, "(1)" + line 399, "pan.___", state 504, "(1)" + line 397, "pan.___", state 509, "((i<1))" + line 397, "pan.___", state 509, "((i>=1))" + line 404, "pan.___", state 515, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 517, "(1)" + line 404, "pan.___", state 518, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 518, "else" + line 404, "pan.___", state 521, "(1)" + line 404, "pan.___", state 522, "(1)" + line 404, "pan.___", state 522, "(1)" + line 408, "pan.___", state 529, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 531, "(1)" + line 408, "pan.___", state 532, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 532, "else" + line 408, "pan.___", state 535, "(1)" + line 408, "pan.___", state 536, "(1)" + line 408, "pan.___", state 536, "(1)" + line 406, "pan.___", state 541, "((i<2))" + line 406, "pan.___", state 541, "((i>=2))" + line 412, "pan.___", state 548, "(1)" + line 412, "pan.___", state 549, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 549, "else" + line 412, "pan.___", state 552, "(1)" + line 412, "pan.___", state 553, "(1)" + line 412, "pan.___", state 553, "(1)" + line 416, "pan.___", state 561, "(1)" + line 416, "pan.___", state 562, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 562, "else" + line 416, "pan.___", state 565, "(1)" + line 416, "pan.___", state 566, "(1)" + line 416, "pan.___", state 566, "(1)" + line 414, "pan.___", state 571, "((i<1))" + line 414, "pan.___", state 571, "((i>=1))" + line 421, "pan.___", state 578, "(1)" + line 421, "pan.___", state 579, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 579, "else" + line 421, "pan.___", state 582, "(1)" + line 421, "pan.___", state 583, "(1)" + line 421, "pan.___", state 583, "(1)" + line 425, "pan.___", state 591, "(1)" + line 425, "pan.___", state 592, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 592, "else" + line 425, "pan.___", state 595, "(1)" + line 425, "pan.___", state 596, "(1)" + line 425, "pan.___", state 596, "(1)" + line 430, "pan.___", state 605, "(1)" + line 430, "pan.___", state 605, "(1)" + line 395, "pan.___", state 612, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 614, "(1)" + line 395, "pan.___", state 615, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 615, "else" + line 395, "pan.___", state 618, "(1)" + line 399, "pan.___", state 626, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 628, "(1)" + line 399, "pan.___", state 629, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 629, "else" + line 399, "pan.___", state 632, "(1)" + line 399, "pan.___", state 633, "(1)" + line 399, "pan.___", state 633, "(1)" + line 397, "pan.___", state 638, "((i<1))" + line 397, "pan.___", state 638, "((i>=1))" + line 404, "pan.___", state 644, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 646, "(1)" + line 404, "pan.___", state 647, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 647, "else" + line 404, "pan.___", state 650, "(1)" + line 404, "pan.___", state 651, "(1)" + line 404, "pan.___", state 651, "(1)" + line 408, "pan.___", state 658, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 660, "(1)" + line 408, "pan.___", state 661, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 661, "else" + line 408, "pan.___", state 664, "(1)" + line 408, "pan.___", state 665, "(1)" + line 408, "pan.___", state 665, "(1)" + line 406, "pan.___", state 670, "((i<2))" + line 406, "pan.___", state 670, "((i>=2))" + line 412, "pan.___", state 677, "(1)" + line 412, "pan.___", state 678, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 678, "else" + line 412, "pan.___", state 681, "(1)" + line 412, "pan.___", state 682, "(1)" + line 412, "pan.___", state 682, "(1)" + line 416, "pan.___", state 690, "(1)" + line 416, "pan.___", state 691, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 691, "else" + line 416, "pan.___", state 694, "(1)" + line 416, "pan.___", state 695, "(1)" + line 416, "pan.___", state 695, "(1)" + line 414, "pan.___", state 700, "((i<1))" + line 414, "pan.___", state 700, "((i>=1))" + line 421, "pan.___", state 707, "(1)" + line 421, "pan.___", state 708, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 708, "else" + line 421, "pan.___", state 711, "(1)" + line 421, "pan.___", state 712, "(1)" + line 421, "pan.___", state 712, "(1)" + line 425, "pan.___", state 720, "(1)" + line 425, "pan.___", state 721, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 721, "else" + line 425, "pan.___", state 724, "(1)" + line 425, "pan.___", state 725, "(1)" + line 425, "pan.___", state 725, "(1)" + line 423, "pan.___", state 730, "((i<2))" + line 423, "pan.___", state 730, "((i>=2))" + line 430, "pan.___", state 734, "(1)" + line 430, "pan.___", state 734, "(1)" + line 1085, "pan.___", state 738, "_proc_urcu_writer = (_proc_urcu_writer|(1<<10))" + line 395, "pan.___", state 743, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 745, "(1)" + line 395, "pan.___", state 746, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 746, "else" + line 395, "pan.___", state 749, "(1)" + line 399, "pan.___", state 757, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 759, "(1)" + line 399, "pan.___", state 760, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 760, "else" + line 399, "pan.___", state 763, "(1)" + line 399, "pan.___", state 764, "(1)" + line 399, "pan.___", state 764, "(1)" + line 397, "pan.___", state 769, "((i<1))" + line 397, "pan.___", state 769, "((i>=1))" + line 404, "pan.___", state 775, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 777, "(1)" + line 404, "pan.___", state 778, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 778, "else" + line 404, "pan.___", state 781, "(1)" + line 404, "pan.___", state 782, "(1)" + line 404, "pan.___", state 782, "(1)" + line 408, "pan.___", state 789, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 791, "(1)" + line 408, "pan.___", state 792, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 792, "else" + line 408, "pan.___", state 795, "(1)" + line 408, "pan.___", state 796, "(1)" + line 408, "pan.___", state 796, "(1)" + line 406, "pan.___", state 801, "((i<2))" + line 406, "pan.___", state 801, "((i>=2))" + line 412, "pan.___", state 808, "(1)" + line 412, "pan.___", state 809, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 809, "else" + line 412, "pan.___", state 812, "(1)" + line 412, "pan.___", state 813, "(1)" + line 412, "pan.___", state 813, "(1)" + line 416, "pan.___", state 821, "(1)" + line 416, "pan.___", state 822, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 822, "else" + line 416, "pan.___", state 825, "(1)" + line 416, "pan.___", state 826, "(1)" + line 416, "pan.___", state 826, "(1)" + line 414, "pan.___", state 831, "((i<1))" + line 414, "pan.___", state 831, "((i>=1))" + line 421, "pan.___", state 838, "(1)" + line 421, "pan.___", state 839, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 839, "else" + line 421, "pan.___", state 842, "(1)" + line 421, "pan.___", state 843, "(1)" + line 421, "pan.___", state 843, "(1)" + line 425, "pan.___", state 851, "(1)" + line 425, "pan.___", state 852, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 852, "else" + line 425, "pan.___", state 855, "(1)" + line 425, "pan.___", state 856, "(1)" + line 425, "pan.___", state 856, "(1)" + line 423, "pan.___", state 861, "((i<2))" + line 423, "pan.___", state 861, "((i>=2))" + line 430, "pan.___", state 865, "(1)" + line 430, "pan.___", state 865, "(1)" + line 1100, "pan.___", state 870, "_proc_urcu_writer = (_proc_urcu_writer|(1<<11))" + line 1095, "pan.___", state 871, "(((tmp2&((1<<7)-1))&&((tmp2^0)&(1<<7))))" + line 1095, "pan.___", state 871, "else" + line 1120, "pan.___", state 875, "_proc_urcu_writer = (_proc_urcu_writer&~(((1<<12)|(1<<11))))" + line 250, "pan.___", state 906, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 915, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 930, "(1)" + line 262, "pan.___", state 937, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 953, "(1)" + line 231, "pan.___", state 961, "(1)" + line 235, "pan.___", state 973, "(1)" + line 239, "pan.___", state 981, "(1)" + line 254, "pan.___", state 1006, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1019, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1028, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1044, "(1)" + line 231, "pan.___", state 1052, "(1)" + line 235, "pan.___", state 1064, "(1)" + line 239, "pan.___", state 1072, "(1)" + line 250, "pan.___", state 1088, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 250, "pan.___", state 1090, "(1)" + line 254, "pan.___", state 1097, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1099, "(1)" + line 254, "pan.___", state 1100, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 254, "pan.___", state 1100, "else" + line 252, "pan.___", state 1105, "((i<1))" + line 252, "pan.___", state 1105, "((i>=1))" + line 258, "pan.___", state 1110, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1112, "(1)" + line 258, "pan.___", state 1113, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 258, "pan.___", state 1113, "else" + line 262, "pan.___", state 1119, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1121, "(1)" + line 262, "pan.___", state 1122, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 262, "pan.___", state 1122, "else" + line 260, "pan.___", state 1127, "((i<2))" + line 260, "pan.___", state 1127, "((i>=2))" + line 227, "pan.___", state 1135, "(1)" + line 231, "pan.___", state 1143, "(1)" + line 231, "pan.___", state 1144, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 231, "pan.___", state 1144, "else" + line 229, "pan.___", state 1149, "((i<1))" + line 229, "pan.___", state 1149, "((i>=1))" + line 235, "pan.___", state 1155, "(1)" + line 235, "pan.___", state 1156, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 235, "pan.___", state 1156, "else" + line 239, "pan.___", state 1163, "(1)" + line 239, "pan.___", state 1164, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 239, "pan.___", state 1164, "else" + line 244, "pan.___", state 1173, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 244, "pan.___", state 1173, "else" + line 277, "pan.___", state 1175, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 277, "pan.___", state 1175, "else" + line 254, "pan.___", state 1188, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1201, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1210, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1226, "(1)" + line 231, "pan.___", state 1234, "(1)" + line 235, "pan.___", state 1246, "(1)" + line 239, "pan.___", state 1254, "(1)" + line 1204, "pan.___", state 1269, "-end-" + (192 of 1269 states) +unreached in proctype :init: + line 1215, "pan.___", state 9, "((j<2))" + line 1215, "pan.___", state 9, "((j>=2))" + line 1216, "pan.___", state 20, "((j<2))" + line 1216, "pan.___", state 20, "((j>=2))" + line 1221, "pan.___", state 33, "((j<2))" + line 1221, "pan.___", state 33, "((j>=2))" + line 1219, "pan.___", state 43, "((i<1))" + line 1219, "pan.___", state 43, "((i>=1))" + line 1229, "pan.___", state 54, "((j<2))" + line 1229, "pan.___", state 54, "((j>=2))" + line 1233, "pan.___", state 67, "((j<2))" + line 1233, "pan.___", state 67, "((j>=2))" + (6 of 78 states) +unreached in proctype :never: + line 1263, "pan.___", state 8, "-end-" + (1 of 8 states) + +pan: elapsed time 266 seconds +pan: rate 2283.3239 states/second +pan: avg transition delay 1.2613e-06 usec +cp .input.spin urcu_free_single_flip.spin.input +cp .input.spin.trail urcu_free_single_flip.spin.input.trail diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_single_flip.spin.input b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_single_flip.spin.input new file mode 100644 index 0000000..b2e670e --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_single_flip.spin.input @@ -0,0 +1,1240 @@ +#define SINGLE_FLIP + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +//#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_single_flip.spin.input.trail b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_single_flip.spin.input.trail new file mode 100644 index 0000000..d8a0531 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_free_single_flip.spin.input.trail @@ -0,0 +1,1039 @@ +-2:3:-2 +-4:-4:-4 +1:0:4464 +2:3:4384 +3:3:4387 +4:3:4387 +5:3:4390 +6:3:4398 +7:3:4398 +8:3:4401 +9:3:4407 +10:3:4411 +11:3:4411 +12:3:4414 +13:3:4424 +14:3:4432 +15:3:4432 +16:3:4435 +17:3:4441 +18:3:4445 +19:3:4445 +20:3:4448 +21:3:4454 +22:3:4458 +23:3:4459 +24:0:4464 +25:3:4461 +26:0:4464 +27:2:3117 +28:0:4464 +29:2:3123 +30:0:4464 +31:2:3124 +32:0:4464 +33:2:3126 +34:0:4464 +35:2:3127 +36:0:4464 +37:2:3128 +38:0:4464 +39:2:3129 +40:0:4464 +41:2:3130 +42:0:4464 +43:2:3131 +44:0:4464 +45:2:3132 +46:2:3133 +47:2:3137 +48:2:3138 +49:2:3146 +50:2:3147 +51:2:3151 +52:2:3152 +53:2:3160 +54:2:3165 +55:2:3169 +56:2:3170 +57:2:3178 +58:2:3179 +59:2:3183 +60:2:3184 +61:2:3178 +62:2:3179 +63:2:3183 +64:2:3184 +65:2:3192 +66:2:3197 +67:2:3198 +68:2:3209 +69:2:3210 +70:2:3211 +71:2:3222 +72:2:3227 +73:2:3228 +74:2:3239 +75:2:3240 +76:2:3241 +77:2:3239 +78:2:3240 +79:2:3241 +80:2:3252 +81:2:3260 +82:0:4464 +83:2:3131 +84:0:4464 +85:2:3264 +86:2:3268 +87:2:3269 +88:2:3273 +89:2:3277 +90:2:3278 +91:2:3282 +92:2:3290 +93:2:3291 +94:2:3295 +95:2:3299 +96:2:3300 +97:2:3295 +98:2:3296 +99:2:3304 +100:0:4464 +101:2:3131 +102:0:4464 +103:2:3312 +104:2:3313 +105:2:3314 +106:0:4464 +107:2:3131 +108:0:4464 +109:2:3319 +110:0:4464 +111:2:4021 +112:2:4022 +113:2:4026 +114:2:4030 +115:2:4031 +116:2:4035 +117:2:4040 +118:2:4048 +119:2:4052 +120:2:4053 +121:2:4048 +122:2:4052 +123:2:4053 +124:2:4057 +125:2:4064 +126:2:4071 +127:2:4072 +128:2:4079 +129:2:4084 +130:2:4091 +131:2:4092 +132:2:4091 +133:2:4092 +134:2:4099 +135:2:4103 +136:0:4464 +137:2:3321 +138:2:4002 +139:0:4464 +140:2:3131 +141:0:4464 +142:2:3322 +143:0:4464 +144:2:3131 +145:0:4464 +146:2:3325 +147:2:3326 +148:2:3330 +149:2:3331 +150:2:3339 +151:2:3340 +152:2:3344 +153:2:3345 +154:2:3353 +155:2:3358 +156:2:3362 +157:2:3363 +158:2:3371 +159:2:3372 +160:2:3376 +161:2:3377 +162:2:3371 +163:2:3372 +164:2:3376 +165:2:3377 +166:2:3385 +167:2:3390 +168:2:3391 +169:2:3402 +170:2:3403 +171:2:3404 +172:2:3415 +173:2:3420 +174:2:3421 +175:2:3432 +176:2:3433 +177:2:3434 +178:2:3432 +179:2:3433 +180:2:3434 +181:2:3445 +182:2:3452 +183:0:4464 +184:2:3131 +185:0:4464 +186:2:3456 +187:2:3457 +188:2:3458 +189:2:3470 +190:2:3471 +191:2:3475 +192:2:3476 +193:2:3484 +194:2:3489 +195:2:3493 +196:2:3494 +197:2:3502 +198:2:3503 +199:2:3507 +200:2:3508 +201:2:3502 +202:2:3503 +203:2:3507 +204:2:3508 +205:2:3516 +206:2:3521 +207:2:3522 +208:2:3533 +209:2:3534 +210:2:3535 +211:2:3546 +212:2:3551 +213:2:3552 +214:2:3563 +215:2:3564 +216:2:3565 +217:2:3563 +218:2:3564 +219:2:3565 +220:2:3576 +221:2:3586 +222:2:3587 +223:0:4464 +224:2:3131 +225:0:4464 +226:2:3990 +227:0:4464 +228:2:4294 +229:2:4295 +230:2:4299 +231:2:4303 +232:2:4304 +233:2:4308 +234:2:4316 +235:2:4317 +236:2:4321 +237:2:4325 +238:2:4326 +239:2:4321 +240:2:4325 +241:2:4326 +242:2:4330 +243:2:4337 +244:2:4344 +245:2:4345 +246:2:4352 +247:2:4357 +248:2:4364 +249:2:4365 +250:2:4364 +251:2:4365 +252:2:4372 +253:2:4376 +254:0:4464 +255:2:3992 +256:2:4002 +257:0:4464 +258:2:3131 +259:0:4464 +260:2:3993 +261:2:3994 +262:0:4464 +263:2:3131 +264:0:4464 +265:2:3998 +266:0:4464 +267:2:4006 +268:0:4464 +269:2:3124 +270:0:4464 +271:2:3126 +272:0:4464 +273:2:3127 +274:0:4464 +275:2:3128 +276:0:4464 +277:2:3129 +278:0:4464 +279:2:3130 +280:0:4464 +281:2:3131 +282:0:4464 +283:2:3132 +284:2:3133 +285:2:3137 +286:2:3138 +287:2:3146 +288:2:3147 +289:2:3151 +290:2:3152 +291:2:3160 +292:2:3165 +293:2:3169 +294:2:3170 +295:2:3178 +296:2:3179 +297:2:3180 +298:2:3178 +299:2:3179 +300:2:3183 +301:2:3184 +302:2:3192 +303:2:3197 +304:2:3198 +305:2:3209 +306:2:3210 +307:2:3211 +308:2:3222 +309:2:3227 +310:2:3228 +311:2:3239 +312:2:3240 +313:2:3241 +314:2:3239 +315:2:3240 +316:2:3241 +317:2:3252 +318:2:3260 +319:0:4464 +320:2:3131 +321:0:4464 +322:2:3264 +323:2:3268 +324:2:3269 +325:2:3273 +326:2:3277 +327:2:3278 +328:2:3282 +329:2:3290 +330:2:3291 +331:2:3295 +332:2:3296 +333:2:3295 +334:2:3299 +335:2:3300 +336:2:3304 +337:0:4464 +338:2:3131 +339:0:4464 +340:2:3312 +341:2:3313 +342:2:3314 +343:0:4464 +344:2:3131 +345:0:4464 +346:2:3319 +347:0:4464 +348:1:2 +349:0:4464 +350:1:8 +351:0:4464 +352:1:9 +353:0:4464 +354:1:10 +355:0:4464 +356:1:11 +357:0:4464 +358:1:12 +359:1:13 +360:1:17 +361:1:18 +362:1:26 +363:1:27 +364:1:31 +365:1:32 +366:1:40 +367:1:45 +368:1:49 +369:1:50 +370:1:58 +371:1:59 +372:1:63 +373:1:64 +374:1:58 +375:1:59 +376:1:63 +377:1:64 +378:1:72 +379:1:84 +380:1:85 +381:1:89 +382:1:90 +383:1:91 +384:1:102 +385:1:107 +386:1:108 +387:1:119 +388:1:120 +389:1:121 +390:1:119 +391:1:120 +392:1:121 +393:1:132 +394:0:4464 +395:1:11 +396:0:4464 +397:1:141 +398:1:142 +399:0:4464 +400:1:11 +401:0:4464 +402:1:148 +403:1:149 +404:1:153 +405:1:154 +406:1:162 +407:1:163 +408:1:167 +409:1:168 +410:1:176 +411:1:181 +412:1:185 +413:1:186 +414:1:194 +415:1:195 +416:1:199 +417:1:200 +418:1:194 +419:1:195 +420:1:199 +421:1:200 +422:1:208 +423:1:220 +424:1:221 +425:1:225 +426:1:226 +427:1:227 +428:1:238 +429:1:243 +430:1:244 +431:1:255 +432:1:256 +433:1:257 +434:1:255 +435:1:256 +436:1:257 +437:1:268 +438:0:4464 +439:1:11 +440:0:4464 +441:1:277 +442:1:278 +443:1:282 +444:1:283 +445:1:291 +446:1:292 +447:1:296 +448:1:297 +449:1:305 +450:1:310 +451:1:314 +452:1:315 +453:1:323 +454:1:324 +455:1:328 +456:1:329 +457:1:323 +458:1:324 +459:1:328 +460:1:329 +461:1:337 +462:1:342 +463:1:343 +464:1:354 +465:1:355 +466:1:356 +467:1:367 +468:1:372 +469:1:373 +470:1:384 +471:1:385 +472:1:386 +473:1:384 +474:1:385 +475:1:386 +476:1:397 +477:1:404 +478:0:4464 +479:1:11 +480:0:4464 +481:1:540 +482:1:544 +483:1:545 +484:1:549 +485:1:550 +486:1:558 +487:1:566 +488:1:567 +489:1:571 +490:1:575 +491:1:576 +492:1:571 +493:1:575 +494:1:576 +495:1:580 +496:1:587 +497:1:594 +498:1:595 +499:1:602 +500:1:607 +501:1:614 +502:1:615 +503:1:614 +504:1:615 +505:1:622 +506:0:4464 +507:1:11 +508:0:4464 +509:2:4021 +510:2:4022 +511:2:4026 +512:2:4030 +513:2:4031 +514:2:4035 +515:2:4040 +516:2:4048 +517:2:4052 +518:2:4053 +519:2:4048 +520:2:4052 +521:2:4053 +522:2:4057 +523:2:4064 +524:2:4071 +525:2:4072 +526:2:4079 +527:2:4084 +528:2:4091 +529:2:4092 +530:2:4091 +531:2:4092 +532:2:4099 +533:2:4103 +534:0:4464 +535:2:3321 +536:2:4002 +537:0:4464 +538:2:3131 +539:0:4464 +540:2:3322 +541:0:4464 +542:2:3131 +543:0:4464 +544:2:3325 +545:2:3326 +546:2:3330 +547:2:3331 +548:2:3339 +549:2:3340 +550:2:3344 +551:2:3345 +552:2:3353 +553:2:3358 +554:2:3362 +555:2:3363 +556:2:3371 +557:2:3372 +558:2:3376 +559:2:3377 +560:2:3371 +561:2:3372 +562:2:3376 +563:2:3377 +564:2:3385 +565:2:3390 +566:2:3391 +567:2:3402 +568:2:3403 +569:2:3404 +570:2:3415 +571:2:3420 +572:2:3421 +573:2:3432 +574:2:3433 +575:2:3434 +576:2:3432 +577:2:3433 +578:2:3434 +579:2:3445 +580:2:3452 +581:0:4464 +582:2:3131 +583:0:4464 +584:2:3456 +585:2:3457 +586:2:3458 +587:2:3470 +588:2:3471 +589:2:3475 +590:2:3476 +591:2:3484 +592:2:3489 +593:2:3493 +594:2:3494 +595:2:3502 +596:2:3503 +597:2:3507 +598:2:3508 +599:2:3502 +600:2:3503 +601:2:3507 +602:2:3508 +603:2:3516 +604:2:3521 +605:2:3522 +606:2:3533 +607:2:3534 +608:2:3535 +609:2:3546 +610:2:3551 +611:2:3552 +612:2:3563 +613:2:3564 +614:2:3565 +615:2:3563 +616:2:3564 +617:2:3565 +618:2:3576 +619:2:3586 +620:2:3587 +621:0:4464 +622:2:3131 +623:0:4464 +624:2:3990 +625:0:4464 +626:2:4294 +627:2:4295 +628:2:4299 +629:2:4303 +630:2:4304 +631:2:4308 +632:2:4316 +633:2:4317 +634:2:4321 +635:2:4325 +636:2:4326 +637:2:4321 +638:2:4325 +639:2:4326 +640:2:4330 +641:2:4337 +642:2:4344 +643:2:4345 +644:2:4352 +645:2:4357 +646:2:4364 +647:2:4365 +648:2:4364 +649:2:4365 +650:2:4372 +651:2:4376 +652:0:4464 +653:2:3992 +654:2:4002 +655:0:4464 +656:2:3131 +657:0:4464 +658:2:3993 +659:2:3994 +660:0:4464 +661:2:3131 +662:0:4464 +663:2:3998 +664:0:4464 +665:2:4006 +666:0:4464 +667:2:3124 +668:0:4464 +669:2:3126 +670:0:4464 +671:2:3127 +672:0:4464 +673:2:3128 +674:0:4464 +675:2:3129 +676:0:4464 +677:2:3130 +678:0:4464 +679:2:3131 +680:0:4464 +681:2:3132 +682:2:3133 +683:2:3137 +684:2:3138 +685:2:3146 +686:2:3147 +687:2:3151 +688:2:3152 +689:2:3160 +690:2:3165 +691:2:3169 +692:2:3170 +693:2:3178 +694:2:3179 +695:2:3183 +696:2:3184 +697:2:3178 +698:2:3179 +699:2:3180 +700:2:3192 +701:2:3197 +702:2:3198 +703:2:3209 +704:2:3210 +705:2:3211 +706:2:3222 +707:2:3227 +708:2:3228 +709:2:3239 +710:2:3240 +711:2:3241 +712:2:3239 +713:2:3240 +714:2:3241 +715:2:3252 +716:2:3260 +717:0:4464 +718:2:3131 +719:0:4464 +720:1:632 +721:1:633 +722:1:637 +723:1:638 +724:1:646 +725:1:647 +726:1:651 +727:1:652 +728:1:660 +729:1:665 +730:1:669 +731:1:670 +732:1:678 +733:1:679 +734:1:683 +735:1:684 +736:1:678 +737:1:679 +738:1:683 +739:1:684 +740:1:692 +741:1:697 +742:1:698 +743:1:709 +744:1:710 +745:1:711 +746:1:722 +747:1:734 +748:1:735 +749:1:739 +750:1:740 +751:1:741 +752:1:739 +753:1:740 +754:1:741 +755:1:752 +756:0:4464 +757:1:11 +758:0:4464 +759:1:761 +760:1:764 +761:1:765 +762:0:4464 +763:1:11 +764:0:4464 +765:1:1028 +766:1:1029 +767:1:1033 +768:1:1034 +769:1:1042 +770:1:1043 +771:1:1047 +772:1:1048 +773:1:1056 +774:1:1061 +775:1:1065 +776:1:1066 +777:1:1074 +778:1:1075 +779:1:1079 +780:1:1080 +781:1:1074 +782:1:1075 +783:1:1079 +784:1:1080 +785:1:1088 +786:1:1093 +787:1:1094 +788:1:1105 +789:1:1106 +790:1:1107 +791:1:1118 +792:1:1130 +793:1:1131 +794:1:1135 +795:1:1136 +796:1:1137 +797:1:1135 +798:1:1136 +799:1:1137 +800:1:1148 +801:1:1155 +802:1:1159 +803:0:4464 +804:1:11 +805:0:4464 +806:1:1160 +807:1:1161 +808:1:1165 +809:1:1166 +810:1:1174 +811:1:1175 +812:1:1176 +813:1:1188 +814:1:1193 +815:1:1197 +816:1:1198 +817:1:1206 +818:1:1207 +819:1:1211 +820:1:1212 +821:1:1206 +822:1:1207 +823:1:1211 +824:1:1212 +825:1:1220 +826:1:1225 +827:1:1226 +828:1:1237 +829:1:1238 +830:1:1239 +831:1:1250 +832:1:1262 +833:1:1263 +834:1:1267 +835:1:1268 +836:1:1269 +837:1:1267 +838:1:1268 +839:1:1269 +840:1:1280 +841:0:4464 +842:1:11 +843:0:4464 +844:1:1289 +845:0:4464 +846:1:3023 +847:1:3030 +848:1:3031 +849:1:3038 +850:1:3043 +851:1:3050 +852:1:3051 +853:1:3050 +854:1:3051 +855:1:3058 +856:1:3062 +857:0:4464 +858:2:3264 +859:2:3268 +860:2:3269 +861:2:3273 +862:2:3277 +863:2:3278 +864:2:3282 +865:2:3290 +866:2:3291 +867:2:3295 +868:2:3299 +869:2:3300 +870:2:3295 +871:2:3296 +872:2:3304 +873:0:4464 +874:2:3131 +875:0:4464 +876:2:3312 +877:2:3313 +878:2:3314 +879:0:4464 +880:2:3131 +881:0:4464 +882:2:3319 +883:0:4464 +884:2:4021 +885:2:4022 +886:2:4026 +887:2:4030 +888:2:4031 +889:2:4035 +890:2:4040 +891:2:4048 +892:2:4052 +893:2:4053 +894:2:4048 +895:2:4052 +896:2:4053 +897:2:4057 +898:2:4064 +899:2:4071 +900:2:4072 +901:2:4079 +902:2:4084 +903:2:4091 +904:2:4092 +905:2:4091 +906:2:4092 +907:2:4099 +908:2:4103 +909:0:4464 +910:2:3321 +911:2:4002 +912:0:4464 +913:2:3131 +914:0:4464 +915:2:3322 +916:0:4464 +917:2:3131 +918:0:4464 +919:2:3325 +920:2:3326 +921:2:3330 +922:2:3331 +923:2:3339 +924:2:3340 +925:2:3344 +926:2:3345 +927:2:3353 +928:2:3358 +929:2:3362 +930:2:3363 +931:2:3371 +932:2:3372 +933:2:3376 +934:2:3377 +935:2:3371 +936:2:3372 +937:2:3376 +938:2:3377 +939:2:3385 +940:2:3390 +941:2:3391 +942:2:3402 +943:2:3403 +944:2:3404 +945:2:3415 +946:2:3420 +947:2:3421 +948:2:3432 +949:2:3433 +950:2:3434 +951:2:3432 +952:2:3433 +953:2:3434 +954:2:3445 +955:2:3452 +956:0:4464 +957:2:3131 +958:0:4464 +959:2:3456 +960:2:3457 +961:2:3458 +962:2:3470 +963:2:3471 +964:2:3475 +965:2:3476 +966:2:3484 +967:2:3489 +968:2:3493 +969:2:3494 +970:2:3502 +971:2:3503 +972:2:3507 +973:2:3508 +974:2:3502 +975:2:3503 +976:2:3507 +977:2:3508 +978:2:3516 +979:2:3521 +980:2:3522 +981:2:3533 +982:2:3534 +983:2:3535 +984:2:3546 +985:2:3551 +986:2:3552 +987:2:3563 +988:2:3564 +989:2:3565 +990:2:3563 +991:2:3564 +992:2:3565 +993:2:3576 +994:2:3584 +995:0:4464 +996:2:3131 +997:0:4464 +998:2:3590 +999:0:4464 +1000:2:4112 +1001:2:4113 +1002:2:4117 +1003:2:4121 +1004:2:4122 +1005:2:4126 +1006:2:4134 +1007:2:4135 +1008:2:4139 +1009:2:4143 +1010:2:4144 +1011:2:4139 +1012:2:4143 +1013:2:4144 +1014:2:4148 +1015:2:4155 +1016:2:4162 +1017:2:4163 +1018:2:4170 +1019:2:4175 +1020:2:4182 +1021:2:4183 +1022:2:4182 +1023:2:4183 +1024:2:4190 +1025:2:4194 +1026:0:4464 +1027:2:3592 +1028:2:4002 +1029:0:4464 +1030:2:3131 +1031:0:4464 +1032:1:1291 +1033:1:1292 +1034:0:4462 +1035:1:11 +1036:0:4468 +1037:2:3480 diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress.ltl b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress.ltl new file mode 100644 index 0000000..8718641 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress.ltl @@ -0,0 +1 @@ +([] <> !np_) diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_reader.define b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_reader.define new file mode 100644 index 0000000..ff3f783 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_reader.define @@ -0,0 +1 @@ +#define READER_PROGRESS diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_reader.log b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_reader.log new file mode 100644 index 0000000..b4f4e20 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_reader.log @@ -0,0 +1,543 @@ +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define > pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_progress.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_progress_reader.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -f -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1258) +depth 23: Claim reached state 9 (line 1263) +depth 1143: Claim reached state 9 (line 1262) +Depth= 5344 States= 1e+06 Transitions= 4.94e+08 Memory= 506.389 t= 677 R= 1e+03 +Depth= 5344 States= 2e+06 Transitions= 1.22e+09 Memory= 545.647 t= 1.68e+03 R= 1e+03 +Depth= 5344 States= 3e+06 Transitions= 1.85e+09 Memory= 585.490 t= 2.58e+03 R= 1e+03 +pan: resizing hashtable to -w22.. done +Depth= 5344 States= 4e+06 Transitions= 2.51e+09 Memory= 656.358 t= 3.5e+03 R= 1e+03 +Depth= 5344 States= 5e+06 Transitions= 3.19e+09 Memory= 693.662 t= 4.45e+03 R= 1e+03 +Depth= 5344 States= 6e+06 Transitions= 3.87e+09 Memory= 736.240 t= 5.41e+03 R= 1e+03 +Depth= 5344 States= 7e+06 Transitions= 4.51e+09 Memory= 776.084 t= 6.3e+03 R= 1e+03 +Depth= 5344 States= 8e+06 Transitions= 5.21e+09 Memory= 816.416 t= 7.28e+03 R= 1e+03 + +(Spin Version 5.1.7 -- 23 December 2008) + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness enabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 5344, errors: 0 + 3811179 states, stored (8.02512e+06 visited) +5.2123433e+09 states, matched +5.2203684e+09 transitions (= visited+matched) +3.1088208e+10 atomic steps +hash conflicts: 1.9918982e+09 (resolved) + +Stats on memory usage (in Megabytes): + 421.616 equivalent memory usage for states (stored*(State-vector + overhead)) + 328.016 actual memory usage for states (compression: 77.80%) + state-vector as stored = 62 byte + 28 byte overhead + 32.000 memory used for hash table (-w22) + 457.764 memory used for DFS stack (-m10000000) + 817.490 total actual memory usage + +unreached in proctype urcu_reader + line 395, "pan.___", state 17, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 49, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 63, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 82, "(1)" + line 421, "pan.___", state 112, "(1)" + line 425, "pan.___", state 125, "(1)" + line 576, "pan.___", state 146, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 395, "pan.___", state 153, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 185, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 199, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 218, "(1)" + line 421, "pan.___", state 248, "(1)" + line 425, "pan.___", state 261, "(1)" + line 395, "pan.___", state 282, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 314, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 328, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 347, "(1)" + line 421, "pan.___", state 377, "(1)" + line 425, "pan.___", state 390, "(1)" + line 395, "pan.___", state 413, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 415, "(1)" + line 395, "pan.___", state 416, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 416, "else" + line 395, "pan.___", state 419, "(1)" + line 399, "pan.___", state 427, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 429, "(1)" + line 399, "pan.___", state 430, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 430, "else" + line 399, "pan.___", state 433, "(1)" + line 399, "pan.___", state 434, "(1)" + line 399, "pan.___", state 434, "(1)" + line 397, "pan.___", state 439, "((i<1))" + line 397, "pan.___", state 439, "((i>=1))" + line 404, "pan.___", state 445, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 447, "(1)" + line 404, "pan.___", state 448, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 448, "else" + line 404, "pan.___", state 451, "(1)" + line 404, "pan.___", state 452, "(1)" + line 404, "pan.___", state 452, "(1)" + line 408, "pan.___", state 459, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 461, "(1)" + line 408, "pan.___", state 462, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 462, "else" + line 408, "pan.___", state 465, "(1)" + line 408, "pan.___", state 466, "(1)" + line 408, "pan.___", state 466, "(1)" + line 406, "pan.___", state 471, "((i<2))" + line 406, "pan.___", state 471, "((i>=2))" + line 412, "pan.___", state 478, "(1)" + line 412, "pan.___", state 479, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 479, "else" + line 412, "pan.___", state 482, "(1)" + line 412, "pan.___", state 483, "(1)" + line 412, "pan.___", state 483, "(1)" + line 416, "pan.___", state 491, "(1)" + line 416, "pan.___", state 492, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 492, "else" + line 416, "pan.___", state 495, "(1)" + line 416, "pan.___", state 496, "(1)" + line 416, "pan.___", state 496, "(1)" + line 414, "pan.___", state 501, "((i<1))" + line 414, "pan.___", state 501, "((i>=1))" + line 421, "pan.___", state 508, "(1)" + line 421, "pan.___", state 509, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 509, "else" + line 421, "pan.___", state 512, "(1)" + line 421, "pan.___", state 513, "(1)" + line 421, "pan.___", state 513, "(1)" + line 425, "pan.___", state 521, "(1)" + line 425, "pan.___", state 522, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 522, "else" + line 425, "pan.___", state 525, "(1)" + line 425, "pan.___", state 526, "(1)" + line 425, "pan.___", state 526, "(1)" + line 423, "pan.___", state 531, "((i<2))" + line 423, "pan.___", state 531, "((i>=2))" + line 430, "pan.___", state 535, "(1)" + line 430, "pan.___", state 535, "(1)" + line 576, "pan.___", state 538, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 576, "pan.___", state 539, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 576, "pan.___", state 540, "(1)" + line 250, "pan.___", state 544, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 555, "(1)" + line 258, "pan.___", state 566, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 575, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 591, "(1)" + line 231, "pan.___", state 599, "(1)" + line 235, "pan.___", state 611, "(1)" + line 239, "pan.___", state 619, "(1)" + line 395, "pan.___", state 637, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 651, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 669, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 683, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 702, "(1)" + line 416, "pan.___", state 715, "(1)" + line 421, "pan.___", state 732, "(1)" + line 425, "pan.___", state 745, "(1)" + line 395, "pan.___", state 773, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 775, "(1)" + line 395, "pan.___", state 776, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 776, "else" + line 395, "pan.___", state 779, "(1)" + line 399, "pan.___", state 787, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 789, "(1)" + line 399, "pan.___", state 790, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 790, "else" + line 399, "pan.___", state 793, "(1)" + line 399, "pan.___", state 794, "(1)" + line 399, "pan.___", state 794, "(1)" + line 397, "pan.___", state 799, "((i<1))" + line 397, "pan.___", state 799, "((i>=1))" + line 404, "pan.___", state 805, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 807, "(1)" + line 404, "pan.___", state 808, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 808, "else" + line 404, "pan.___", state 811, "(1)" + line 404, "pan.___", state 812, "(1)" + line 404, "pan.___", state 812, "(1)" + line 408, "pan.___", state 819, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 821, "(1)" + line 408, "pan.___", state 822, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 822, "else" + line 408, "pan.___", state 825, "(1)" + line 408, "pan.___", state 826, "(1)" + line 408, "pan.___", state 826, "(1)" + line 406, "pan.___", state 831, "((i<2))" + line 406, "pan.___", state 831, "((i>=2))" + line 412, "pan.___", state 838, "(1)" + line 412, "pan.___", state 839, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 839, "else" + line 412, "pan.___", state 842, "(1)" + line 412, "pan.___", state 843, "(1)" + line 412, "pan.___", state 843, "(1)" + line 416, "pan.___", state 851, "(1)" + line 416, "pan.___", state 852, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 852, "else" + line 416, "pan.___", state 855, "(1)" + line 416, "pan.___", state 856, "(1)" + line 416, "pan.___", state 856, "(1)" + line 414, "pan.___", state 861, "((i<1))" + line 414, "pan.___", state 861, "((i>=1))" + line 421, "pan.___", state 868, "(1)" + line 421, "pan.___", state 869, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 869, "else" + line 421, "pan.___", state 872, "(1)" + line 421, "pan.___", state 873, "(1)" + line 421, "pan.___", state 873, "(1)" + line 425, "pan.___", state 881, "(1)" + line 425, "pan.___", state 882, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 882, "else" + line 425, "pan.___", state 885, "(1)" + line 425, "pan.___", state 886, "(1)" + line 425, "pan.___", state 886, "(1)" + line 430, "pan.___", state 895, "(1)" + line 430, "pan.___", state 895, "(1)" + line 395, "pan.___", state 902, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 904, "(1)" + line 395, "pan.___", state 905, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 905, "else" + line 395, "pan.___", state 908, "(1)" + line 399, "pan.___", state 916, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 918, "(1)" + line 399, "pan.___", state 919, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 919, "else" + line 399, "pan.___", state 922, "(1)" + line 399, "pan.___", state 923, "(1)" + line 399, "pan.___", state 923, "(1)" + line 397, "pan.___", state 928, "((i<1))" + line 397, "pan.___", state 928, "((i>=1))" + line 404, "pan.___", state 934, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 936, "(1)" + line 404, "pan.___", state 937, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 937, "else" + line 404, "pan.___", state 940, "(1)" + line 404, "pan.___", state 941, "(1)" + line 404, "pan.___", state 941, "(1)" + line 408, "pan.___", state 948, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 950, "(1)" + line 408, "pan.___", state 951, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 951, "else" + line 408, "pan.___", state 954, "(1)" + line 408, "pan.___", state 955, "(1)" + line 408, "pan.___", state 955, "(1)" + line 406, "pan.___", state 960, "((i<2))" + line 406, "pan.___", state 960, "((i>=2))" + line 412, "pan.___", state 967, "(1)" + line 412, "pan.___", state 968, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 968, "else" + line 412, "pan.___", state 971, "(1)" + line 412, "pan.___", state 972, "(1)" + line 412, "pan.___", state 972, "(1)" + line 416, "pan.___", state 980, "(1)" + line 416, "pan.___", state 981, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 981, "else" + line 416, "pan.___", state 984, "(1)" + line 416, "pan.___", state 985, "(1)" + line 416, "pan.___", state 985, "(1)" + line 414, "pan.___", state 990, "((i<1))" + line 414, "pan.___", state 990, "((i>=1))" + line 421, "pan.___", state 997, "(1)" + line 421, "pan.___", state 998, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 998, "else" + line 421, "pan.___", state 1001, "(1)" + line 421, "pan.___", state 1002, "(1)" + line 421, "pan.___", state 1002, "(1)" + line 425, "pan.___", state 1010, "(1)" + line 425, "pan.___", state 1011, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 1011, "else" + line 425, "pan.___", state 1014, "(1)" + line 425, "pan.___", state 1015, "(1)" + line 425, "pan.___", state 1015, "(1)" + line 423, "pan.___", state 1020, "((i<2))" + line 423, "pan.___", state 1020, "((i>=2))" + line 430, "pan.___", state 1024, "(1)" + line 430, "pan.___", state 1024, "(1)" + line 584, "pan.___", state 1028, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 395, "pan.___", state 1033, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1047, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1065, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1079, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1098, "(1)" + line 416, "pan.___", state 1111, "(1)" + line 421, "pan.___", state 1128, "(1)" + line 425, "pan.___", state 1141, "(1)" + line 395, "pan.___", state 1165, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1197, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1211, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1230, "(1)" + line 421, "pan.___", state 1260, "(1)" + line 425, "pan.___", state 1273, "(1)" + line 395, "pan.___", state 1298, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1330, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1344, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1363, "(1)" + line 421, "pan.___", state 1393, "(1)" + line 425, "pan.___", state 1406, "(1)" + line 395, "pan.___", state 1427, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1459, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1473, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1492, "(1)" + line 421, "pan.___", state 1522, "(1)" + line 425, "pan.___", state 1535, "(1)" + line 250, "pan.___", state 1558, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1580, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1589, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1605, "(1)" + line 231, "pan.___", state 1613, "(1)" + line 235, "pan.___", state 1625, "(1)" + line 239, "pan.___", state 1633, "(1)" + line 395, "pan.___", state 1651, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1665, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1683, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1697, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1716, "(1)" + line 416, "pan.___", state 1729, "(1)" + line 421, "pan.___", state 1746, "(1)" + line 425, "pan.___", state 1759, "(1)" + line 395, "pan.___", state 1780, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1794, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1812, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1826, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1845, "(1)" + line 416, "pan.___", state 1858, "(1)" + line 421, "pan.___", state 1875, "(1)" + line 425, "pan.___", state 1888, "(1)" + line 395, "pan.___", state 1912, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1928, "(1)" + line 404, "pan.___", state 1944, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1958, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1977, "(1)" + line 421, "pan.___", state 2007, "(1)" + line 425, "pan.___", state 2020, "(1)" + line 623, "pan.___", state 2041, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 395, "pan.___", state 2048, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2080, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2094, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2113, "(1)" + line 421, "pan.___", state 2143, "(1)" + line 425, "pan.___", state 2156, "(1)" + line 395, "pan.___", state 2177, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2209, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2223, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2242, "(1)" + line 421, "pan.___", state 2272, "(1)" + line 425, "pan.___", state 2285, "(1)" + line 395, "pan.___", state 2308, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 2310, "(1)" + line 395, "pan.___", state 2311, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 2311, "else" + line 395, "pan.___", state 2314, "(1)" + line 399, "pan.___", state 2322, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2324, "(1)" + line 399, "pan.___", state 2325, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 2325, "else" + line 399, "pan.___", state 2328, "(1)" + line 399, "pan.___", state 2329, "(1)" + line 399, "pan.___", state 2329, "(1)" + line 397, "pan.___", state 2334, "((i<1))" + line 397, "pan.___", state 2334, "((i>=1))" + line 404, "pan.___", state 2340, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2342, "(1)" + line 404, "pan.___", state 2343, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 2343, "else" + line 404, "pan.___", state 2346, "(1)" + line 404, "pan.___", state 2347, "(1)" + line 404, "pan.___", state 2347, "(1)" + line 408, "pan.___", state 2354, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2356, "(1)" + line 408, "pan.___", state 2357, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 2357, "else" + line 408, "pan.___", state 2360, "(1)" + line 408, "pan.___", state 2361, "(1)" + line 408, "pan.___", state 2361, "(1)" + line 406, "pan.___", state 2366, "((i<2))" + line 406, "pan.___", state 2366, "((i>=2))" + line 412, "pan.___", state 2373, "(1)" + line 412, "pan.___", state 2374, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 2374, "else" + line 412, "pan.___", state 2377, "(1)" + line 412, "pan.___", state 2378, "(1)" + line 412, "pan.___", state 2378, "(1)" + line 416, "pan.___", state 2386, "(1)" + line 416, "pan.___", state 2387, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 2387, "else" + line 416, "pan.___", state 2390, "(1)" + line 416, "pan.___", state 2391, "(1)" + line 416, "pan.___", state 2391, "(1)" + line 414, "pan.___", state 2396, "((i<1))" + line 414, "pan.___", state 2396, "((i>=1))" + line 421, "pan.___", state 2403, "(1)" + line 421, "pan.___", state 2404, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 2404, "else" + line 421, "pan.___", state 2407, "(1)" + line 421, "pan.___", state 2408, "(1)" + line 421, "pan.___", state 2408, "(1)" + line 425, "pan.___", state 2416, "(1)" + line 425, "pan.___", state 2417, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 2417, "else" + line 425, "pan.___", state 2420, "(1)" + line 425, "pan.___", state 2421, "(1)" + line 425, "pan.___", state 2421, "(1)" + line 423, "pan.___", state 2426, "((i<2))" + line 423, "pan.___", state 2426, "((i>=2))" + line 430, "pan.___", state 2430, "(1)" + line 430, "pan.___", state 2430, "(1)" + line 623, "pan.___", state 2433, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 623, "pan.___", state 2434, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 623, "pan.___", state 2435, "(1)" + line 250, "pan.___", state 2439, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 2450, "(1)" + line 258, "pan.___", state 2461, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 2470, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 2486, "(1)" + line 231, "pan.___", state 2494, "(1)" + line 235, "pan.___", state 2506, "(1)" + line 239, "pan.___", state 2514, "(1)" + line 395, "pan.___", state 2532, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2546, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2564, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2578, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2597, "(1)" + line 416, "pan.___", state 2610, "(1)" + line 421, "pan.___", state 2627, "(1)" + line 425, "pan.___", state 2640, "(1)" + line 250, "pan.___", state 2664, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 2673, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 2686, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 2695, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 2711, "(1)" + line 231, "pan.___", state 2719, "(1)" + line 235, "pan.___", state 2731, "(1)" + line 239, "pan.___", state 2739, "(1)" + line 395, "pan.___", state 2757, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2771, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2789, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2803, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2822, "(1)" + line 416, "pan.___", state 2835, "(1)" + line 421, "pan.___", state 2852, "(1)" + line 425, "pan.___", state 2865, "(1)" + line 395, "pan.___", state 2886, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2900, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2918, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2932, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2951, "(1)" + line 416, "pan.___", state 2964, "(1)" + line 421, "pan.___", state 2981, "(1)" + line 425, "pan.___", state 2994, "(1)" + line 227, "pan.___", state 3027, "(1)" + line 235, "pan.___", state 3047, "(1)" + line 239, "pan.___", state 3055, "(1)" + line 227, "pan.___", state 3070, "(1)" + line 231, "pan.___", state 3078, "(1)" + line 235, "pan.___", state 3090, "(1)" + line 239, "pan.___", state 3098, "(1)" + line 877, "pan.___", state 3115, "-end-" + (318 of 3115 states) +unreached in proctype urcu_writer + line 395, "pan.___", state 18, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 32, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 50, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 412, "pan.___", state 83, "(1)" + line 416, "pan.___", state 96, "(1)" + line 421, "pan.___", state 113, "(1)" + line 250, "pan.___", state 149, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 158, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 171, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 211, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 225, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 243, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 257, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 276, "(1)" + line 416, "pan.___", state 289, "(1)" + line 421, "pan.___", state 306, "(1)" + line 425, "pan.___", state 319, "(1)" + line 399, "pan.___", state 356, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 374, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 388, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 420, "(1)" + line 421, "pan.___", state 437, "(1)" + line 425, "pan.___", state 450, "(1)" + line 399, "pan.___", state 494, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 512, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 526, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 558, "(1)" + line 421, "pan.___", state 575, "(1)" + line 425, "pan.___", state 588, "(1)" + line 399, "pan.___", state 623, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 641, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 655, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 687, "(1)" + line 421, "pan.___", state 704, "(1)" + line 425, "pan.___", state 717, "(1)" + line 399, "pan.___", state 754, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 772, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 786, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 818, "(1)" + line 421, "pan.___", state 835, "(1)" + line 425, "pan.___", state 848, "(1)" + line 250, "pan.___", state 898, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 907, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 920, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 227, "pan.___", state 945, "(1)" + line 231, "pan.___", state 953, "(1)" + line 235, "pan.___", state 965, "(1)" + line 239, "pan.___", state 973, "(1)" + line 250, "pan.___", state 993, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 1002, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1017, "(1)" + line 262, "pan.___", state 1024, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1040, "(1)" + line 231, "pan.___", state 1048, "(1)" + line 235, "pan.___", state 1060, "(1)" + line 239, "pan.___", state 1068, "(1)" + line 254, "pan.___", state 1093, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1106, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1115, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1131, "(1)" + line 231, "pan.___", state 1139, "(1)" + line 235, "pan.___", state 1151, "(1)" + line 239, "pan.___", state 1159, "(1)" + line 254, "pan.___", state 1184, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1197, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1206, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1222, "(1)" + line 231, "pan.___", state 1230, "(1)" + line 235, "pan.___", state 1242, "(1)" + line 239, "pan.___", state 1250, "(1)" + line 254, "pan.___", state 1275, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1288, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1297, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1313, "(1)" + line 231, "pan.___", state 1321, "(1)" + line 235, "pan.___", state 1333, "(1)" + line 239, "pan.___", state 1341, "(1)" + line 1204, "pan.___", state 1356, "-end-" + (78 of 1356 states) +unreached in proctype :init: + (0 of 78 states) +unreached in proctype :never: + line 1265, "pan.___", state 11, "-end-" + (1 of 11 states) + +pan: elapsed time 7.29e+03 seconds +pan: rate 1100.4528 states/second +pan: avg transition delay 1.3969e-06 usec +cp .input.spin urcu_progress_reader.spin.input +cp .input.spin.trail urcu_progress_reader.spin.input.trail diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_reader.spin.input b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_reader.spin.input new file mode 100644 index 0000000..a9b6907 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_reader.spin.input @@ -0,0 +1,1240 @@ +#define READER_PROGRESS + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +//#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer.define b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer.define new file mode 100644 index 0000000..1e4417f --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer.define @@ -0,0 +1 @@ +#define WRITER_PROGRESS diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer.log b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer.log new file mode 100644 index 0000000..240c728 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer.log @@ -0,0 +1,536 @@ +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define > pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_progress.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_progress_writer.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -f -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1258) +depth 23: Claim reached state 9 (line 1263) +depth 1481: Claim reached state 9 (line 1262) +Depth= 4026 States= 1e+06 Transitions= 4.1e+08 Memory= 492.131 t= 536 R= 2e+03 +Depth= 4485 States= 2e+06 Transitions= 8.98e+08 Memory= 518.401 t= 1.18e+03 R= 2e+03 +Depth= 4485 States= 3e+06 Transitions= 1.65e+09 Memory= 565.666 t= 2.18e+03 R= 1e+03 +pan: resizing hashtable to -w22.. done +Depth= 4694 States= 4e+06 Transitions= 2.35e+09 Memory= 638.975 t= 3.12e+03 R= 1e+03 +Depth= 4694 States= 5e+06 Transitions= 3.04e+09 Memory= 684.190 t= 4.03e+03 R= 1e+03 +Depth= 4694 States= 6e+06 Transitions= 3.8e+09 Memory= 723.936 t= 5.04e+03 R= 1e+03 +Depth= 4694 States= 7e+06 Transitions= 4.45e+09 Memory= 769.248 t= 5.92e+03 R= 1e+03 +Depth= 4694 States= 8e+06 Transitions= 5.23e+09 Memory= 814.561 t= 6.96e+03 R= 1e+03 + +(Spin Version 5.1.7 -- 23 December 2008) + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness enabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 4694, errors: 0 + 3819484 states, stored (8.06154e+06 visited) +5.2640635e+09 states, matched +5.272125e+09 transitions (= visited+matched) +3.1366722e+10 atomic steps +hash conflicts: 1.5911163e+09 (resolved) + +Stats on memory usage (in Megabytes): + 422.535 equivalent memory usage for states (stored*(State-vector + overhead)) + 328.667 actual memory usage for states (compression: 77.78%) + state-vector as stored = 62 byte + 28 byte overhead + 32.000 memory used for hash table (-w22) + 457.764 memory used for DFS stack (-m10000000) + 818.174 total actual memory usage + +unreached in proctype urcu_reader + line 395, "pan.___", state 17, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 49, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 63, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 82, "(1)" + line 421, "pan.___", state 112, "(1)" + line 425, "pan.___", state 125, "(1)" + line 576, "pan.___", state 146, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 395, "pan.___", state 153, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 185, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 199, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 218, "(1)" + line 421, "pan.___", state 248, "(1)" + line 425, "pan.___", state 261, "(1)" + line 395, "pan.___", state 282, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 314, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 328, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 347, "(1)" + line 421, "pan.___", state 377, "(1)" + line 425, "pan.___", state 390, "(1)" + line 395, "pan.___", state 413, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 415, "(1)" + line 395, "pan.___", state 416, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 416, "else" + line 395, "pan.___", state 419, "(1)" + line 399, "pan.___", state 427, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 429, "(1)" + line 399, "pan.___", state 430, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 430, "else" + line 399, "pan.___", state 433, "(1)" + line 399, "pan.___", state 434, "(1)" + line 399, "pan.___", state 434, "(1)" + line 397, "pan.___", state 439, "((i<1))" + line 397, "pan.___", state 439, "((i>=1))" + line 404, "pan.___", state 445, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 447, "(1)" + line 404, "pan.___", state 448, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 448, "else" + line 404, "pan.___", state 451, "(1)" + line 404, "pan.___", state 452, "(1)" + line 404, "pan.___", state 452, "(1)" + line 408, "pan.___", state 459, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 461, "(1)" + line 408, "pan.___", state 462, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 462, "else" + line 408, "pan.___", state 465, "(1)" + line 408, "pan.___", state 466, "(1)" + line 408, "pan.___", state 466, "(1)" + line 406, "pan.___", state 471, "((i<2))" + line 406, "pan.___", state 471, "((i>=2))" + line 412, "pan.___", state 478, "(1)" + line 412, "pan.___", state 479, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 479, "else" + line 412, "pan.___", state 482, "(1)" + line 412, "pan.___", state 483, "(1)" + line 412, "pan.___", state 483, "(1)" + line 416, "pan.___", state 491, "(1)" + line 416, "pan.___", state 492, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 492, "else" + line 416, "pan.___", state 495, "(1)" + line 416, "pan.___", state 496, "(1)" + line 416, "pan.___", state 496, "(1)" + line 414, "pan.___", state 501, "((i<1))" + line 414, "pan.___", state 501, "((i>=1))" + line 421, "pan.___", state 508, "(1)" + line 421, "pan.___", state 509, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 509, "else" + line 421, "pan.___", state 512, "(1)" + line 421, "pan.___", state 513, "(1)" + line 421, "pan.___", state 513, "(1)" + line 425, "pan.___", state 521, "(1)" + line 425, "pan.___", state 522, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 522, "else" + line 425, "pan.___", state 525, "(1)" + line 425, "pan.___", state 526, "(1)" + line 425, "pan.___", state 526, "(1)" + line 423, "pan.___", state 531, "((i<2))" + line 423, "pan.___", state 531, "((i>=2))" + line 430, "pan.___", state 535, "(1)" + line 430, "pan.___", state 535, "(1)" + line 576, "pan.___", state 538, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 576, "pan.___", state 539, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 576, "pan.___", state 540, "(1)" + line 250, "pan.___", state 544, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 555, "(1)" + line 258, "pan.___", state 566, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 575, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 591, "(1)" + line 231, "pan.___", state 599, "(1)" + line 235, "pan.___", state 611, "(1)" + line 239, "pan.___", state 619, "(1)" + line 395, "pan.___", state 637, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 651, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 669, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 683, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 702, "(1)" + line 416, "pan.___", state 715, "(1)" + line 421, "pan.___", state 732, "(1)" + line 425, "pan.___", state 745, "(1)" + line 395, "pan.___", state 773, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 775, "(1)" + line 395, "pan.___", state 776, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 776, "else" + line 395, "pan.___", state 779, "(1)" + line 399, "pan.___", state 787, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 789, "(1)" + line 399, "pan.___", state 790, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 790, "else" + line 399, "pan.___", state 793, "(1)" + line 399, "pan.___", state 794, "(1)" + line 399, "pan.___", state 794, "(1)" + line 397, "pan.___", state 799, "((i<1))" + line 397, "pan.___", state 799, "((i>=1))" + line 404, "pan.___", state 805, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 807, "(1)" + line 404, "pan.___", state 808, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 808, "else" + line 404, "pan.___", state 811, "(1)" + line 404, "pan.___", state 812, "(1)" + line 404, "pan.___", state 812, "(1)" + line 408, "pan.___", state 819, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 821, "(1)" + line 408, "pan.___", state 822, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 822, "else" + line 408, "pan.___", state 825, "(1)" + line 408, "pan.___", state 826, "(1)" + line 408, "pan.___", state 826, "(1)" + line 406, "pan.___", state 831, "((i<2))" + line 406, "pan.___", state 831, "((i>=2))" + line 412, "pan.___", state 838, "(1)" + line 412, "pan.___", state 839, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 839, "else" + line 412, "pan.___", state 842, "(1)" + line 412, "pan.___", state 843, "(1)" + line 412, "pan.___", state 843, "(1)" + line 416, "pan.___", state 851, "(1)" + line 416, "pan.___", state 852, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 852, "else" + line 416, "pan.___", state 855, "(1)" + line 416, "pan.___", state 856, "(1)" + line 416, "pan.___", state 856, "(1)" + line 414, "pan.___", state 861, "((i<1))" + line 414, "pan.___", state 861, "((i>=1))" + line 421, "pan.___", state 868, "(1)" + line 421, "pan.___", state 869, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 869, "else" + line 421, "pan.___", state 872, "(1)" + line 421, "pan.___", state 873, "(1)" + line 421, "pan.___", state 873, "(1)" + line 425, "pan.___", state 881, "(1)" + line 425, "pan.___", state 882, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 882, "else" + line 425, "pan.___", state 885, "(1)" + line 425, "pan.___", state 886, "(1)" + line 425, "pan.___", state 886, "(1)" + line 430, "pan.___", state 895, "(1)" + line 430, "pan.___", state 895, "(1)" + line 395, "pan.___", state 902, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 904, "(1)" + line 395, "pan.___", state 905, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 905, "else" + line 395, "pan.___", state 908, "(1)" + line 399, "pan.___", state 916, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 918, "(1)" + line 399, "pan.___", state 919, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 919, "else" + line 399, "pan.___", state 922, "(1)" + line 399, "pan.___", state 923, "(1)" + line 399, "pan.___", state 923, "(1)" + line 397, "pan.___", state 928, "((i<1))" + line 397, "pan.___", state 928, "((i>=1))" + line 404, "pan.___", state 934, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 936, "(1)" + line 404, "pan.___", state 937, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 937, "else" + line 404, "pan.___", state 940, "(1)" + line 404, "pan.___", state 941, "(1)" + line 404, "pan.___", state 941, "(1)" + line 408, "pan.___", state 948, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 950, "(1)" + line 408, "pan.___", state 951, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 951, "else" + line 408, "pan.___", state 954, "(1)" + line 408, "pan.___", state 955, "(1)" + line 408, "pan.___", state 955, "(1)" + line 406, "pan.___", state 960, "((i<2))" + line 406, "pan.___", state 960, "((i>=2))" + line 412, "pan.___", state 967, "(1)" + line 412, "pan.___", state 968, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 968, "else" + line 412, "pan.___", state 971, "(1)" + line 412, "pan.___", state 972, "(1)" + line 412, "pan.___", state 972, "(1)" + line 416, "pan.___", state 980, "(1)" + line 416, "pan.___", state 981, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 981, "else" + line 416, "pan.___", state 984, "(1)" + line 416, "pan.___", state 985, "(1)" + line 416, "pan.___", state 985, "(1)" + line 414, "pan.___", state 990, "((i<1))" + line 414, "pan.___", state 990, "((i>=1))" + line 421, "pan.___", state 997, "(1)" + line 421, "pan.___", state 998, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 998, "else" + line 421, "pan.___", state 1001, "(1)" + line 421, "pan.___", state 1002, "(1)" + line 421, "pan.___", state 1002, "(1)" + line 425, "pan.___", state 1010, "(1)" + line 425, "pan.___", state 1011, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 1011, "else" + line 425, "pan.___", state 1014, "(1)" + line 425, "pan.___", state 1015, "(1)" + line 425, "pan.___", state 1015, "(1)" + line 423, "pan.___", state 1020, "((i<2))" + line 423, "pan.___", state 1020, "((i>=2))" + line 430, "pan.___", state 1024, "(1)" + line 430, "pan.___", state 1024, "(1)" + line 584, "pan.___", state 1028, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 395, "pan.___", state 1033, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1047, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1065, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1079, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1098, "(1)" + line 416, "pan.___", state 1111, "(1)" + line 421, "pan.___", state 1128, "(1)" + line 425, "pan.___", state 1141, "(1)" + line 395, "pan.___", state 1165, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1197, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1211, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1230, "(1)" + line 421, "pan.___", state 1260, "(1)" + line 425, "pan.___", state 1273, "(1)" + line 395, "pan.___", state 1298, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1330, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1344, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1363, "(1)" + line 421, "pan.___", state 1393, "(1)" + line 425, "pan.___", state 1406, "(1)" + line 395, "pan.___", state 1427, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1459, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1473, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1492, "(1)" + line 421, "pan.___", state 1522, "(1)" + line 425, "pan.___", state 1535, "(1)" + line 250, "pan.___", state 1558, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1580, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1589, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1605, "(1)" + line 231, "pan.___", state 1613, "(1)" + line 235, "pan.___", state 1625, "(1)" + line 239, "pan.___", state 1633, "(1)" + line 395, "pan.___", state 1651, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1665, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1683, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1697, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1716, "(1)" + line 416, "pan.___", state 1729, "(1)" + line 421, "pan.___", state 1746, "(1)" + line 425, "pan.___", state 1759, "(1)" + line 395, "pan.___", state 1780, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1794, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 1812, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1826, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1845, "(1)" + line 416, "pan.___", state 1858, "(1)" + line 421, "pan.___", state 1875, "(1)" + line 425, "pan.___", state 1888, "(1)" + line 395, "pan.___", state 1912, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 1928, "(1)" + line 404, "pan.___", state 1944, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 1958, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 1977, "(1)" + line 421, "pan.___", state 2007, "(1)" + line 425, "pan.___", state 2020, "(1)" + line 623, "pan.___", state 2041, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 395, "pan.___", state 2048, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2080, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2094, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2113, "(1)" + line 421, "pan.___", state 2143, "(1)" + line 425, "pan.___", state 2156, "(1)" + line 395, "pan.___", state 2177, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2209, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2223, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2242, "(1)" + line 421, "pan.___", state 2272, "(1)" + line 425, "pan.___", state 2285, "(1)" + line 395, "pan.___", state 2308, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 2310, "(1)" + line 395, "pan.___", state 2311, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 395, "pan.___", state 2311, "else" + line 395, "pan.___", state 2314, "(1)" + line 399, "pan.___", state 2322, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2324, "(1)" + line 399, "pan.___", state 2325, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 399, "pan.___", state 2325, "else" + line 399, "pan.___", state 2328, "(1)" + line 399, "pan.___", state 2329, "(1)" + line 399, "pan.___", state 2329, "(1)" + line 397, "pan.___", state 2334, "((i<1))" + line 397, "pan.___", state 2334, "((i>=1))" + line 404, "pan.___", state 2340, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2342, "(1)" + line 404, "pan.___", state 2343, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 404, "pan.___", state 2343, "else" + line 404, "pan.___", state 2346, "(1)" + line 404, "pan.___", state 2347, "(1)" + line 404, "pan.___", state 2347, "(1)" + line 408, "pan.___", state 2354, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2356, "(1)" + line 408, "pan.___", state 2357, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 408, "pan.___", state 2357, "else" + line 408, "pan.___", state 2360, "(1)" + line 408, "pan.___", state 2361, "(1)" + line 408, "pan.___", state 2361, "(1)" + line 406, "pan.___", state 2366, "((i<2))" + line 406, "pan.___", state 2366, "((i>=2))" + line 412, "pan.___", state 2373, "(1)" + line 412, "pan.___", state 2374, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 412, "pan.___", state 2374, "else" + line 412, "pan.___", state 2377, "(1)" + line 412, "pan.___", state 2378, "(1)" + line 412, "pan.___", state 2378, "(1)" + line 416, "pan.___", state 2386, "(1)" + line 416, "pan.___", state 2387, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 416, "pan.___", state 2387, "else" + line 416, "pan.___", state 2390, "(1)" + line 416, "pan.___", state 2391, "(1)" + line 416, "pan.___", state 2391, "(1)" + line 414, "pan.___", state 2396, "((i<1))" + line 414, "pan.___", state 2396, "((i>=1))" + line 421, "pan.___", state 2403, "(1)" + line 421, "pan.___", state 2404, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 421, "pan.___", state 2404, "else" + line 421, "pan.___", state 2407, "(1)" + line 421, "pan.___", state 2408, "(1)" + line 421, "pan.___", state 2408, "(1)" + line 425, "pan.___", state 2416, "(1)" + line 425, "pan.___", state 2417, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 425, "pan.___", state 2417, "else" + line 425, "pan.___", state 2420, "(1)" + line 425, "pan.___", state 2421, "(1)" + line 425, "pan.___", state 2421, "(1)" + line 423, "pan.___", state 2426, "((i<2))" + line 423, "pan.___", state 2426, "((i>=2))" + line 430, "pan.___", state 2430, "(1)" + line 430, "pan.___", state 2430, "(1)" + line 623, "pan.___", state 2433, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 623, "pan.___", state 2434, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 623, "pan.___", state 2435, "(1)" + line 250, "pan.___", state 2439, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 2450, "(1)" + line 258, "pan.___", state 2461, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 2470, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 2486, "(1)" + line 231, "pan.___", state 2494, "(1)" + line 235, "pan.___", state 2506, "(1)" + line 239, "pan.___", state 2514, "(1)" + line 395, "pan.___", state 2532, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2546, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2564, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2578, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2597, "(1)" + line 416, "pan.___", state 2610, "(1)" + line 421, "pan.___", state 2627, "(1)" + line 425, "pan.___", state 2640, "(1)" + line 250, "pan.___", state 2664, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 2673, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 2686, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 2695, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 2711, "(1)" + line 231, "pan.___", state 2719, "(1)" + line 235, "pan.___", state 2731, "(1)" + line 239, "pan.___", state 2739, "(1)" + line 395, "pan.___", state 2757, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2771, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2789, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2803, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2822, "(1)" + line 416, "pan.___", state 2835, "(1)" + line 421, "pan.___", state 2852, "(1)" + line 425, "pan.___", state 2865, "(1)" + line 395, "pan.___", state 2886, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 2900, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 2918, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 2932, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 2951, "(1)" + line 416, "pan.___", state 2964, "(1)" + line 421, "pan.___", state 2981, "(1)" + line 425, "pan.___", state 2994, "(1)" + line 227, "pan.___", state 3027, "(1)" + line 235, "pan.___", state 3047, "(1)" + line 239, "pan.___", state 3055, "(1)" + line 227, "pan.___", state 3070, "(1)" + line 231, "pan.___", state 3078, "(1)" + line 235, "pan.___", state 3090, "(1)" + line 239, "pan.___", state 3098, "(1)" + line 877, "pan.___", state 3115, "-end-" + (318 of 3115 states) +unreached in proctype urcu_writer + line 395, "pan.___", state 18, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 32, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 50, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 412, "pan.___", state 83, "(1)" + line 416, "pan.___", state 96, "(1)" + line 421, "pan.___", state 113, "(1)" + line 250, "pan.___", state 149, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 158, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 171, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 395, "pan.___", state 211, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 399, "pan.___", state 225, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 243, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 257, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 412, "pan.___", state 276, "(1)" + line 416, "pan.___", state 289, "(1)" + line 421, "pan.___", state 306, "(1)" + line 425, "pan.___", state 319, "(1)" + line 399, "pan.___", state 356, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 374, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 388, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 420, "(1)" + line 421, "pan.___", state 437, "(1)" + line 425, "pan.___", state 450, "(1)" + line 399, "pan.___", state 494, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 512, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 526, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 558, "(1)" + line 421, "pan.___", state 575, "(1)" + line 425, "pan.___", state 588, "(1)" + line 399, "pan.___", state 623, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 641, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 655, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 687, "(1)" + line 421, "pan.___", state 704, "(1)" + line 425, "pan.___", state 717, "(1)" + line 399, "pan.___", state 754, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 404, "pan.___", state 772, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 408, "pan.___", state 786, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 416, "pan.___", state 818, "(1)" + line 421, "pan.___", state 835, "(1)" + line 425, "pan.___", state 848, "(1)" + line 250, "pan.___", state 903, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 254, "pan.___", state 912, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 927, "(1)" + line 262, "pan.___", state 934, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 950, "(1)" + line 231, "pan.___", state 958, "(1)" + line 235, "pan.___", state 970, "(1)" + line 239, "pan.___", state 978, "(1)" + line 254, "pan.___", state 1003, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1016, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1025, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1041, "(1)" + line 231, "pan.___", state 1049, "(1)" + line 235, "pan.___", state 1061, "(1)" + line 239, "pan.___", state 1069, "(1)" + line 254, "pan.___", state 1094, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1107, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1116, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1132, "(1)" + line 231, "pan.___", state 1140, "(1)" + line 235, "pan.___", state 1152, "(1)" + line 239, "pan.___", state 1160, "(1)" + line 254, "pan.___", state 1185, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 258, "pan.___", state 1198, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 262, "pan.___", state 1207, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 227, "pan.___", state 1223, "(1)" + line 231, "pan.___", state 1231, "(1)" + line 235, "pan.___", state 1243, "(1)" + line 239, "pan.___", state 1251, "(1)" + line 1204, "pan.___", state 1266, "-end-" + (71 of 1266 states) +unreached in proctype :init: + (0 of 78 states) +unreached in proctype :never: + line 1265, "pan.___", state 11, "-end-" + (1 of 11 states) + +pan: elapsed time 7.01e+03 seconds +pan: rate 1149.3413 states/second +pan: avg transition delay 1.3304e-06 usec +cp .input.spin urcu_progress_writer.spin.input +cp .input.spin.trail urcu_progress_writer.spin.input.trail diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer.spin.input b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer.spin.input new file mode 100644 index 0000000..d9d698f --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer.spin.input @@ -0,0 +1,1240 @@ +#define WRITER_PROGRESS + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +//#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer_error.define b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer_error.define new file mode 100644 index 0000000..8d304f5 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer_error.define @@ -0,0 +1,2 @@ +#define WRITER_PROGRESS +#define GEN_ERROR_WRITER_PROGRESS diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer_error.log b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer_error.log new file mode 100644 index 0000000..99db2db --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer_error.log @@ -0,0 +1,809 @@ +rm -f pan* trail.out .input.spin* *.spin.trail .input.define +touch .input.define +cat .input.define > pan.ltl +cat DEFINES >> pan.ltl +spin -f "!(`cat urcu_progress.ltl | grep -v ^//`)" >> pan.ltl +cp urcu_progress_writer_error.define .input.define +cat .input.define > .input.spin +cat DEFINES >> .input.spin +cat urcu.spin >> .input.spin +rm -f .input.spin.trail +spin -a -X -N pan.ltl .input.spin +Exit-Status 0 +gcc -O2 -w -DHASH64 -o pan pan.c +./pan -a -f -v -c1 -X -m10000000 -w20 +warning: for p.o. reduction to be valid the never claim must be stutter-invariant +(never claims generated from LTL formulae are stutter-invariant) +depth 0: Claim reached state 5 (line 1259) +depth 23: Claim reached state 9 (line 1264) +depth 1481: Claim reached state 9 (line 1263) +pan: acceptance cycle (at depth 7186) +pan: wrote .input.spin.trail + +(Spin Version 5.1.7 -- 23 December 2008) +Warning: Search not completed + + Partial Order Reduction + +Full statespace search for: + never claim + + assertion violations + (if within scope of claim) + acceptance cycles + (fairness enabled) + invalid end states - (disabled by never claim) + +State-vector 88 byte, depth reached 8718, errors: 1 + 25100 states, stored (77932 visited) + 18210466 states, matched + 18288398 transitions (= visited+matched) +1.0440929e+08 atomic steps +hash conflicts: 119465 (resolved) + +Stats on memory usage (in Megabytes): + 2.777 equivalent memory usage for states (stored*(State-vector + overhead)) + 2.791 actual memory usage for states (unsuccessful compression: 100.52%) + state-vector as stored = 89 byte + 28 byte overhead + 8.000 memory used for hash table (-w20) + 457.764 memory used for DFS stack (-m10000000) + 468.498 total actual memory usage + +unreached in proctype urcu_reader + line 396, "pan.___", state 17, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 49, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 63, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 82, "(1)" + line 422, "pan.___", state 112, "(1)" + line 426, "pan.___", state 125, "(1)" + line 577, "pan.___", state 146, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<1))" + line 396, "pan.___", state 153, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 185, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 199, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 218, "(1)" + line 422, "pan.___", state 248, "(1)" + line 426, "pan.___", state 261, "(1)" + line 396, "pan.___", state 282, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 314, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 328, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 347, "(1)" + line 422, "pan.___", state 377, "(1)" + line 426, "pan.___", state 390, "(1)" + line 396, "pan.___", state 413, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 415, "(1)" + line 396, "pan.___", state 416, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 416, "else" + line 396, "pan.___", state 419, "(1)" + line 400, "pan.___", state 427, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 429, "(1)" + line 400, "pan.___", state 430, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 400, "pan.___", state 430, "else" + line 400, "pan.___", state 433, "(1)" + line 400, "pan.___", state 434, "(1)" + line 400, "pan.___", state 434, "(1)" + line 398, "pan.___", state 439, "((i<1))" + line 398, "pan.___", state 439, "((i>=1))" + line 405, "pan.___", state 445, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 447, "(1)" + line 405, "pan.___", state 448, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 405, "pan.___", state 448, "else" + line 405, "pan.___", state 451, "(1)" + line 405, "pan.___", state 452, "(1)" + line 405, "pan.___", state 452, "(1)" + line 409, "pan.___", state 459, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 461, "(1)" + line 409, "pan.___", state 462, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 409, "pan.___", state 462, "else" + line 409, "pan.___", state 465, "(1)" + line 409, "pan.___", state 466, "(1)" + line 409, "pan.___", state 466, "(1)" + line 407, "pan.___", state 471, "((i<2))" + line 407, "pan.___", state 471, "((i>=2))" + line 413, "pan.___", state 478, "(1)" + line 413, "pan.___", state 479, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 479, "else" + line 413, "pan.___", state 482, "(1)" + line 413, "pan.___", state 483, "(1)" + line 413, "pan.___", state 483, "(1)" + line 417, "pan.___", state 491, "(1)" + line 417, "pan.___", state 492, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 417, "pan.___", state 492, "else" + line 417, "pan.___", state 495, "(1)" + line 417, "pan.___", state 496, "(1)" + line 417, "pan.___", state 496, "(1)" + line 415, "pan.___", state 501, "((i<1))" + line 415, "pan.___", state 501, "((i>=1))" + line 422, "pan.___", state 508, "(1)" + line 422, "pan.___", state 509, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 422, "pan.___", state 509, "else" + line 422, "pan.___", state 512, "(1)" + line 422, "pan.___", state 513, "(1)" + line 422, "pan.___", state 513, "(1)" + line 426, "pan.___", state 521, "(1)" + line 426, "pan.___", state 522, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 426, "pan.___", state 522, "else" + line 426, "pan.___", state 525, "(1)" + line 426, "pan.___", state 526, "(1)" + line 426, "pan.___", state 526, "(1)" + line 424, "pan.___", state 531, "((i<2))" + line 424, "pan.___", state 531, "((i>=2))" + line 431, "pan.___", state 535, "(1)" + line 431, "pan.___", state 535, "(1)" + line 577, "pan.___", state 538, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 577, "pan.___", state 539, "_proc_urcu_reader = (_proc_urcu_reader|(1<<5))" + line 577, "pan.___", state 540, "(1)" + line 251, "pan.___", state 544, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 255, "pan.___", state 555, "(1)" + line 259, "pan.___", state 566, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 263, "pan.___", state 575, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 228, "pan.___", state 591, "(1)" + line 232, "pan.___", state 599, "(1)" + line 236, "pan.___", state 611, "(1)" + line 240, "pan.___", state 619, "(1)" + line 396, "pan.___", state 637, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 651, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 669, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 683, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 702, "(1)" + line 417, "pan.___", state 715, "(1)" + line 422, "pan.___", state 732, "(1)" + line 426, "pan.___", state 745, "(1)" + line 396, "pan.___", state 773, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 775, "(1)" + line 396, "pan.___", state 776, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 776, "else" + line 396, "pan.___", state 779, "(1)" + line 400, "pan.___", state 787, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 789, "(1)" + line 400, "pan.___", state 790, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 400, "pan.___", state 790, "else" + line 400, "pan.___", state 793, "(1)" + line 400, "pan.___", state 794, "(1)" + line 400, "pan.___", state 794, "(1)" + line 398, "pan.___", state 799, "((i<1))" + line 398, "pan.___", state 799, "((i>=1))" + line 405, "pan.___", state 805, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 807, "(1)" + line 405, "pan.___", state 808, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 405, "pan.___", state 808, "else" + line 405, "pan.___", state 811, "(1)" + line 405, "pan.___", state 812, "(1)" + line 405, "pan.___", state 812, "(1)" + line 409, "pan.___", state 819, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 821, "(1)" + line 409, "pan.___", state 822, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 409, "pan.___", state 822, "else" + line 409, "pan.___", state 825, "(1)" + line 409, "pan.___", state 826, "(1)" + line 409, "pan.___", state 826, "(1)" + line 407, "pan.___", state 831, "((i<2))" + line 407, "pan.___", state 831, "((i>=2))" + line 413, "pan.___", state 838, "(1)" + line 413, "pan.___", state 839, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 839, "else" + line 413, "pan.___", state 842, "(1)" + line 413, "pan.___", state 843, "(1)" + line 413, "pan.___", state 843, "(1)" + line 417, "pan.___", state 851, "(1)" + line 417, "pan.___", state 852, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 417, "pan.___", state 852, "else" + line 417, "pan.___", state 855, "(1)" + line 417, "pan.___", state 856, "(1)" + line 417, "pan.___", state 856, "(1)" + line 415, "pan.___", state 861, "((i<1))" + line 415, "pan.___", state 861, "((i>=1))" + line 422, "pan.___", state 868, "(1)" + line 422, "pan.___", state 869, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 422, "pan.___", state 869, "else" + line 422, "pan.___", state 872, "(1)" + line 422, "pan.___", state 873, "(1)" + line 422, "pan.___", state 873, "(1)" + line 426, "pan.___", state 881, "(1)" + line 426, "pan.___", state 882, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 426, "pan.___", state 882, "else" + line 426, "pan.___", state 885, "(1)" + line 426, "pan.___", state 886, "(1)" + line 426, "pan.___", state 886, "(1)" + line 431, "pan.___", state 895, "(1)" + line 431, "pan.___", state 895, "(1)" + line 396, "pan.___", state 902, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 904, "(1)" + line 396, "pan.___", state 905, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 905, "else" + line 396, "pan.___", state 908, "(1)" + line 400, "pan.___", state 916, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 918, "(1)" + line 400, "pan.___", state 919, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 400, "pan.___", state 919, "else" + line 400, "pan.___", state 922, "(1)" + line 400, "pan.___", state 923, "(1)" + line 400, "pan.___", state 923, "(1)" + line 398, "pan.___", state 928, "((i<1))" + line 398, "pan.___", state 928, "((i>=1))" + line 405, "pan.___", state 934, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 936, "(1)" + line 405, "pan.___", state 937, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 405, "pan.___", state 937, "else" + line 405, "pan.___", state 940, "(1)" + line 405, "pan.___", state 941, "(1)" + line 405, "pan.___", state 941, "(1)" + line 409, "pan.___", state 948, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 950, "(1)" + line 409, "pan.___", state 951, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 409, "pan.___", state 951, "else" + line 409, "pan.___", state 954, "(1)" + line 409, "pan.___", state 955, "(1)" + line 409, "pan.___", state 955, "(1)" + line 407, "pan.___", state 960, "((i<2))" + line 407, "pan.___", state 960, "((i>=2))" + line 413, "pan.___", state 967, "(1)" + line 413, "pan.___", state 968, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 968, "else" + line 413, "pan.___", state 971, "(1)" + line 413, "pan.___", state 972, "(1)" + line 413, "pan.___", state 972, "(1)" + line 417, "pan.___", state 980, "(1)" + line 417, "pan.___", state 981, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 417, "pan.___", state 981, "else" + line 417, "pan.___", state 984, "(1)" + line 417, "pan.___", state 985, "(1)" + line 417, "pan.___", state 985, "(1)" + line 415, "pan.___", state 990, "((i<1))" + line 415, "pan.___", state 990, "((i>=1))" + line 422, "pan.___", state 997, "(1)" + line 422, "pan.___", state 998, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 422, "pan.___", state 998, "else" + line 422, "pan.___", state 1001, "(1)" + line 422, "pan.___", state 1002, "(1)" + line 422, "pan.___", state 1002, "(1)" + line 426, "pan.___", state 1010, "(1)" + line 426, "pan.___", state 1011, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 426, "pan.___", state 1011, "else" + line 426, "pan.___", state 1014, "(1)" + line 426, "pan.___", state 1015, "(1)" + line 426, "pan.___", state 1015, "(1)" + line 424, "pan.___", state 1020, "((i<2))" + line 424, "pan.___", state 1020, "((i>=2))" + line 431, "pan.___", state 1024, "(1)" + line 431, "pan.___", state 1024, "(1)" + line 585, "pan.___", state 1028, "_proc_urcu_reader = (_proc_urcu_reader|(1<<11))" + line 396, "pan.___", state 1033, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1047, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1065, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 1079, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 1098, "(1)" + line 417, "pan.___", state 1111, "(1)" + line 422, "pan.___", state 1128, "(1)" + line 426, "pan.___", state 1141, "(1)" + line 396, "pan.___", state 1165, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1197, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 1211, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 1230, "(1)" + line 422, "pan.___", state 1260, "(1)" + line 426, "pan.___", state 1273, "(1)" + line 396, "pan.___", state 1298, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1330, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 1344, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 1363, "(1)" + line 422, "pan.___", state 1393, "(1)" + line 426, "pan.___", state 1406, "(1)" + line 396, "pan.___", state 1427, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1459, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 1473, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 1492, "(1)" + line 422, "pan.___", state 1522, "(1)" + line 426, "pan.___", state 1535, "(1)" + line 251, "pan.___", state 1558, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 259, "pan.___", state 1580, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 263, "pan.___", state 1589, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 228, "pan.___", state 1605, "(1)" + line 232, "pan.___", state 1613, "(1)" + line 236, "pan.___", state 1625, "(1)" + line 240, "pan.___", state 1633, "(1)" + line 396, "pan.___", state 1651, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1665, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1683, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 1697, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 1716, "(1)" + line 417, "pan.___", state 1729, "(1)" + line 422, "pan.___", state 1746, "(1)" + line 426, "pan.___", state 1759, "(1)" + line 396, "pan.___", state 1780, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1794, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1812, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 1826, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 1845, "(1)" + line 417, "pan.___", state 1858, "(1)" + line 422, "pan.___", state 1875, "(1)" + line 426, "pan.___", state 1888, "(1)" + line 396, "pan.___", state 1912, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1928, "(1)" + line 405, "pan.___", state 1944, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 1958, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 1977, "(1)" + line 422, "pan.___", state 2007, "(1)" + line 426, "pan.___", state 2020, "(1)" + line 624, "pan.___", state 2041, "_proc_urcu_reader = (_proc_urcu_reader|((1<<2)<<19))" + line 396, "pan.___", state 2048, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 2080, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 2094, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 2113, "(1)" + line 422, "pan.___", state 2143, "(1)" + line 426, "pan.___", state 2156, "(1)" + line 396, "pan.___", state 2177, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 2209, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 2223, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 2242, "(1)" + line 422, "pan.___", state 2272, "(1)" + line 426, "pan.___", state 2285, "(1)" + line 396, "pan.___", state 2308, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 2310, "(1)" + line 396, "pan.___", state 2311, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 2311, "else" + line 396, "pan.___", state 2314, "(1)" + line 400, "pan.___", state 2322, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2324, "(1)" + line 400, "pan.___", state 2325, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 400, "pan.___", state 2325, "else" + line 400, "pan.___", state 2328, "(1)" + line 400, "pan.___", state 2329, "(1)" + line 400, "pan.___", state 2329, "(1)" + line 398, "pan.___", state 2334, "((i<1))" + line 398, "pan.___", state 2334, "((i>=1))" + line 405, "pan.___", state 2340, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 2342, "(1)" + line 405, "pan.___", state 2343, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 405, "pan.___", state 2343, "else" + line 405, "pan.___", state 2346, "(1)" + line 405, "pan.___", state 2347, "(1)" + line 405, "pan.___", state 2347, "(1)" + line 409, "pan.___", state 2354, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 2356, "(1)" + line 409, "pan.___", state 2357, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 409, "pan.___", state 2357, "else" + line 409, "pan.___", state 2360, "(1)" + line 409, "pan.___", state 2361, "(1)" + line 409, "pan.___", state 2361, "(1)" + line 407, "pan.___", state 2366, "((i<2))" + line 407, "pan.___", state 2366, "((i>=2))" + line 413, "pan.___", state 2373, "(1)" + line 413, "pan.___", state 2374, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 2374, "else" + line 413, "pan.___", state 2377, "(1)" + line 413, "pan.___", state 2378, "(1)" + line 413, "pan.___", state 2378, "(1)" + line 417, "pan.___", state 2386, "(1)" + line 417, "pan.___", state 2387, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 417, "pan.___", state 2387, "else" + line 417, "pan.___", state 2390, "(1)" + line 417, "pan.___", state 2391, "(1)" + line 417, "pan.___", state 2391, "(1)" + line 415, "pan.___", state 2396, "((i<1))" + line 415, "pan.___", state 2396, "((i>=1))" + line 422, "pan.___", state 2403, "(1)" + line 422, "pan.___", state 2404, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 422, "pan.___", state 2404, "else" + line 422, "pan.___", state 2407, "(1)" + line 422, "pan.___", state 2408, "(1)" + line 422, "pan.___", state 2408, "(1)" + line 426, "pan.___", state 2416, "(1)" + line 426, "pan.___", state 2417, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 426, "pan.___", state 2417, "else" + line 426, "pan.___", state 2420, "(1)" + line 426, "pan.___", state 2421, "(1)" + line 426, "pan.___", state 2421, "(1)" + line 424, "pan.___", state 2426, "((i<2))" + line 424, "pan.___", state 2426, "((i>=2))" + line 431, "pan.___", state 2430, "(1)" + line 431, "pan.___", state 2430, "(1)" + line 624, "pan.___", state 2433, "cached_urcu_active_readers.val[_pid] = (tmp+1)" + line 624, "pan.___", state 2434, "_proc_urcu_reader = (_proc_urcu_reader|(1<<23))" + line 624, "pan.___", state 2435, "(1)" + line 251, "pan.___", state 2439, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 255, "pan.___", state 2450, "(1)" + line 259, "pan.___", state 2461, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 263, "pan.___", state 2470, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 228, "pan.___", state 2486, "(1)" + line 232, "pan.___", state 2494, "(1)" + line 236, "pan.___", state 2506, "(1)" + line 240, "pan.___", state 2514, "(1)" + line 396, "pan.___", state 2532, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2546, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 2564, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 2578, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 2597, "(1)" + line 417, "pan.___", state 2610, "(1)" + line 422, "pan.___", state 2627, "(1)" + line 426, "pan.___", state 2640, "(1)" + line 251, "pan.___", state 2664, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 255, "pan.___", state 2673, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 259, "pan.___", state 2686, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 263, "pan.___", state 2695, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 228, "pan.___", state 2711, "(1)" + line 232, "pan.___", state 2719, "(1)" + line 236, "pan.___", state 2731, "(1)" + line 240, "pan.___", state 2739, "(1)" + line 396, "pan.___", state 2757, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2771, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 2789, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 2803, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 2822, "(1)" + line 417, "pan.___", state 2835, "(1)" + line 422, "pan.___", state 2852, "(1)" + line 426, "pan.___", state 2865, "(1)" + line 396, "pan.___", state 2886, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 2900, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 2918, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 2932, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 2951, "(1)" + line 417, "pan.___", state 2964, "(1)" + line 422, "pan.___", state 2981, "(1)" + line 426, "pan.___", state 2994, "(1)" + line 228, "pan.___", state 3027, "(1)" + line 236, "pan.___", state 3047, "(1)" + line 240, "pan.___", state 3055, "(1)" + line 228, "pan.___", state 3070, "(1)" + line 232, "pan.___", state 3078, "(1)" + line 236, "pan.___", state 3090, "(1)" + line 240, "pan.___", state 3098, "(1)" + line 878, "pan.___", state 3115, "-end-" + (318 of 3115 states) +unreached in proctype urcu_writer + line 396, "pan.___", state 18, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 24, "(1)" + line 400, "pan.___", state 32, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 38, "(1)" + line 400, "pan.___", state 39, "(1)" + line 400, "pan.___", state 39, "(1)" + line 398, "pan.___", state 44, "((i<1))" + line 398, "pan.___", state 44, "((i>=1))" + line 405, "pan.___", state 50, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 56, "(1)" + line 405, "pan.___", state 57, "(1)" + line 405, "pan.___", state 57, "(1)" + line 409, "pan.___", state 64, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 70, "(1)" + line 409, "pan.___", state 71, "(1)" + line 409, "pan.___", state 71, "(1)" + line 407, "pan.___", state 76, "((i<2))" + line 407, "pan.___", state 76, "((i>=2))" + line 413, "pan.___", state 83, "(1)" + line 413, "pan.___", state 84, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 84, "else" + line 413, "pan.___", state 87, "(1)" + line 413, "pan.___", state 88, "(1)" + line 413, "pan.___", state 88, "(1)" + line 417, "pan.___", state 96, "(1)" + line 417, "pan.___", state 97, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 417, "pan.___", state 97, "else" + line 417, "pan.___", state 100, "(1)" + line 417, "pan.___", state 101, "(1)" + line 417, "pan.___", state 101, "(1)" + line 415, "pan.___", state 106, "((i<1))" + line 415, "pan.___", state 106, "((i>=1))" + line 422, "pan.___", state 113, "(1)" + line 422, "pan.___", state 114, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 422, "pan.___", state 114, "else" + line 422, "pan.___", state 117, "(1)" + line 422, "pan.___", state 118, "(1)" + line 422, "pan.___", state 118, "(1)" + line 426, "pan.___", state 126, "(1)" + line 426, "pan.___", state 127, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 426, "pan.___", state 127, "else" + line 426, "pan.___", state 130, "(1)" + line 426, "pan.___", state 131, "(1)" + line 426, "pan.___", state 131, "(1)" + line 424, "pan.___", state 136, "((i<2))" + line 424, "pan.___", state 136, "((i>=2))" + line 431, "pan.___", state 140, "(1)" + line 431, "pan.___", state 140, "(1)" + line 251, "pan.___", state 149, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 255, "pan.___", state 158, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 166, "((i<1))" + line 253, "pan.___", state 166, "((i>=1))" + line 259, "pan.___", state 171, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 1001, "pan.___", state 199, "old_data = cached_rcu_ptr.val[_pid]" + line 396, "pan.___", state 211, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 217, "(1)" + line 400, "pan.___", state 225, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 231, "(1)" + line 400, "pan.___", state 232, "(1)" + line 400, "pan.___", state 232, "(1)" + line 398, "pan.___", state 237, "((i<1))" + line 398, "pan.___", state 237, "((i>=1))" + line 405, "pan.___", state 243, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 249, "(1)" + line 405, "pan.___", state 250, "(1)" + line 405, "pan.___", state 250, "(1)" + line 409, "pan.___", state 257, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 263, "(1)" + line 409, "pan.___", state 264, "(1)" + line 409, "pan.___", state 264, "(1)" + line 407, "pan.___", state 269, "((i<2))" + line 407, "pan.___", state 269, "((i>=2))" + line 413, "pan.___", state 276, "(1)" + line 413, "pan.___", state 277, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 277, "else" + line 413, "pan.___", state 280, "(1)" + line 413, "pan.___", state 281, "(1)" + line 413, "pan.___", state 281, "(1)" + line 417, "pan.___", state 289, "(1)" + line 417, "pan.___", state 290, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 417, "pan.___", state 290, "else" + line 417, "pan.___", state 293, "(1)" + line 417, "pan.___", state 294, "(1)" + line 417, "pan.___", state 294, "(1)" + line 415, "pan.___", state 299, "((i<1))" + line 415, "pan.___", state 299, "((i>=1))" + line 422, "pan.___", state 306, "(1)" + line 422, "pan.___", state 307, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 422, "pan.___", state 307, "else" + line 422, "pan.___", state 310, "(1)" + line 422, "pan.___", state 311, "(1)" + line 422, "pan.___", state 311, "(1)" + line 426, "pan.___", state 319, "(1)" + line 426, "pan.___", state 320, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 426, "pan.___", state 320, "else" + line 426, "pan.___", state 323, "(1)" + line 426, "pan.___", state 324, "(1)" + line 426, "pan.___", state 324, "(1)" + line 424, "pan.___", state 329, "((i<2))" + line 424, "pan.___", state 329, "((i>=2))" + line 431, "pan.___", state 333, "(1)" + line 431, "pan.___", state 333, "(1)" + line 396, "pan.___", state 344, "(1)" + line 396, "pan.___", state 345, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 345, "else" + line 396, "pan.___", state 348, "(1)" + line 400, "pan.___", state 356, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 362, "(1)" + line 400, "pan.___", state 363, "(1)" + line 400, "pan.___", state 363, "(1)" + line 398, "pan.___", state 368, "((i<1))" + line 398, "pan.___", state 368, "((i>=1))" + line 405, "pan.___", state 374, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 380, "(1)" + line 405, "pan.___", state 381, "(1)" + line 405, "pan.___", state 381, "(1)" + line 409, "pan.___", state 388, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 394, "(1)" + line 409, "pan.___", state 395, "(1)" + line 409, "pan.___", state 395, "(1)" + line 407, "pan.___", state 400, "((i<2))" + line 407, "pan.___", state 400, "((i>=2))" + line 413, "pan.___", state 407, "(1)" + line 413, "pan.___", state 408, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 408, "else" + line 413, "pan.___", state 411, "(1)" + line 413, "pan.___", state 412, "(1)" + line 413, "pan.___", state 412, "(1)" + line 417, "pan.___", state 420, "(1)" + line 417, "pan.___", state 421, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 417, "pan.___", state 421, "else" + line 417, "pan.___", state 424, "(1)" + line 417, "pan.___", state 425, "(1)" + line 417, "pan.___", state 425, "(1)" + line 415, "pan.___", state 430, "((i<1))" + line 415, "pan.___", state 430, "((i>=1))" + line 422, "pan.___", state 437, "(1)" + line 422, "pan.___", state 438, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 422, "pan.___", state 438, "else" + line 422, "pan.___", state 441, "(1)" + line 422, "pan.___", state 442, "(1)" + line 422, "pan.___", state 442, "(1)" + line 426, "pan.___", state 450, "(1)" + line 426, "pan.___", state 451, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 426, "pan.___", state 451, "else" + line 426, "pan.___", state 454, "(1)" + line 426, "pan.___", state 455, "(1)" + line 426, "pan.___", state 455, "(1)" + line 424, "pan.___", state 460, "((i<2))" + line 424, "pan.___", state 460, "((i>=2))" + line 431, "pan.___", state 464, "(1)" + line 431, "pan.___", state 464, "(1)" + line 396, "pan.___", state 477, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 479, "(1)" + line 396, "pan.___", state 480, "((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid)))" + line 396, "pan.___", state 480, "else" + line 396, "pan.___", state 483, "(1)" + line 400, "pan.___", state 491, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 493, "(1)" + line 400, "pan.___", state 494, "((cache_dirty_urcu_active_readers.bitfield&(1<<_pid)))" + line 400, "pan.___", state 494, "else" + line 400, "pan.___", state 497, "(1)" + line 400, "pan.___", state 498, "(1)" + line 400, "pan.___", state 498, "(1)" + line 398, "pan.___", state 503, "((i<1))" + line 398, "pan.___", state 503, "((i>=1))" + line 405, "pan.___", state 509, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 511, "(1)" + line 405, "pan.___", state 512, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 405, "pan.___", state 512, "else" + line 405, "pan.___", state 515, "(1)" + line 405, "pan.___", state 516, "(1)" + line 405, "pan.___", state 516, "(1)" + line 409, "pan.___", state 523, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 525, "(1)" + line 409, "pan.___", state 526, "((cache_dirty_rcu_data[i].bitfield&(1<<_pid)))" + line 409, "pan.___", state 526, "else" + line 409, "pan.___", state 529, "(1)" + line 409, "pan.___", state 530, "(1)" + line 409, "pan.___", state 530, "(1)" + line 407, "pan.___", state 535, "((i<2))" + line 407, "pan.___", state 535, "((i>=2))" + line 413, "pan.___", state 542, "(1)" + line 413, "pan.___", state 543, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 543, "else" + line 413, "pan.___", state 546, "(1)" + line 413, "pan.___", state 547, "(1)" + line 413, "pan.___", state 547, "(1)" + line 417, "pan.___", state 555, "(1)" + line 417, "pan.___", state 556, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 417, "pan.___", state 556, "else" + line 417, "pan.___", state 559, "(1)" + line 417, "pan.___", state 560, "(1)" + line 417, "pan.___", state 560, "(1)" + line 415, "pan.___", state 565, "((i<1))" + line 415, "pan.___", state 565, "((i>=1))" + line 422, "pan.___", state 572, "(1)" + line 422, "pan.___", state 573, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 422, "pan.___", state 573, "else" + line 422, "pan.___", state 576, "(1)" + line 422, "pan.___", state 577, "(1)" + line 422, "pan.___", state 577, "(1)" + line 426, "pan.___", state 585, "(1)" + line 426, "pan.___", state 586, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 426, "pan.___", state 586, "else" + line 426, "pan.___", state 589, "(1)" + line 426, "pan.___", state 590, "(1)" + line 426, "pan.___", state 590, "(1)" + line 431, "pan.___", state 599, "(1)" + line 431, "pan.___", state 599, "(1)" + line 396, "pan.___", state 605, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 611, "(1)" + line 400, "pan.___", state 619, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 625, "(1)" + line 400, "pan.___", state 626, "(1)" + line 400, "pan.___", state 626, "(1)" + line 398, "pan.___", state 631, "((i<1))" + line 398, "pan.___", state 631, "((i>=1))" + line 405, "pan.___", state 637, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 643, "(1)" + line 405, "pan.___", state 644, "(1)" + line 405, "pan.___", state 644, "(1)" + line 409, "pan.___", state 651, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 657, "(1)" + line 409, "pan.___", state 658, "(1)" + line 409, "pan.___", state 658, "(1)" + line 407, "pan.___", state 663, "((i<2))" + line 407, "pan.___", state 663, "((i>=2))" + line 413, "pan.___", state 670, "(1)" + line 413, "pan.___", state 671, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 671, "else" + line 413, "pan.___", state 674, "(1)" + line 413, "pan.___", state 675, "(1)" + line 413, "pan.___", state 675, "(1)" + line 417, "pan.___", state 683, "(1)" + line 417, "pan.___", state 684, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 417, "pan.___", state 684, "else" + line 417, "pan.___", state 687, "(1)" + line 417, "pan.___", state 688, "(1)" + line 417, "pan.___", state 688, "(1)" + line 415, "pan.___", state 693, "((i<1))" + line 415, "pan.___", state 693, "((i>=1))" + line 422, "pan.___", state 700, "(1)" + line 422, "pan.___", state 701, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 422, "pan.___", state 701, "else" + line 422, "pan.___", state 704, "(1)" + line 422, "pan.___", state 705, "(1)" + line 422, "pan.___", state 705, "(1)" + line 426, "pan.___", state 713, "(1)" + line 426, "pan.___", state 714, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 426, "pan.___", state 714, "else" + line 426, "pan.___", state 717, "(1)" + line 426, "pan.___", state 718, "(1)" + line 426, "pan.___", state 718, "(1)" + line 431, "pan.___", state 727, "(1)" + line 431, "pan.___", state 727, "(1)" + line 396, "pan.___", state 734, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 396, "pan.___", state 740, "(1)" + line 400, "pan.___", state 748, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 754, "(1)" + line 400, "pan.___", state 755, "(1)" + line 400, "pan.___", state 755, "(1)" + line 398, "pan.___", state 760, "((i<1))" + line 398, "pan.___", state 760, "((i>=1))" + line 405, "pan.___", state 766, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 772, "(1)" + line 405, "pan.___", state 773, "(1)" + line 405, "pan.___", state 773, "(1)" + line 409, "pan.___", state 780, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 409, "pan.___", state 786, "(1)" + line 409, "pan.___", state 787, "(1)" + line 409, "pan.___", state 787, "(1)" + line 407, "pan.___", state 792, "((i<2))" + line 407, "pan.___", state 792, "((i>=2))" + line 413, "pan.___", state 799, "(1)" + line 413, "pan.___", state 800, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 413, "pan.___", state 800, "else" + line 413, "pan.___", state 803, "(1)" + line 413, "pan.___", state 804, "(1)" + line 413, "pan.___", state 804, "(1)" + line 417, "pan.___", state 812, "(1)" + line 417, "pan.___", state 813, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 417, "pan.___", state 813, "else" + line 417, "pan.___", state 816, "(1)" + line 417, "pan.___", state 817, "(1)" + line 417, "pan.___", state 817, "(1)" + line 415, "pan.___", state 822, "((i<1))" + line 415, "pan.___", state 822, "((i>=1))" + line 422, "pan.___", state 829, "(1)" + line 422, "pan.___", state 830, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 422, "pan.___", state 830, "else" + line 422, "pan.___", state 833, "(1)" + line 422, "pan.___", state 834, "(1)" + line 422, "pan.___", state 834, "(1)" + line 426, "pan.___", state 842, "(1)" + line 426, "pan.___", state 843, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 426, "pan.___", state 843, "else" + line 426, "pan.___", state 846, "(1)" + line 426, "pan.___", state 847, "(1)" + line 426, "pan.___", state 847, "(1)" + line 424, "pan.___", state 852, "((i<2))" + line 424, "pan.___", state 852, "((i>=2))" + line 431, "pan.___", state 856, "(1)" + line 431, "pan.___", state 856, "(1)" + line 400, "pan.___", state 879, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 897, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 911, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 417, "pan.___", state 943, "(1)" + line 422, "pan.___", state 960, "(1)" + line 426, "pan.___", state 973, "(1)" + line 396, "pan.___", state 999, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 400, "pan.___", state 1013, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 405, "pan.___", state 1031, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 409, "pan.___", state 1045, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 413, "pan.___", state 1064, "(1)" + line 417, "pan.___", state 1077, "(1)" + line 422, "pan.___", state 1094, "(1)" + line 426, "pan.___", state 1107, "(1)" + line 251, "pan.___", state 1153, "cache_dirty_urcu_gp_ctr.bitfield = (cache_dirty_urcu_gp_ctr.bitfield&~((1<<_pid)))" + line 255, "pan.___", state 1162, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 253, "pan.___", state 1170, "((i<1))" + line 253, "pan.___", state 1170, "((i>=1))" + line 259, "pan.___", state 1177, "(1)" + line 259, "pan.___", state 1178, "((cache_dirty_rcu_ptr.bitfield&(1<<_pid)))" + line 259, "pan.___", state 1178, "else" + line 263, "pan.___", state 1184, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 261, "pan.___", state 1192, "((i<2))" + line 261, "pan.___", state 1192, "((i>=2))" + line 228, "pan.___", state 1200, "(1)" + line 232, "pan.___", state 1208, "(1)" + line 232, "pan.___", state 1209, "(!((cache_dirty_urcu_active_readers.bitfield&(1<<_pid))))" + line 232, "pan.___", state 1209, "else" + line 230, "pan.___", state 1214, "((i<1))" + line 230, "pan.___", state 1214, "((i>=1))" + line 236, "pan.___", state 1220, "(1)" + line 236, "pan.___", state 1221, "(!((cache_dirty_rcu_ptr.bitfield&(1<<_pid))))" + line 236, "pan.___", state 1221, "else" + line 240, "pan.___", state 1228, "(1)" + line 240, "pan.___", state 1229, "(!((cache_dirty_rcu_data[i].bitfield&(1<<_pid))))" + line 240, "pan.___", state 1229, "else" + line 245, "pan.___", state 1238, "(!((cache_dirty_urcu_gp_ctr.bitfield&(1<<_pid))))" + line 245, "pan.___", state 1238, "else" + line 255, "pan.___", state 1253, "cache_dirty_urcu_active_readers.bitfield = (cache_dirty_urcu_active_readers.bitfield&~((1<<_pid)))" + line 259, "pan.___", state 1266, "cache_dirty_rcu_ptr.bitfield = (cache_dirty_rcu_ptr.bitfield&~((1<<_pid)))" + line 263, "pan.___", state 1275, "cache_dirty_rcu_data[i].bitfield = (cache_dirty_rcu_data[i].bitfield&~((1<<_pid)))" + line 228, "pan.___", state 1291, "(1)" + line 232, "pan.___", state 1299, "(1)" + line 236, "pan.___", state 1311, "(1)" + line 240, "pan.___", state 1319, "(1)" + line 1205, "pan.___", state 1334, "-end-" + (242 of 1334 states) +unreached in proctype :init: + (0 of 78 states) +unreached in proctype :never: + line 1266, "pan.___", state 11, "-end-" + (1 of 11 states) + +pan: elapsed time 24.3 seconds +pan: rate 3201.8077 states/second +pan: avg transition delay 1.3309e-06 usec +cp .input.spin urcu_progress_writer_error.spin.input +cp .input.spin.trail urcu_progress_writer_error.spin.input.trail diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer_error.spin.input b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer_error.spin.input new file mode 100644 index 0000000..ea022e9 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer_error.spin.input @@ -0,0 +1,1241 @@ +#define WRITER_PROGRESS +#define GEN_ERROR_WRITER_PROGRESS + +// Poison value for freed memory +#define POISON 1 +// Memory with correct data +#define WINE 0 +#define SLAB_SIZE 2 + +#define read_poison (data_read_first[0] == POISON || data_read_second[0] == POISON) + +#define RCU_GP_CTR_BIT (1 << 7) +#define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1) + +//disabled +//#define REMOTE_BARRIERS +/* + * mem.spin: Promela code to validate memory barriers with OOO memory + * and out-of-order instruction scheduling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (c) 2009 Mathieu Desnoyers + */ + +/* Promela validation variables. */ + +/* specific defines "included" here */ +/* DEFINES file "included" here */ + +#define NR_READERS 1 +#define NR_WRITERS 1 + +#define NR_PROCS 2 + +#define get_pid() (_pid) + +#define get_readerid() (get_pid()) + +/* + * Produced process control and data flow. Updated after each instruction to + * show which variables are ready. Using one-hot bit encoding per variable to + * save state space. Used as triggers to execute the instructions having those + * variables as input. Leaving bits active to inhibit instruction execution. + * Scheme used to make instruction disabling and automatic dependency fall-back + * automatic. + */ + +#define CONSUME_TOKENS(state, bits, notbits) \ + ((!(state & (notbits))) && (state & (bits)) == (bits)) + +#define PRODUCE_TOKENS(state, bits) \ + state = state | (bits); + +#define CLEAR_TOKENS(state, bits) \ + state = state & ~(bits) + +/* + * Types of dependency : + * + * Data dependency + * + * - True dependency, Read-after-Write (RAW) + * + * This type of dependency happens when a statement depends on the result of a + * previous statement. This applies to any statement which needs to read a + * variable written by a preceding statement. + * + * - False dependency, Write-after-Read (WAR) + * + * Typically, variable renaming can ensure that this dependency goes away. + * However, if the statements must read and then write from/to the same variable + * in the OOO memory model, renaming may be impossible, and therefore this + * causes a WAR dependency. + * + * - Output dependency, Write-after-Write (WAW) + * + * Two writes to the same variable in subsequent statements. Variable renaming + * can ensure this is not needed, but can be required when writing multiple + * times to the same OOO mem model variable. + * + * Control dependency + * + * Execution of a given instruction depends on a previous instruction evaluating + * in a way that allows its execution. E.g. : branches. + * + * Useful considerations for joining dependencies after branch + * + * - Pre-dominance + * + * "We say box i dominates box j if every path (leading from input to output + * through the diagram) which passes through box j must also pass through box + * i. Thus box i dominates box j if box j is subordinate to box i in the + * program." + * + * http://www.hipersoft.rice.edu/grads/publications/dom14.pdf + * Other classic algorithm to calculate dominance : Lengauer-Tarjan (in gcc) + * + * - Post-dominance + * + * Just as pre-dominance, but with arcs of the data flow inverted, and input vs + * output exchanged. Therefore, i post-dominating j ensures that every path + * passing by j will pass by i before reaching the output. + * + * Other considerations + * + * Note about "volatile" keyword dependency : The compiler will order volatile + * accesses so they appear in the right order on a given CPU. They can be + * reordered by the CPU instruction scheduling. This therefore cannot be + * considered as a depencency. + * + * References : + * + * Cooper, Keith D.; & Torczon, Linda. (2005). Engineering a Compiler. Morgan + * Kaufmann. ISBN 1-55860-698-X. + * Kennedy, Ken; & Allen, Randy. (2001). Optimizing Compilers for Modern + * Architectures: A Dependence-based Approach. Morgan Kaufmann. ISBN + * 1-55860-286-0. + * Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. + * Morgan Kaufmann. ISBN 1-55860-320-4. + */ + +/* + * Note about loops and nested calls + * + * To keep this model simple, loops expressed in the framework will behave as if + * there was a core synchronizing instruction between loops. To see the effect + * of loop unrolling, manually unrolling loops is required. Note that if loops + * end or start with a core synchronizing instruction, the model is appropriate. + * Nested calls are not supported. + */ + +/* + * Each process have its own data in cache. Caches are randomly updated. + * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces + * both. + */ + +typedef per_proc_byte { + byte val[NR_PROCS]; +}; + +typedef per_proc_bit { + bit val[NR_PROCS]; +}; + +/* Bitfield has a maximum of 8 procs */ +typedef per_proc_bitfield { + byte bitfield; +}; + +#define DECLARE_CACHED_VAR(type, x) \ + type mem_##x; \ + per_proc_##type cached_##x; \ + per_proc_bitfield cache_dirty_##x; + +#define INIT_CACHED_VAR(x, v, j) \ + mem_##x = v; \ + cache_dirty_##x.bitfield = 0; \ + j = 0; \ + do \ + :: j < NR_PROCS -> \ + cached_##x.val[j] = v; \ + j++ \ + :: j >= NR_PROCS -> break \ + od; + +#define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id)) + +#define READ_CACHED_VAR(x) (cached_##x.val[get_pid()]) + +#define WRITE_CACHED_VAR(x, v) \ + atomic { \ + cached_##x.val[get_pid()] = v; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield | (1 << get_pid()); \ + } + +#define CACHE_WRITE_TO_MEM(x, id) \ + if \ + :: IS_CACHE_DIRTY(x, id) -> \ + mem_##x = cached_##x.val[id]; \ + cache_dirty_##x.bitfield = \ + cache_dirty_##x.bitfield & (~(1 << id)); \ + :: else -> \ + skip \ + fi; + +#define CACHE_READ_FROM_MEM(x, id) \ + if \ + :: !IS_CACHE_DIRTY(x, id) -> \ + cached_##x.val[id] = mem_##x;\ + :: else -> \ + skip \ + fi; + +/* + * May update other caches if cache is dirty, or not. + */ +#define RANDOM_CACHE_WRITE_TO_MEM(x, id)\ + if \ + :: 1 -> CACHE_WRITE_TO_MEM(x, id); \ + :: 1 -> skip \ + fi; + +#define RANDOM_CACHE_READ_FROM_MEM(x, id)\ + if \ + :: 1 -> CACHE_READ_FROM_MEM(x, id); \ + :: 1 -> skip \ + fi; + +/* Must consume all prior read tokens. All subsequent reads depend on it. */ +inline smp_rmb(i, j) +{ + atomic { + CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Must consume all prior write tokens. All subsequent writes depend on it. */ +inline smp_wmb(i, j) +{ + atomic { + CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid()); + i++ + :: i >= NR_READERS -> break + od; + CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* Synchronization point. Must consume all prior read and write tokens. All + * subsequent reads and writes depend on it. */ +inline smp_mb(i, j) +{ + atomic { + smp_wmb(i, j); + smp_rmb(i, j); + } +} + +#ifdef REMOTE_BARRIERS + +bit reader_barrier[NR_READERS]; + +/* + * We cannot leave the barriers dependencies in place in REMOTE_BARRIERS mode + * because they would add unexisting core synchronization and would therefore + * create an incomplete model. + * Therefore, we model the read-side memory barriers by completely disabling the + * memory barriers and their dependencies from the read-side. One at a time + * (different verification runs), we make a different instruction listen for + * signals. + */ + +#define smp_mb_reader(i, j) + +/* + * Service 0, 1 or many barrier requests. + */ +inline smp_mb_recv(i, j) +{ + do + :: (reader_barrier[get_readerid()] == 1) -> + /* + * We choose to ignore cycles caused by writer busy-looping, + * waiting for the reader, sending barrier requests, and the + * reader always services them without continuing execution. + */ +progress_ignoring_mb1: + smp_mb(i, j); + reader_barrier[get_readerid()] = 0; + :: 1 -> + /* + * We choose to ignore writer's non-progress caused by the + * reader ignoring the writer's mb() requests. + */ +progress_ignoring_mb2: + break; + od; +} + +//#ifdef WRITER_PROGRESS +//#define PROGRESS_LABEL(progressid) +//#else +//#define PROGRESS_LABEL(progressid) +//#endif + +#define PROGRESS_LABEL(progressid) progress_writer_progid_##progressid: + +#define smp_mb_send(i, j, progressid) \ +{ \ + smp_mb(i, j); \ + i = 0; \ + do \ + :: i < NR_READERS -> \ + 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. \ + */ \ + do \ + :: (reader_barrier[i] == 1) -> \ +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(i, j, progressid) smp_mb(i, j) +#define smp_mb_reader smp_mb +#define smp_mb_recv(i, j) + +#endif + +/* Keep in sync manually with smp_rmb, smp_wmb, ooo_mem and init() */ +DECLARE_CACHED_VAR(byte, urcu_gp_ctr); +/* Note ! currently only one reader */ +DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]); +/* RCU data */ +DECLARE_CACHED_VAR(bit, rcu_data[SLAB_SIZE]); + +/* RCU pointer */ +#if (SLAB_SIZE == 2) +DECLARE_CACHED_VAR(bit, rcu_ptr); +bit ptr_read_first[NR_READERS]; +bit ptr_read_second[NR_READERS]; +#else +DECLARE_CACHED_VAR(byte, rcu_ptr); +byte ptr_read_first[NR_READERS]; +byte ptr_read_second[NR_READERS]; +#endif + +bit data_read_first[NR_READERS]; +bit data_read_second[NR_READERS]; + +bit init_done = 0; + +inline wait_init_done() +{ + do + :: init_done == 0 -> skip; + :: else -> break; + od; +} + +inline ooo_mem(i) +{ + atomic { + RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_WRITE_TO_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_WRITE_TO_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid()); + i = 0; + do + :: i < NR_READERS -> + RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i], + get_pid()); + i++ + :: i >= NR_READERS -> break + od; + RANDOM_CACHE_READ_FROM_MEM(rcu_ptr, get_pid()); + i = 0; + do + :: i < SLAB_SIZE -> + RANDOM_CACHE_READ_FROM_MEM(rcu_data[i], get_pid()); + i++ + :: i >= SLAB_SIZE -> break + od; + } +} + +/* + * Bit encoding, urcu_reader : + */ + +int _proc_urcu_reader; +#define proc_urcu_reader _proc_urcu_reader + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROD_A_READ (1 << 0) +#define READ_PROD_B_IF_TRUE (1 << 1) +#define READ_PROD_B_IF_FALSE (1 << 2) +#define READ_PROD_C_IF_TRUE_READ (1 << 3) + +#define PROCEDURE_READ_LOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, consumetoken, READ_PROD_A_READ << base) -> \ + ooo_mem(i); \ + tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_A_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + READ_PROD_A_READ << base, /* RAW, pre-dominant */ \ + (READ_PROD_B_IF_TRUE | READ_PROD_B_IF_FALSE) << base) -> \ + if \ + :: (!(tmp & RCU_GP_CTR_NEST_MASK)) -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base); \ + :: else -> \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_B_IF_FALSE << base); \ + fi; \ + /* IF TRUE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_B_IF_TRUE << base, \ + READ_PROD_C_IF_TRUE_READ << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_gp_ctr); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_C_IF_TRUE_READ << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_C_IF_TRUE_READ /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ELSE */ \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + (READ_PROD_B_IF_FALSE /* pre-dominant */ \ + | READ_PROD_A_READ) << base, /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], \ + tmp + 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + /* IF_MERGE implies \ + * post-dominance */ \ + /* ENDIF */ \ + skip + +/* Body of PROCEDURE_READ_LOCK */ +#define READ_PROC_READ_UNLOCK (1 << 0) + +#define PROCEDURE_READ_UNLOCK(base, consumetoken, producetoken) \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken, \ + READ_PROC_READ_UNLOCK << base) -> \ + ooo_mem(i); \ + tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); \ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_UNLOCK << base); \ + :: CONSUME_TOKENS(proc_urcu_reader, \ + consumetoken \ + | (READ_PROC_READ_UNLOCK << base), /* WAR */ \ + producetoken) -> \ + ooo_mem(i); \ + WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1); \ + PRODUCE_TOKENS(proc_urcu_reader, producetoken); \ + skip + + +#define READ_PROD_NONE (1 << 0) + +/* PROCEDURE_READ_LOCK base = << 1 : 1 to 5 */ +#define READ_LOCK_BASE 1 +#define READ_LOCK_OUT (1 << 5) + +#define READ_PROC_FIRST_MB (1 << 6) + +/* PROCEDURE_READ_LOCK (NESTED) base : << 7 : 7 to 11 */ +#define READ_LOCK_NESTED_BASE 7 +#define READ_LOCK_NESTED_OUT (1 << 11) + +#define READ_PROC_READ_GEN (1 << 12) +#define READ_PROC_ACCESS_GEN (1 << 13) + +/* PROCEDURE_READ_UNLOCK (NESTED) base = << 14 : 14 to 15 */ +#define READ_UNLOCK_NESTED_BASE 14 +#define READ_UNLOCK_NESTED_OUT (1 << 15) + +#define READ_PROC_SECOND_MB (1 << 16) + +/* PROCEDURE_READ_UNLOCK base = << 17 : 17 to 18 */ +#define READ_UNLOCK_BASE 17 +#define READ_UNLOCK_OUT (1 << 18) + +/* PROCEDURE_READ_LOCK_UNROLL base = << 19 : 19 to 23 */ +#define READ_LOCK_UNROLL_BASE 19 +#define READ_LOCK_OUT_UNROLL (1 << 23) + +#define READ_PROC_THIRD_MB (1 << 24) + +#define READ_PROC_READ_GEN_UNROLL (1 << 25) +#define READ_PROC_ACCESS_GEN_UNROLL (1 << 26) + +#define READ_PROC_FOURTH_MB (1 << 27) + +/* PROCEDURE_READ_UNLOCK_UNROLL base = << 28 : 28 to 29 */ +#define READ_UNLOCK_UNROLL_BASE 28 +#define READ_UNLOCK_OUT_UNROLL (1 << 29) + + +/* Should not include branches */ +#define READ_PROC_ALL_TOKENS (READ_PROD_NONE \ + | READ_LOCK_OUT \ + | READ_PROC_FIRST_MB \ + | READ_LOCK_NESTED_OUT \ + | READ_PROC_READ_GEN \ + | READ_PROC_ACCESS_GEN \ + | READ_UNLOCK_NESTED_OUT \ + | READ_PROC_SECOND_MB \ + | READ_UNLOCK_OUT \ + | READ_LOCK_OUT_UNROLL \ + | READ_PROC_THIRD_MB \ + | READ_PROC_READ_GEN_UNROLL \ + | READ_PROC_ACCESS_GEN_UNROLL \ + | READ_PROC_FOURTH_MB \ + | READ_UNLOCK_OUT_UNROLL) + +/* Must clear all tokens, including branches */ +#define READ_PROC_ALL_TOKENS_CLEAR ((1 << 30) - 1) + +inline urcu_one_read(i, j, nest_i, tmp, tmp2) +{ + PRODUCE_TOKENS(proc_urcu_reader, READ_PROD_NONE); + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + +#ifdef REMOTE_BARRIERS + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); +#endif + + do + :: 1 -> + +#ifdef REMOTE_BARRIERS + /* + * Signal-based memory barrier will only execute when the + * execution order appears in program order. + */ + if + :: 1 -> + atomic { + if + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE, + READ_LOCK_OUT | READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT + | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT | READ_LOCK_NESTED_OUT, + READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN, + READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT, + READ_UNLOCK_OUT + | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL, + READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL, + READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN + | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL, + READ_UNLOCK_OUT_UNROLL) + || CONSUME_TOKENS(proc_urcu_reader, READ_PROD_NONE | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT | READ_PROC_READ_GEN | READ_PROC_ACCESS_GEN | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT | READ_LOCK_OUT_UNROLL + | READ_PROC_READ_GEN_UNROLL | READ_PROC_ACCESS_GEN_UNROLL | READ_UNLOCK_OUT_UNROLL, + 0) -> + goto non_atomic3; +non_atomic3_end: + skip; + fi; + } + fi; + + goto non_atomic3_skip; +non_atomic3: + smp_mb_recv(i, j); + goto non_atomic3_end; +non_atomic3_skip: + +#endif /* REMOTE_BARRIERS */ + + atomic { + if + PROCEDURE_READ_LOCK(READ_LOCK_BASE, READ_PROD_NONE, READ_LOCK_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_LOCK_OUT, /* post-dominant */ + READ_PROC_FIRST_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FIRST_MB); + + PROCEDURE_READ_LOCK(READ_LOCK_NESTED_BASE, READ_PROC_FIRST_MB | READ_LOCK_OUT, + READ_LOCK_NESTED_OUT); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB, /* mb() orders reads */ + READ_PROC_READ_GEN) -> + ooo_mem(i); + ptr_read_first[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_READ_GEN, + READ_PROC_ACCESS_GEN) -> + /* smp_read_barrier_depends */ + goto rmb1; +rmb1_end: + data_read_first[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_first[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN); + + + /* Note : we remove the nested memory barrier from the read unlock + * model, given it is not usually needed. The implementation has the barrier + * because the performance impact added by a branch in the common case does not + * justify it. + */ + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_NESTED_BASE, + READ_PROC_FIRST_MB + | READ_LOCK_OUT + | READ_LOCK_NESTED_OUT, + READ_UNLOCK_NESTED_OUT); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_ACCESS_GEN /* mb() orders reads */ + | READ_PROC_READ_GEN /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_LOCK_OUT /* post-dominant */ + | READ_LOCK_NESTED_OUT /* post-dominant */ + | READ_UNLOCK_NESTED_OUT, + READ_PROC_SECOND_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_SECOND_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_BASE, + READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT); + + /* Unrolling loop : second consecutive lock */ + /* reading urcu_active_readers, which have been written by + * READ_UNLOCK_OUT : RAW */ + PROCEDURE_READ_LOCK(READ_LOCK_UNROLL_BASE, + READ_UNLOCK_OUT /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_LOCK_OUT_UNROLL); + + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_THIRD_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_THIRD_MB); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_READ_GEN_UNROLL) -> + ooo_mem(i); + ptr_read_second[get_readerid()] = READ_CACHED_VAR(rcu_ptr); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_READ_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB, /* mb() orders reads */ + READ_PROC_ACCESS_GEN_UNROLL) -> + /* smp_read_barrier_depends */ + goto rmb2; +rmb2_end: + data_read_second[get_readerid()] = + READ_CACHED_VAR(rcu_data[ptr_read_second[get_readerid()]]); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_ACCESS_GEN_UNROLL); + + :: CONSUME_TOKENS(proc_urcu_reader, + READ_PROC_READ_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_ACCESS_GEN_UNROLL /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() ordered */ + | READ_PROC_SECOND_MB /* mb() ordered */ + | READ_PROC_THIRD_MB /* mb() ordered */ + | READ_LOCK_OUT_UNROLL /* post-dominant */ + | READ_LOCK_NESTED_OUT + | READ_LOCK_OUT + | READ_UNLOCK_NESTED_OUT + | READ_UNLOCK_OUT, + READ_PROC_FOURTH_MB) -> + smp_mb_reader(i, j); + PRODUCE_TOKENS(proc_urcu_reader, READ_PROC_FOURTH_MB); + + PROCEDURE_READ_UNLOCK(READ_UNLOCK_UNROLL_BASE, + READ_PROC_FOURTH_MB /* mb() orders reads */ + | READ_PROC_THIRD_MB /* mb() orders reads */ + | READ_LOCK_OUT_UNROLL /* RAW */ + | READ_PROC_SECOND_MB /* mb() orders reads */ + | READ_PROC_FIRST_MB /* mb() orders reads */ + | READ_LOCK_NESTED_OUT /* RAW */ + | READ_LOCK_OUT /* RAW */ + | READ_UNLOCK_NESTED_OUT, /* RAW */ + READ_UNLOCK_OUT_UNROLL); + :: CONSUME_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_reader, READ_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Dependency between consecutive loops : + * RAW dependency on + * WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1) + * tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]); + * between loops. + * _WHEN THE MB()s are in place_, they add full ordering of the + * generation pointer read wrt active reader count read, which ensures + * execution will not spill across loop execution. + * However, in the event mb()s are removed (execution using signal + * handler to promote barrier()() -> smp_mb()), nothing prevents one loop + * to spill its execution on other loop's execution. + */ + goto end; +rmb1: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb1_end; +rmb2: +#ifndef NO_RMB + smp_rmb(i, j); +#else + ooo_mem(i); +#endif + goto rmb2_end; +end: + skip; +} + + + +active proctype urcu_reader() +{ + byte i, j, nest_i; + byte tmp, tmp2; + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + +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 + urcu_one_read(i, j, nest_i, tmp, tmp2); + od; +} + +/* no name clash please */ +#undef proc_urcu_reader + + +/* Model the RCU update process. */ + +/* + * Bit encoding, urcu_writer : + * Currently only supports one reader. + */ + +int _proc_urcu_writer; +#define proc_urcu_writer _proc_urcu_writer + +#define WRITE_PROD_NONE (1 << 0) + +#define WRITE_DATA (1 << 1) +#define WRITE_PROC_WMB (1 << 2) +#define WRITE_XCHG_PTR (1 << 3) + +#define WRITE_PROC_FIRST_MB (1 << 4) + +/* first flip */ +#define WRITE_PROC_FIRST_READ_GP (1 << 5) +#define WRITE_PROC_FIRST_WRITE_GP (1 << 6) +#define WRITE_PROC_FIRST_WAIT (1 << 7) +#define WRITE_PROC_FIRST_WAIT_LOOP (1 << 8) + +/* second flip */ +#define WRITE_PROC_SECOND_READ_GP (1 << 9) +#define WRITE_PROC_SECOND_WRITE_GP (1 << 10) +#define WRITE_PROC_SECOND_WAIT (1 << 11) +#define WRITE_PROC_SECOND_WAIT_LOOP (1 << 12) + +#define WRITE_PROC_SECOND_MB (1 << 13) + +#define WRITE_FREE (1 << 14) + +#define WRITE_PROC_ALL_TOKENS (WRITE_PROD_NONE \ + | WRITE_DATA \ + | WRITE_PROC_WMB \ + | WRITE_XCHG_PTR \ + | WRITE_PROC_FIRST_MB \ + | WRITE_PROC_FIRST_READ_GP \ + | WRITE_PROC_FIRST_WRITE_GP \ + | WRITE_PROC_FIRST_WAIT \ + | WRITE_PROC_SECOND_READ_GP \ + | WRITE_PROC_SECOND_WRITE_GP \ + | WRITE_PROC_SECOND_WAIT \ + | WRITE_PROC_SECOND_MB \ + | WRITE_FREE) + +#define WRITE_PROC_ALL_TOKENS_CLEAR ((1 << 15) - 1) + +/* + * Mutexes are implied around writer execution. A single writer at a time. + */ +active proctype urcu_writer() +{ + byte i, j; + byte tmp, tmp2, tmpa; + byte cur_data = 0, old_data, loop_nr = 0; + byte cur_gp_val = 0; /* + * Keep a local trace of the current parity so + * we don't add non-existing dependencies on the global + * GP update. Needed to test single flip case. + */ + + wait_init_done(); + + assert(get_pid() < NR_PROCS); + + do + :: (loop_nr < 3) -> +#ifdef WRITER_PROGRESS +progress_writer1: +#endif + loop_nr = loop_nr + 1; + + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROD_NONE); + +#ifdef NO_WMB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); +#endif + +#ifdef NO_MB + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); +#endif + +#ifdef SINGLE_FLIP + 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 -> + atomic { + if + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROD_NONE, + WRITE_DATA) -> + ooo_mem(i); + cur_data = (cur_data + 1) % SLAB_SIZE; + WRITE_CACHED_VAR(rcu_data[cur_data], WINE); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_DATA); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA, + WRITE_PROC_WMB) -> + smp_wmb(i, j); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_WMB, + WRITE_XCHG_PTR) -> + /* rcu_xchg_pointer() */ + atomic { + old_data = READ_CACHED_VAR(rcu_ptr); + WRITE_CACHED_VAR(rcu_ptr, cur_data); + } + PRODUCE_TOKENS(proc_urcu_writer, WRITE_XCHG_PTR); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR, + WRITE_PROC_FIRST_MB) -> + goto smp_mb_send1; +smp_mb_send1_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_MB); + + /* first flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB, + WRITE_PROC_FIRST_READ_GP) -> + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP, + WRITE_PROC_FIRST_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_FIRST_WAIT | WRITE_PROC_FIRST_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); +#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) -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP); + :: else -> + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send2; +smp_mb_send2_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_FIRST_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_FIRST_WAIT_LOOP | WRITE_PROC_FIRST_WAIT); + + /* second flip */ + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT /* Control dependency : need to branch out of + * the loop to execute the next flip (CHECK) */ + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_READ_GP) -> + ooo_mem(i); + tmpa = READ_CACHED_VAR(urcu_gp_ctr); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_READ_GP); + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_MB + | WRITE_PROC_WMB + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP, + WRITE_PROC_SECOND_WRITE_GP) -> + ooo_mem(i); + WRITE_CACHED_VAR(urcu_gp_ctr, tmpa ^ RCU_GP_CTR_BIT); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WRITE_GP); + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + WRITE_PROC_SECOND_WAIT | WRITE_PROC_SECOND_WAIT_LOOP) -> + ooo_mem(i); + /* ONLY WAITING FOR READER 0 */ + tmp2 = READ_CACHED_VAR(urcu_active_readers[0]); + if + :: (tmp2 & RCU_GP_CTR_NEST_MASK) + && ((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); + fi; + + :: CONSUME_TOKENS(proc_urcu_writer, + //WRITE_PROC_FIRST_WRITE_GP /* TEST ADDING SYNC CORE */ + WRITE_PROC_SECOND_WRITE_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_WAIT_LOOP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, /* can be reordered before/after flips */ + 0) -> +#ifndef GEN_ERROR_WRITER_PROGRESS + goto smp_mb_send3; +smp_mb_send3_end: +#else + ooo_mem(i); +#endif + /* This instruction loops to WRITE_PROC_SECOND_WAIT */ + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_WAIT_LOOP | WRITE_PROC_SECOND_WAIT); + + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_FIRST_READ_GP + | WRITE_PROC_SECOND_READ_GP + | WRITE_PROC_FIRST_WRITE_GP + | WRITE_PROC_SECOND_WRITE_GP + | WRITE_DATA | WRITE_PROC_WMB | WRITE_XCHG_PTR + | WRITE_PROC_FIRST_MB, + WRITE_PROC_SECOND_MB) -> + goto smp_mb_send4; +smp_mb_send4_end: + PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_SECOND_MB); + + :: CONSUME_TOKENS(proc_urcu_writer, + WRITE_XCHG_PTR + | WRITE_PROC_FIRST_WAIT + | WRITE_PROC_SECOND_WAIT + | WRITE_PROC_WMB /* No dependency on + * WRITE_DATA because we + * write to a + * different location. */ + | WRITE_PROC_SECOND_MB + | WRITE_PROC_FIRST_MB, + WRITE_FREE) -> + WRITE_CACHED_VAR(rcu_data[old_data], POISON); + PRODUCE_TOKENS(proc_urcu_writer, WRITE_FREE); + + :: CONSUME_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS, 0) -> + CLEAR_TOKENS(proc_urcu_writer, WRITE_PROC_ALL_TOKENS_CLEAR); + break; + fi; + } + od; + /* + * Note : Promela model adds implicit serialization of the + * WRITE_FREE instruction. Normally, it would be permitted to + * spill on the next loop execution. Given the validation we do + * checks for the data entry read to be poisoned, it's ok if + * we do not check "late arriving" memory poisoning. + */ + :: else -> break; + od; + /* + * 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 +#ifdef READER_PROGRESS + /* + * Make sure we don't block the reader's progress. + */ + smp_mb_send(i, j, 5); +#endif + skip; + od; + + /* Non-atomic parts of the loop */ + goto end; +smp_mb_send1: + smp_mb_send(i, j, 1); + goto smp_mb_send1_end; +#ifndef GEN_ERROR_WRITER_PROGRESS +smp_mb_send2: + smp_mb_send(i, j, 2); + goto smp_mb_send2_end; +smp_mb_send3: + smp_mb_send(i, j, 3); + goto smp_mb_send3_end; +#endif +smp_mb_send4: + smp_mb_send(i, j, 4); + goto smp_mb_send4_end; +end: + skip; +} + +/* no name clash please */ +#undef proc_urcu_writer + + +/* Leave after the readers and writers so the pid count is ok. */ +init { + byte i, j; + + atomic { + INIT_CACHED_VAR(urcu_gp_ctr, 1, j); + INIT_CACHED_VAR(rcu_ptr, 0, j); + + i = 0; + do + :: i < NR_READERS -> + INIT_CACHED_VAR(urcu_active_readers[i], 0, j); + ptr_read_first[i] = 1; + ptr_read_second[i] = 1; + data_read_first[i] = WINE; + data_read_second[i] = WINE; + i++; + :: i >= NR_READERS -> break + od; + INIT_CACHED_VAR(rcu_data[0], WINE, j); + i = 1; + do + :: i < SLAB_SIZE -> + INIT_CACHED_VAR(rcu_data[i], POISON, j); + i++ + :: i >= SLAB_SIZE -> break + od; + + init_done = 1; + } +} diff --git a/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer_error.spin.input.trail b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer_error.spin.input.trail new file mode 100644 index 0000000..29e0696 --- /dev/null +++ b/formal-model/results/urcu-controldataflow-no-ipi/urcu_progress_writer_error.spin.input.trail @@ -0,0 +1,8711 @@ +-2:3:-2 +-4:-4:-4 +1:0:4529 +2:3:4449 +3:3:4452 +4:3:4452 +5:3:4455 +6:3:4463 +7:3:4463 +8:3:4466 +9:3:4472 +10:3:4476 +11:3:4476 +12:3:4479 +13:3:4489 +14:3:4497 +15:3:4497 +16:3:4500 +17:3:4506 +18:3:4510 +19:3:4510 +20:3:4513 +21:3:4519 +22:3:4523 +23:3:4524 +24:0:4529 +25:3:4526 +26:0:4529 +27:2:3117 +28:0:4529 +29:2:3123 +30:0:4529 +31:2:3124 +32:0:4529 +33:2:3125 +34:0:4527 +35:2:3126 +36:0:4533 +37:2:3127 +38:0:4533 +39:2:3128 +40:2:3129 +41:2:3133 +42:2:3134 +43:2:3142 +44:2:3143 +45:2:3147 +46:2:3148 +47:2:3156 +48:2:3161 +49:2:3165 +50:2:3166 +51:2:3174 +52:2:3175 +53:2:3179 +54:2:3180 +55:2:3174 +56:2:3175 +57:2:3179 +58:2:3180 +59:2:3188 +60:2:3193 +61:2:3194 +62:2:3205 +63:2:3206 +64:2:3207 +65:2:3218 +66:2:3223 +67:2:3224 +68:2:3235 +69:2:3236 +70:2:3237 +71:2:3235 +72:2:3236 +73:2:3237 +74:2:3248 +75:2:3256 +76:0:4533 +77:2:3127 +78:0:4533 +79:2:3260 +80:2:3264 +81:2:3265 +82:2:3269 +83:2:3273 +84:2:3274 +85:2:3278 +86:2:3286 +87:2:3287 +88:2:3291 +89:2:3295 +90:2:3296 +91:2:3291 +92:2:3292 +93:2:3300 +94:0:4533 +95:2:3127 +96:0:4533 +97:2:3308 +98:2:3309 +99:2:3310 +100:0:4533 +101:2:3127 +102:0:4533 +103:2:3315 +104:0:4533 +105:2:4268 +106:2:4269 +107:2:4273 +108:2:4277 +109:2:4278 +110:2:4282 +111:2:4287 +112:2:4295 +113:2:4299 +114:2:4300 +115:2:4295 +116:2:4299 +117:2:4300 +118:2:4304 +119:2:4311 +120:2:4318 +121:2:4319 +122:2:4326 +123:2:4331 +124:2:4338 +125:2:4339 +126:2:4338 +127:2:4339 +128:2:4346 +129:2:4350 +130:0:4533 +131:2:3317 +132:2:4249 +133:0:4533 +134:2:3127 +135:0:4533 +136:2:3318 +137:0:4533 +138:2:3127 +139:0:4533 +140:2:3321 +141:2:3322 +142:2:3326 +143:2:3327 +144:2:3335 +145:2:3336 +146:2:3340 +147:2:3341 +148:2:3349 +149:2:3354 +150:2:3358 +151:2:3359 +152:2:3367 +153:2:3368 +154:2:3372 +155:2:3373 +156:2:3367 +157:2:3368 +158:2:3372 +159:2:3373 +160:2:3381 +161:2:3386 +162:2:3387 +163:2:3398 +164:2:3399 +165:2:3400 +166:2:3411 +167:2:3416 +168:2:3417 +169:2:3428 +170:2:3429 +171:2:3430 +172:2:3428 +173:2:3429 +174:2:3430 +175:2:3441 +176:2:3448 +177:0:4533 +178:2:3127 +179:0:4533 +180:2:3452 +181:2:3453 +182:2:3454 +183:2:3466 +184:2:3467 +185:2:3471 +186:2:3472 +187:2:3480 +188:2:3485 +189:2:3489 +190:2:3490 +191:2:3498 +192:2:3499 +193:2:3503 +194:2:3504 +195:2:3498 +196:2:3499 +197:2:3503 +198:2:3504 +199:2:3512 +200:2:3517 +201:2:3518 +202:2:3529 +203:2:3530 +204:2:3531 +205:2:3542 +206:2:3547 +207:2:3548 +208:2:3559 +209:2:3560 +210:2:3561 +211:2:3559 +212:2:3560 +213:2:3561 +214:2:3572 +215:2:3583 +216:2:3584 +217:0:4533 +218:2:3127 +219:0:4533 +220:2:3715 +221:2:3716 +222:2:3720 +223:2:3721 +224:2:3729 +225:2:3730 +226:2:3734 +227:2:3735 +228:2:3743 +229:2:3748 +230:2:3752 +231:2:3753 +232:2:3761 +233:2:3762 +234:2:3766 +235:2:3767 +236:2:3761 +237:2:3762 +238:2:3766 +239:2:3767 +240:2:3775 +241:2:3780 +242:2:3781 +243:2:3792 +244:2:3793 +245:2:3794 +246:2:3805 +247:2:3810 +248:2:3811 +249:2:3822 +250:2:3823 +251:2:3824 +252:2:3822 +253:2:3823 +254:2:3824 +255:2:3835 +256:0:4533 +257:2:3127 +258:0:4533 +259:2:3844 +260:2:3845 +261:2:3849 +262:2:3850 +263:2:3858 +264:2:3859 +265:2:3863 +266:2:3864 +267:2:3872 +268:2:3877 +269:2:3881 +270:2:3882 +271:2:3890 +272:2:3891 +273:2:3895 +274:2:3896 +275:2:3890 +276:2:3891 +277:2:3895 +278:2:3896 +279:2:3904 +280:2:3909 +281:2:3910 +282:2:3921 +283:2:3922 +284:2:3923 +285:2:3934 +286:2:3939 +287:2:3940 +288:2:3951 +289:2:3952 +290:2:3953 +291:2:3951 +292:2:3952 +293:2:3953 +294:2:3964 +295:2:3971 +296:0:4533 +297:2:3127 +298:0:4533 +299:1:2 +300:0:4533 +301:1:8 +302:0:4533 +303:1:9 +304:0:4533 +305:1:10 +306:0:4533 +307:1:11 +308:0:4533 +309:1:12 +310:1:13 +311:1:17 +312:1:18 +313:1:26 +314:1:27 +315:1:31 +316:1:32 +317:1:40 +318:1:45 +319:1:49 +320:1:50 +321:1:58 +322:1:59 +323:1:63 +324:1:64 +325:1:58 +326:1:59 +327:1:63 +328:1:64 +329:1:72 +330:1:77 +331:1:78 +332:1:89 +333:1:90 +334:1:91 +335:1:102 +336:1:107 +337:1:108 +338:1:119 +339:1:120 +340:1:121 +341:1:119 +342:1:120 +343:1:121 +344:1:132 +345:0:4533 +346:1:11 +347:0:4533 +348:1:141 +349:1:142 +350:0:4533 +351:1:11 +352:0:4533 +353:1:148 +354:1:149 +355:1:153 +356:1:154 +357:1:162 +358:1:163 +359:1:167 +360:1:168 +361:1:176 +362:1:181 +363:1:185 +364:1:186 +365:1:194 +366:1:195 +367:1:199 +368:1:200 +369:1:194 +370:1:195 +371:1:199 +372:1:200 +373:1:208 +374:1:213 +375:1:214 +376:1:225 +377:1:226 +378:1:227 +379:1:238 +380:1:243 +381:1:244 +382:1:255 +383:1:256 +384:1:257 +385:1:255 +386:1:256 +387:1:257 +388:1:268 +389:0:4533 +390:1:11 +391:0:4533 +392:1:277 +393:1:278 +394:1:282 +395:1:283 +396:1:291 +397:1:292 +398:1:296 +399:1:297 +400:1:305 +401:1:310 +402:1:314 +403:1:315 +404:1:323 +405:1:324 +406:1:328 +407:1:329 +408:1:323 +409:1:324 +410:1:328 +411:1:329 +412:1:337 +413:1:342 +414:1:343 +415:1:354 +416:1:355 +417:1:356 +418:1:367 +419:1:372 +420:1:373 +421:1:384 +422:1:385 +423:1:386 +424:1:384 +425:1:385 +426:1:386 +427:1:397 +428:1:404 +429:0:4533 +430:1:11 +431:0:4533 +432:1:540 +433:1:544 +434:1:545 +435:1:549 +436:1:550 +437:1:558 +438:1:566 +439:1:567 +440:1:571 +441:1:575 +442:1:576 +443:1:571 +444:1:575 +445:1:576 +446:1:580 +447:1:587 +448:1:594 +449:1:595 +450:1:602 +451:1:607 +452:1:614 +453:1:615 +454:1:614 +455:1:615 +456:1:622 +457:0:4533 +458:1:11 +459:0:4533 +460:2:3975 +461:2:3976 +462:2:3977 +463:2:3989 +464:2:3990 +465:2:3994 +466:2:3995 +467:2:4003 +468:2:4008 +469:2:4012 +470:2:4013 +471:2:4021 +472:2:4022 +473:2:4026 +474:2:4027 +475:2:4021 +476:2:4022 +477:2:4026 +478:2:4027 +479:2:4035 +480:2:4040 +481:2:4041 +482:2:4052 +483:2:4053 +484:2:4054 +485:2:4065 +486:2:4070 +487:2:4071 +488:2:4082 +489:2:4083 +490:2:4084 +491:2:4082 +492:2:4083 +493:2:4084 +494:2:4095 +495:2:4103 +496:0:4533 +497:2:3127 +498:0:4533 +499:2:4109 +500:2:4110 +501:2:4114 +502:2:4115 +503:2:4123 +504:2:4124 +505:2:4128 +506:2:4129 +507:2:4137 +508:2:4142 +509:2:4146 +510:2:4147 +511:2:4155 +512:2:4156 +513:2:4160 +514:2:4161 +515:2:4155 +516:2:4156 +517:2:4160 +518:2:4161 +519:2:4169 +520:2:4174 +521:2:4175 +522:2:4186 +523:2:4187 +524:2:4188 +525:2:4199 +526:2:4204 +527:2:4205 +528:2:4216 +529:2:4217 +530:2:4218 +531:2:4216 +532:2:4217 +533:2:4218 +534:2:4229 +535:0:4533 +536:2:3127 +537:0:4533 +538:1:632 +539:1:633 +540:1:637 +541:1:638 +542:1:646 +543:1:647 +544:1:651 +545:1:652 +546:1:660 +547:1:665 +548:1:669 +549:1:670 +550:1:678 +551:1:679 +552:1:683 +553:1:684 +554:1:678 +555:1:679 +556:1:683 +557:1:684 +558:1:692 +559:1:697 +560:1:698 +561:1:709 +562:1:710 +563:1:711 +564:1:722 +565:1:727 +566:1:728 +567:1:739 +568:1:740 +569:1:741 +570:1:739 +571:1:740 +572:1:741 +573:1:752 +574:0:4533 +575:1:11 +576:0:4533 +577:2:3975 +578:2:3976 +579:2:3980 +580:2:3981 +581:2:3989 +582:2:3990 +583:2:3994 +584:2:3995 +585:2:4003 +586:2:4008 +587:2:4012 +588:2:4013 +589:2:4021 +590:2:4022 +591:2:4026 +592:2:4027 +593:2:4021 +594:2:4022 +595:2:4026 +596:2:4027 +597:2:4035 +598:2:4040 +599:2:4041 +600:2:4052 +601:2:4053 +602:2:4054 +603:2:4065 +604:2:4070 +605:2:4071 +606:2:4082 +607:2:4083 +608:2:4084 +609:2:4082 +610:2:4083 +611:2:4084 +612:2:4095 +613:2:4103 +614:0:4533 +615:2:3127 +616:0:4533 +617:2:4109 +618:2:4110 +619:2:4114 +620:2:4115 +621:2:4123 +622:2:4124 +623:2:4128 +624:2:4129 +625:2:4137 +626:2:4142 +627:2:4146 +628:2:4147 +629:2:4155 +630:2:4156 +631:2:4160 +632:2:4161 +633:2:4155 +634:2:4156 +635:2:4160 +636:2:4161 +637:2:4169 +638:2:4174 +639:2:4175 +640:2:4186 +641:2:4187 +642:2:4188 +643:2:4199 +644:2:4204 +645:2:4205 +646:2:4216 +647:2:4217 +648:2:4218 +649:2:4216 +650:2:4217 +651:2:4218 +652:2:4229 +653:0:4533 +654:2:3127 +655:0:4533 +656:1:761 +657:1:764 +658:1:765 +659:0:4533 +660:1:11 +661:0:4533 +662:2:3975 +663:2:3976 +664:2:3980 +665:2:3981 +666:2:3989 +667:2:3990 +668:2:3994 +669:2:3995 +670:2:4003 +671:2:4008 +672:2:4012 +673:2:4013 +674:2:4021 +675:2:4022 +676:2:4026 +677:2:4027 +678:2:4021 +679:2:4022 +680:2:4026 +681:2:4027 +682:2:4035 +683:2:4040 +684:2:4041 +685:2:4052 +686:2:4053 +687:2:4054 +688:2:4065 +689:2:4070 +690:2:4071 +691:2:4082 +692:2:4083 +693:2:4084 +694:2:4082 +695:2:4083 +696:2:4084 +697:2:4095 +698:2:4103 +699:0:4533 +700:2:3127 +701:0:4533 +702:2:4109 +703:2:4110 +704:2:4114 +705:2:4115 +706:2:4123 +707:2:4124 +708:2:4128 +709:2:4129 +710:2:4137 +711:2:4142 +712:2:4146 +713:2:4147 +714:2:4155 +715:2:4156 +716:2:4160 +717:2:4161 +718:2:4155 +719:2:4156 +720:2:4160 +721:2:4161 +722:2:4169 +723:2:4174 +724:2:4175 +725:2:4186 +726:2:4187 +727:2:4188 +728:2:4199 +729:2:4204 +730:2:4205 +731:2:4216 +732:2:4217 +733:2:4218 +734:2:4216 +735:2:4217 +736:2:4218 +737:2:4229 +738:0:4533 +739:2:3127 +740:0:4533 +741:1:1028 +742:1:1029 +743:1:1033 +744:1:1034 +745:1:1042 +746:1:1043 +747:1:1047 +748:1:1048 +749:1:1056 +750:1:1061 +751:1:1065 +752:1:1066 +753:1:1074 +754:1:1075 +755:1:1079 +756:1:1080 +757:1:1074 +758:1:1075 +759:1:1079 +760:1:1080 +761:1:1088 +762:1:1093 +763:1:1094 +764:1:1105 +765:1:1106 +766:1:1107 +767:1:1118 +768:1:1123 +769:1:1124 +770:1:1135 +771:1:1136 +772:1:1137 +773:1:1135 +774:1:1136 +775:1:1137 +776:1:1148 +777:1:1155 +778:1:1159 +779:0:4533 +780:1:11 +781:0:4533 +782:2:3975 +783:2:3976 +784:2:3980 +785:2:3981 +786:2:3989 +787:2:3990 +788:2:3994 +789:2:3995 +790:2:4003 +791:2:4008 +792:2:4012 +793:2:4013 +794:2:4021 +795:2:4022 +796:2:4026 +797:2:4027 +798:2:4021 +799:2:4022 +800:2:4026 +801:2:4027 +802:2:4035 +803:2:4040 +804:2:4041 +805:2:4052 +806:2:4053 +807:2:4054 +808:2:4065 +809:2:4070 +810:2:4071 +811:2:4082 +812:2:4083 +813:2:4084 +814:2:4082 +815:2:4083 +816:2:4084 +817:2:4095 +818:2:4103 +819:0:4533 +820:2:3127 +821:0:4533 +822:2:4109 +823:2:4110 +824:2:4114 +825:2:4115 +826:2:4123 +827:2:4124 +828:2:4128 +829:2:4129 +830:2:4137 +831:2:4142 +832:2:4146 +833:2:4147 +834:2:4155 +835:2:4156 +836:2:4160 +837:2:4161 +838:2:4155 +839:2:4156 +840:2:4160 +841:2:4161 +842:2:4169 +843:2:4174 +844:2:4175 +845:2:4186 +846:2:4187 +847:2:4188 +848:2:4199 +849:2:4204 +850:2:4205 +851:2:4216 +852:2:4217 +853:2:4218 +854:2:4216 +855:2:4217 +856:2:4218 +857:2:4229 +858:0:4533 +859:2:3127 +860:0:4533 +861:1:1160 +862:1:1161 +863:1:1165 +864:1:1166 +865:1:1174 +866:1:1175 +867:1:1176 +868:1:1188 +869:1:1193 +870:1:1197 +871:1:1198 +872:1:1206 +873:1:1207 +874:1:1211 +875:1:1212 +876:1:1206 +877:1:1207 +878:1:1211 +879:1:1212 +880:1:1220 +881:1:1225 +882:1:1226 +883:1:1237 +884:1:1238 +885:1:1239 +886:1:1250 +887:1:1255 +888:1:1256 +889:1:1267 +890:1:1268 +891:1:1269 +892:1:1267 +893:1:1268 +894:1:1269 +895:1:1280 +896:0:4533 +897:1:11 +898:0:4533 +899:2:3975 +900:2:3976 +901:2:3980 +902:2:3981 +903:2:3989 +904:2:3990 +905:2:3994 +906:2:3995 +907:2:4003 +908:2:4008 +909:2:4012 +910:2:4013 +911:2:4021 +912:2:4022 +913:2:4026 +914:2:4027 +915:2:4021 +916:2:4022 +917:2:4026 +918:2:4027 +919:2:4035 +920:2:4040 +921:2:4041 +922:2:4052 +923:2:4053 +924:2:4054 +925:2:4065 +926:2:4070 +927:2:4071 +928:2:4082 +929:2:4083 +930:2:4084 +931:2:4082 +932:2:4083 +933:2:4084 +934:2:4095 +935:2:4103 +936:0:4533 +937:2:3127 +938:0:4533 +939:2:4109 +940:2:4110 +941:2:4114 +942:2:4115 +943:2:4123 +944:2:4124 +945:2:4128 +946:2:4129 +947:2:4137 +948:2:4142 +949:2:4146 +950:2:4147 +951:2:4155 +952:2:4156 +953:2:4160 +954:2:4161 +955:2:4155 +956:2:4156 +957:2:4160 +958:2:4161 +959:2:4169 +960:2:4174 +961:2:4175 +962:2:4186 +963:2:4187 +964:2:4188 +965:2:4199 +966:2:4204 +967:2:4205 +968:2:4216 +969:2:4217 +970:2:4218 +971:2:4216 +972:2:4217 +973:2:4218 +974:2:4229 +975:0:4533 +976:2:3127 +977:0:4533 +978:1:1289 +979:0:4533 +980:2:3975 +981:2:3976 +982:2:3980 +983:2:3981 +984:2:3989 +985:2:3990 +986:2:3994 +987:2:3995 +988:2:4003 +989:2:4008 +990:2:4012 +991:2:4013 +992:2:4021 +993:2:4022 +994:2:4026 +995:2:4027 +996:2:4021 +997:2:4022 +998:2:4026 +999:2:4027 +1000:2:4035 +1001:2:4040 +1002:2:4041 +1003:2:4052 +1004:2:4053 +1005:2:4054 +1006:2:4065 +1007:2:4070 +1008:2:4071 +1009:2:4082 +1010:2:4083 +1011:2:4084 +1012:2:4082 +1013:2:4083 +1014:2:4084 +1015:2:4095 +1016:2:4103 +1017:0:4533 +1018:2:3127 +1019:0:4533 +1020:2:4109 +1021:2:4110 +1022:2:4114 +1023:2:4115 +1024:2:4123 +1025:2:4124 +1026:2:4128 +1027:2:4129 +1028:2:4137 +1029:2:4142 +1030:2:4146 +1031:2:4147 +1032:2:4155 +1033:2:4156 +1034:2:4160 +1035:2:4161 +1036:2:4155 +1037:2:4156 +1038:2:4160 +1039:2:4161 +1040:2:4169 +1041:2:4174 +1042:2:4175 +1043:2:4186 +1044:2:4187 +1045:2:4188 +1046:2:4199 +1047:2:4204 +1048:2:4205 +1049:2:4216 +1050:2:4217 +1051:2:4218 +1052:2:4216 +1053:2:4217 +1054:2:4218 +1055:2:4229 +1056:0:4533 +1057:2:3127 +1058:0:4533 +1059:1:3023 +1060:1:3030 +1061:1:3031 +1062:1:3038 +1063:1:3043 +1064:1:3050 +1065:1:3051 +1066:1:3050 +1067:1:3051 +1068:1:3058 +1069:1:3062 +1070:0:4533 +1071:2:3975 +1072:2:3976 +1073:2:3980 +1074:2:3981 +1075:2:3989 +1076:2:3990 +1077:2:3994 +1078:2:3995 +1079:2:4003 +1080:2:4008 +1081:2:4012 +1082:2:4013 +1083:2:4021 +1084:2:4022 +1085:2:4026 +1086:2:4027 +1087:2:4021 +1088:2:4022 +1089:2:4026 +1090:2:4027 +1091:2:4035 +1092:2:4040 +1093:2:4041 +1094:2:4052 +1095:2:4053 +1096:2:4054 +1097:2:4065 +1098:2:4070 +1099:2:4071 +1100:2:4082 +1101:2:4083 +1102:2:4084 +1103:2:4082 +1104:2:4083 +1105:2:4084 +1106:2:4095 +1107:2:4103 +1108:0:4533 +1109:2:3127 +1110:0:4533 +1111:2:4109 +1112:2:4110 +1113:2:4114 +1114:2:4115 +1115:2:4123 +1116:2:4124 +1117:2:4128 +1118:2:4129 +1119:2:4137 +1120:2:4142 +1121:2:4146 +1122:2:4147 +1123:2:4155 +1124:2:4156 +1125:2:4160 +1126:2:4161 +1127:2:4155 +1128:2:4156 +1129:2:4160 +1130:2:4161 +1131:2:4169 +1132:2:4174 +1133:2:4175 +1134:2:4186 +1135:2:4187 +1136:2:4188 +1137:2:4199 +1138:2:4204 +1139:2:4205 +1140:2:4216 +1141:2:4217 +1142:2:4218 +1143:2:4216 +1144:2:4217 +1145:2:4218 +1146:2:4229 +1147:0:4533 +1148:2:3127 +1149:0:4533 +1150:1:1291 +1151:1:1292 +1152:0:4533 +1153:1:11 +1154:0:4533 +1155:2:3975 +1156:2:3976 +1157:2:3980 +1158:2:3981 +1159:2:3989 +1160:2:3990 +1161:2:3994 +1162:2:3995 +1163:2:4003 +1164:2:4008 +1165:2:4012 +1166:2:4013 +1167:2:4021 +1168:2:4022 +1169:2:4026 +1170:2:4027 +1171:2:4021 +1172:2:4022 +1173:2:4026 +1174:2:4027 +1175:2:4035 +1176:2:4040 +1177:2:4041 +1178:2:4052 +1179:2:4053 +1180:2:4054 +1181:2:4065 +1182:2:4070 +1183:2:4071 +1184:2:4082 +1185:2:4083 +1186:2:4084 +1187:2:4082 +1188:2:4083 +1189:2:4084 +1190:2:4095 +1191:2:4103 +1192:0:4533 +1193:2:3127 +1194:0:4533 +1195:2:4109 +1196:2:4110 +1197:2:4114 +1198:2:4115 +1199:2:4123 +1200:2:4124 +1201:2:4128 +1202:2:4129 +1203:2:4137 +1204:2:4142 +1205:2:4146 +1206:2:4147 +1207:2:4155 +1208:2:4156 +1209:2:4160 +1210:2:4161 +1211:2:4155 +1212:2:4156 +1213:2:4160 +1214:2:4161 +1215:2:4169 +1216:2:4174 +1217:2:4175 +1218:2:4186 +1219:2:4187 +1220:2:4188 +1221:2:4199 +1222:2:4204 +1223:2:4205 +1224:2:4216 +1225:2:4217 +1226:2:4218 +1227:2:4216 +1228:2:4217 +1229:2:4218 +1230:2:4229 +1231:0:4533 +1232:2:3127 +1233:0:4533 +1234:1:1293 +1235:1:1294 +1236:1:1298 +1237:1:1299 +1238:1:1307 +1239:1:1308 +1240:1:1312 +1241:1:1313 +1242:1:1321 +1243:1:1326 +1244:1:1330 +1245:1:1331 +1246:1:1339 +1247:1:1340 +1248:1:1344 +1249:1:1345 +1250:1:1339 +1251:1:1340 +1252:1:1344 +1253:1:1345 +1254:1:1353 +1255:1:1358 +1256:1:1359 +1257:1:1370 +1258:1:1371 +1259:1:1372 +1260:1:1383 +1261:1:1388 +1262:1:1389 +1263:1:1400 +1264:1:1401 +1265:1:1402 +1266:1:1400 +1267:1:1401 +1268:1:1402 +1269:1:1413 +1270:0:4533 +1271:1:11 +1272:0:4533 +1273:2:3975 +1274:2:3976 +1275:2:3980 +1276:2:3981 +1277:2:3989 +1278:2:3990 +1279:2:3994 +1280:2:3995 +1281:2:4003 +1282:2:4008 +1283:2:4012 +1284:2:4013 +1285:2:4021 +1286:2:4022 +1287:2:4026 +1288:2:4027 +1289:2:4021 +1290:2:4022 +1291:2:4026 +1292:2:4027 +1293:2:4035 +1294:2:4040 +1295:2:4041 +1296:2:4052 +1297:2:4053 +1298:2:4054 +1299:2:4065 +1300:2:4070 +1301:2:4071 +1302:2:4082 +1303:2:4083 +1304:2:4084 +1305:2:4082 +1306:2:4083 +1307:2:4084 +1308:2:4095 +1309:2:4103 +1310:0:4533 +1311:2:3127 +1312:0:4533 +1313:2:4109 +1314:2:4110 +1315:2:4114 +1316:2:4115 +1317:2:4123 +1318:2:4124 +1319:2:4128 +1320:2:4129 +1321:2:4137 +1322:2:4142 +1323:2:4146 +1324:2:4147 +1325:2:4155 +1326:2:4156 +1327:2:4160 +1328:2:4161 +1329:2:4155 +1330:2:4156 +1331:2:4160 +1332:2:4161 +1333:2:4169 +1334:2:4174 +1335:2:4175 +1336:2:4186 +1337:2:4187 +1338:2:4188 +1339:2:4199 +1340:2:4204 +1341:2:4205 +1342:2:4216 +1343:2:4217 +1344:2:4218 +1345:2:4216 +1346:2:4217 +1347:2:4218 +1348:2:4229 +1349:0:4533 +1350:2:3127 +1351:0:4533 +1352:1:1422 +1353:1:1423 +1354:1:1427 +1355:1:1428 +1356:1:1436 +1357:1:1437 +1358:1:1441 +1359:1:1442 +1360:1:1450 +1361:1:1455 +1362:1:1459 +1363:1:1460 +1364:1:1468 +1365:1:1469 +1366:1:1473 +1367:1:1474 +1368:1:1468 +1369:1:1469 +1370:1:1473 +1371:1:1474 +1372:1:1482 +1373:1:1487 +1374:1:1488 +1375:1:1499 +1376:1:1500 +1377:1:1501 +1378:1:1512 +1379:1:1517 +1380:1:1518 +1381:1:1529 +1382:1:1530 +1383:1:1531 +1384:1:1529 +1385:1:1530 +1386:1:1531 +1387:1:1542 +1388:1:1549 +1389:1:1553 +1390:0:4533 +1391:1:11 +1392:0:4533 +1393:2:3975 +1394:2:3976 +1395:2:3980 +1396:2:3981 +1397:2:3989 +1398:2:3990 +1399:2:3994 +1400:2:3995 +1401:2:4003 +1402:2:4008 +1403:2:4012 +1404:2:4013 +1405:2:4021 +1406:2:4022 +1407:2:4026 +1408:2:4027 +1409:2:4021 +1410:2:4022 +1411:2:4026 +1412:2:4027 +1413:2:4035 +1414:2:4040 +1415:2:4041 +1416:2:4052 +1417:2:4053 +1418:2:4054 +1419:2:4065 +1420:2:4070 +1421:2:4071 +1422:2:4082 +1423:2:4083 +1424:2:4084 +1425:2:4082 +1426:2:4083 +1427:2:4084 +1428:2:4095 +1429:2:4103 +1430:0:4533 +1431:2:3127 +1432:0:4533 +1433:2:4109 +1434:2:4110 +1435:2:4114 +1436:2:4115 +1437:2:4123 +1438:2:4124 +1439:2:4128 +1440:2:4129 +1441:2:4137 +1442:2:4142 +1443:2:4146 +1444:2:4147 +1445:2:4155 +1446:2:4156 +1447:2:4160 +1448:2:4161 +1449:2:4155 +1450:2:4156 +1451:2:4160 +1452:2:4161 +1453:2:4169 +1454:2:4174 +1455:2:4175 +1456:2:4186 +1457:2:4187 +1458:2:4188 +1459:2:4199 +1460:2:4204 +1461:2:4205 +1462:2:4216 +1463:2:4217 +1464:2:4218 +1465:2:4216 +1466:2:4217 +1467:2:4218 +1468:2:4229 +1469:0:4533 +1470:2:3127 +1471:0:4533 +1472:1:1554 +1473:1:1558 +1474:1:1559 +1475:1:1563 +1476:1:1564 +1477:1:1572 +1478:1:1580 +1479:1:1581 +1480:1:1585 +1481:1:1589 +1482:1:1590 +1483:1:1585 +1484:1:1589 +1485:1:1590 +1486:1:1594 +1487:1:1601 +1488:1:1608 +1489:1:1609 +1490:1:1616 +1491:1:1621 +1492:1:1628 +1493:1:1629 +1494:1:1628 +1495:1:1629 +1496:1:1636 +1497:0:4533 +1498:1:11 +1499:0:4533 +1500:2:3975 +1501:2:3976 +1502:2:3980 +1503:2:3981 +1504:2:3989 +1505:2:3990 +1506:2:3994 +1507:2:3995 +1508:2:4003 +1509:2:4008 +1510:2:4012 +1511:2:4013 +1512:2:4021 +1513:2:4022 +1514:2:4026 +1515:2:4027 +1516:2:4021 +1517:2:4022 +1518:2:4026 +1519:2:4027 +1520:2:4035 +1521:2:4040 +1522:2:4041 +1523:2:4052 +1524:2:4053 +1525:2:4054 +1526:2:4065 +1527:2:4070 +1528:2:4071 +1529:2:4082 +1530:2:4083 +1531:2:4084 +1532:2:4082 +1533:2:4083 +1534:2:4084 +1535:2:4095 +1536:2:4103 +1537:0:4533 +1538:2:3127 +1539:0:4533 +1540:2:4109 +1541:2:4110 +1542:2:4114 +1543:2:4115 +1544:2:4123 +1545:2:4124 +1546:2:4128 +1547:2:4129 +1548:2:4137 +1549:2:4142 +1550:2:4146 +1551:2:4147 +1552:2:4155 +1553:2:4156 +1554:2:4160 +1555:2:4161 +1556:2:4155 +1557:2:4156 +1558:2:4160 +1559:2:4161 +1560:2:4169 +1561:2:4174 +1562:2:4175 +1563:2:4186 +1564:2:4187 +1565:2:4188 +1566:2:4199 +1567:2:4204 +1568:2:4205 +1569:2:4216 +1570:2:4217 +1571:2:4218 +1572:2:4216 +1573:2:4217 +1574:2:4218 +1575:2:4229 +1576:0:4533 +1577:2:3127 +1578:0:4533 +1579:1:1646 +1580:1:1647 +1581:1:1651 +1582:1:1652 +1583:1:1660 +1584:1:1661 +1585:1:1665 +1586:1:1666 +1587:1:1674 +1588:1:1679 +1589:1:1683 +1590:1:1684 +1591:1:1692 +1592:1:1693 +1593:1:1697 +1594:1:1698 +1595:1:1692 +1596:1:1693 +1597:1:1697 +1598:1:1698 +1599:1:1706 +1600:1:1711 +1601:1:1712 +1602:1:1723 +1603:1:1724 +1604:1:1725 +1605:1:1736 +1606:1:1741 +1607:1:1742 +1608:1:1753 +1609:1:1754 +1610:1:1755 +1611:1:1753 +1612:1:1754 +1613:1:1755 +1614:1:1766 +1615:0:4533 +1616:1:11 +1617:0:4533 +1618:2:3975 +1619:2:3976 +1620:2:3980 +1621:2:3981 +1622:2:3989 +1623:2:3990 +1624:2:3994 +1625:2:3995 +1626:2:4003 +1627:2:4008 +1628:2:4012 +1629:2:4013 +1630:2:4021 +1631:2:4022 +1632:2:4026 +1633:2:4027 +1634:2:4021 +1635:2:4022 +1636:2:4026 +1637:2:4027 +1638:2:4035 +1639:2:4040 +1640:2:4041 +1641:2:4052 +1642:2:4053 +1643:2:4054 +1644:2:4065 +1645:2:4070 +1646:2:4071 +1647:2:4082 +1648:2:4083 +1649:2:4084 +1650:2:4082 +1651:2:4083 +1652:2:4084 +1653:2:4095 +1654:2:4103 +1655:0:4533 +1656:2:3127 +1657:0:4533 +1658:2:4109 +1659:2:4110 +1660:2:4114 +1661:2:4115 +1662:2:4123 +1663:2:4124 +1664:2:4128 +1665:2:4129 +1666:2:4137 +1667:2:4142 +1668:2:4146 +1669:2:4147 +1670:2:4155 +1671:2:4156 +1672:2:4160 +1673:2:4161 +1674:2:4155 +1675:2:4156 +1676:2:4160 +1677:2:4161 +1678:2:4169 +1679:2:4174 +1680:2:4175 +1681:2:4186 +1682:2:4187 +1683:2:4188 +1684:2:4199 +1685:2:4204 +1686:2:4205 +1687:2:4216 +1688:2:4217 +1689:2:4218 +1690:2:4216 +1691:2:4217 +1692:2:4218 +1693:2:4229 +1694:0:4533 +1695:2:3127 +1696:0:4533 +1697:1:1775 +1698:1:1776 +1699:1:1780 +1700:1:1781 +1701:1:1789 +1702:1:1790 +1703:1:1794 +1704:1:1795 +1705:1:1803 +1706:1:1808 +1707:1:1812 +1708:1:1813 +1709:1:1821 +1710:1:1822 +1711:1:1826 +1712:1:1827 +1713:1:1821 +1714:1:1822 +1715:1:1826 +1716:1:1827 +1717:1:1835 +1718:1:1840 +1719:1:1841 +1720:1:1852 +1721:1:1853 +1722:1:1854 +1723:1:1865 +1724:1:1870 +1725:1:1871 +1726:1:1882 +1727:1:1883 +1728:1:1884 +1729:1:1882 +1730:1:1883 +1731:1:1884 +1732:1:1895 +1733:1:1902 +1734:1:1906 +1735:0:4533 +1736:1:11 +1737:0:4533 +1738:2:3975 +1739:2:3976 +1740:2:3980 +1741:2:3981 +1742:2:3989 +1743:2:3990 +1744:2:3994 +1745:2:3995 +1746:2:4003 +1747:2:4008 +1748:2:4012 +1749:2:4013 +1750:2:4021 +1751:2:4022 +1752:2:4026 +1753:2:4027 +1754:2:4021 +1755:2:4022 +1756:2:4026 +1757:2:4027 +1758:2:4035 +1759:2:4040 +1760:2:4041 +1761:2:4052 +1762:2:4053 +1763:2:4054 +1764:2:4065 +1765:2:4070 +1766:2:4071 +1767:2:4082 +1768:2:4083 +1769:2:4084 +1770:2:4082 +1771:2:4083 +1772:2:4084 +1773:2:4095 +1774:2:4103 +1775:0:4533 +1776:2:3127 +1777:0:4533 +1778:2:4109 +1779:2:4110 +1780:2:4114 +1781:2:4115 +1782:2:4123 +1783:2:4124 +1784:2:4128 +1785:2:4129 +1786:2:4137 +1787:2:4142 +1788:2:4146 +1789:2:4147 +1790:2:4155 +1791:2:4156 +1792:2:4160 +1793:2:4161 +1794:2:4155 +1795:2:4156 +1796:2:4160 +1797:2:4161 +1798:2:4169 +1799:2:4174 +1800:2:4175 +1801:2:4186 +1802:2:4187 +1803:2:4188 +1804:2:4199 +1805:2:4204 +1806:2:4205 +1807:2:4216 +1808:2:4217 +1809:2:4218 +1810:2:4216 +1811:2:4217 +1812:2:4218 +1813:2:4229 +1814:0:4533 +1815:2:3127 +1816:0:4533 +1817:1:1907 +1818:1:1908 +1819:1:1912 +1820:1:1913 +1821:1:1921 +1822:1:1922 +1823:1:1923 +1824:1:1935 +1825:1:1940 +1826:1:1944 +1827:1:1945 +1828:1:1953 +1829:1:1954 +1830:1:1958 +1831:1:1959 +1832:1:1953 +1833:1:1954 +1834:1:1958 +1835:1:1959 +1836:1:1967 +1837:1:1972 +1838:1:1973 +1839:1:1984 +1840:1:1985 +1841:1:1986 +1842:1:1997 +1843:1:2002 +1844:1:2003 +1845:1:2014 +1846:1:2015 +1847:1:2016 +1848:1:2014 +1849:1:2015 +1850:1:2016 +1851:1:2027 +1852:0:4533 +1853:1:11 +1854:0:4533 +1855:2:3975 +1856:2:3976 +1857:2:3980 +1858:2:3981 +1859:2:3989 +1860:2:3990 +1861:2:3994 +1862:2:3995 +1863:2:4003 +1864:2:4008 +1865:2:4012 +1866:2:4013 +1867:2:4021 +1868:2:4022 +1869:2:4026 +1870:2:4027 +1871:2:4021 +1872:2:4022 +1873:2:4026 +1874:2:4027 +1875:2:4035 +1876:2:4040 +1877:2:4041 +1878:2:4052 +1879:2:4060 +1880:2:4061 +1881:2:4065 +1882:2:4070 +1883:2:4071 +1884:2:4082 +1885:2:4083 +1886:2:4084 +1887:2:4082 +1888:2:4083 +1889:2:4084 +1890:2:4095 +1891:2:4103 +1892:0:4533 +1893:2:3127 +1894:0:4533 +1895:2:4109 +1896:2:4110 +1897:2:4114 +1898:2:4115 +1899:2:4123 +1900:2:4124 +1901:2:4128 +1902:2:4129 +1903:2:4137 +1904:2:4142 +1905:2:4146 +1906:2:4147 +1907:2:4155 +1908:2:4156 +1909:2:4160 +1910:2:4161 +1911:2:4155 +1912:2:4156 +1913:2:4160 +1914:2:4161 +1915:2:4169 +1916:2:4174 +1917:2:4175 +1918:2:4186 +1919:2:4194 +1920:2:4195 +1921:2:4199 +1922:2:4204 +1923:2:4205 +1924:2:4216 +1925:2:4217 +1926:2:4218 +1927:2:4216 +1928:2:4217 +1929:2:4218 +1930:2:4229 +1931:0:4533 +1932:2:3127 +1933:0:4533 +1934:1:2036 +1935:1:2037 +1936:0:4533 +1937:1:11 +1938:0:4533 +1939:2:3975 +1940:2:3976 +1941:2:3980 +1942:2:3981 +1943:2:3989 +1944:2:3990 +1945:2:3994 +1946:2:3995 +1947:2:4003 +1948:2:4008 +1949:2:4012 +1950:2:4013 +1951:2:4021 +1952:2:4022 +1953:2:4026 +1954:2:4027 +1955:2:4021 +1956:2:4022 +1957:2:4026 +1958:2:4027 +1959:2:4035 +1960:2:4040 +1961:2:4041 +1962:2:4052 +1963:2:4060 +1964:2:4061 +1965:2:4065 +1966:2:4070 +1967:2:4071 +1968:2:4082 +1969:2:4083 +1970:2:4084 +1971:2:4082 +1972:2:4083 +1973:2:4084 +1974:2:4095 +1975:2:4103 +1976:0:4533 +1977:2:3127 +1978:0:4533 +1979:2:4109 +1980:2:4110 +1981:2:4114 +1982:2:4115 +1983:2:4123 +1984:2:4124 +1985:2:4128 +1986:2:4129 +1987:2:4137 +1988:2:4142 +1989:2:4146 +1990:2:4147 +1991:2:4155 +1992:2:4156 +1993:2:4160 +1994:2:4161 +1995:2:4155 +1996:2:4156 +1997:2:4160 +1998:2:4161 +1999:2:4169 +2000:2:4174 +2001:2:4175 +2002:2:4186 +2003:2:4194 +2004:2:4195 +2005:2:4199 +2006:2:4204 +2007:2:4205 +2008:2:4216 +2009:2:4217 +2010:2:4218 +2011:2:4216 +2012:2:4217 +2013:2:4218 +2014:2:4229 +2015:0:4533 +2016:2:3127 +2017:0:4533 +2018:1:2043 +2019:1:2044 +2020:1:2048 +2021:1:2049 +2022:1:2057 +2023:1:2058 +2024:1:2062 +2025:1:2063 +2026:1:2071 +2027:1:2076 +2028:1:2080 +2029:1:2081 +2030:1:2089 +2031:1:2090 +2032:1:2094 +2033:1:2095 +2034:1:2089 +2035:1:2090 +2036:1:2094 +2037:1:2095 +2038:1:2103 +2039:1:2108 +2040:1:2109 +2041:1:2120 +2042:1:2121 +2043:1:2122 +2044:1:2133 +2045:1:2138 +2046:1:2139 +2047:1:2150 +2048:1:2151 +2049:1:2152 +2050:1:2150 +2051:1:2151 +2052:1:2152 +2053:1:2163 +2054:0:4533 +2055:1:11 +2056:0:4533 +2057:2:3975 +2058:2:3976 +2059:2:3980 +2060:2:3981 +2061:2:3989 +2062:2:3990 +2063:2:3994 +2064:2:3995 +2065:2:4003 +2066:2:4008 +2067:2:4012 +2068:2:4013 +2069:2:4021 +2070:2:4022 +2071:2:4026 +2072:2:4027 +2073:2:4021 +2074:2:4022 +2075:2:4026 +2076:2:4027 +2077:2:4035 +2078:2:4040 +2079:2:4041 +2080:2:4052 +2081:2:4060 +2082:2:4061 +2083:2:4065 +2084:2:4070 +2085:2:4071 +2086:2:4082 +2087:2:4083 +2088:2:4084 +2089:2:4082 +2090:2:4083 +2091:2:4084 +2092:2:4095 +2093:2:4103 +2094:0:4533 +2095:2:3127 +2096:0:4533 +2097:2:4109 +2098:2:4110 +2099:2:4114 +2100:2:4115 +2101:2:4123 +2102:2:4124 +2103:2:4128 +2104:2:4129 +2105:2:4137 +2106:2:4142 +2107:2:4146 +2108:2:4147 +2109:2:4155 +2110:2:4156 +2111:2:4160 +2112:2:4161 +2113:2:4155 +2114:2:4156 +2115:2:4160 +2116:2:4161 +2117:2:4169 +2118:2:4174 +2119:2:4175 +2120:2:4186 +2121:2:4194 +2122:2:4195 +2123:2:4199 +2124:2:4204 +2125:2:4205 +2126:2:4216 +2127:2:4217 +2128:2:4218 +2129:2:4216 +2130:2:4217 +2131:2:4218 +2132:2:4229 +2133:0:4533 +2134:2:3127 +2135:0:4533 +2136:1:2172 +2137:1:2173 +2138:1:2177 +2139:1:2178 +2140:1:2186 +2141:1:2187 +2142:1:2191 +2143:1:2192 +2144:1:2200 +2145:1:2205 +2146:1:2209 +2147:1:2210 +2148:1:2218 +2149:1:2219 +2150:1:2223 +2151:1:2224 +2152:1:2218 +2153:1:2219 +2154:1:2223 +2155:1:2224 +2156:1:2232 +2157:1:2237 +2158:1:2238 +2159:1:2249 +2160:1:2250 +2161:1:2251 +2162:1:2262 +2163:1:2267 +2164:1:2268 +2165:1:2279 +2166:1:2280 +2167:1:2281 +2168:1:2279 +2169:1:2280 +2170:1:2281 +2171:1:2292 +2172:1:2299 +2173:0:4533 +2174:1:11 +2175:0:4533 +2176:2:3975 +2177:2:3976 +2178:2:3980 +2179:2:3981 +2180:2:3989 +2181:2:3990 +2182:2:3994 +2183:2:3995 +2184:2:4003 +2185:2:4008 +2186:2:4012 +2187:2:4013 +2188:2:4021 +2189:2:4022 +2190:2:4026 +2191:2:4027 +2192:2:4021 +2193:2:4022 +2194:2:4026 +2195:2:4027 +2196:2:4035 +2197:2:4040 +2198:2:4041 +2199:2:4052 +2200:2:4060 +2201:2:4061 +2202:2:4065 +2203:2:4070 +2204:2:4071 +2205:2:4082 +2206:2:4083 +2207:2:4084 +2208:2:4082 +2209:2:4083 +2210:2:4084 +2211:2:4095 +2212:2:4103 +2213:0:4533 +2214:2:3127 +2215:0:4533 +2216:2:4109 +2217:2:4110 +2218:2:4114 +2219:2:4115 +2220:2:4123 +2221:2:4124 +2222:2:4128 +2223:2:4129 +2224:2:4137 +2225:2:4142 +2226:2:4146 +2227:2:4147 +2228:2:4155 +2229:2:4156 +2230:2:4160 +2231:2:4161 +2232:2:4155 +2233:2:4156 +2234:2:4160 +2235:2:4161 +2236:2:4169 +2237:2:4174 +2238:2:4175 +2239:2:4186 +2240:2:4194 +2241:2:4195 +2242:2:4199 +2243:2:4204 +2244:2:4205 +2245:2:4216 +2246:2:4217 +2247:2:4218 +2248:2:4216 +2249:2:4217 +2250:2:4218 +2251:2:4229 +2252:0:4533 +2253:2:3127 +2254:0:4533 +2255:1:2435 +2256:1:2439 +2257:1:2440 +2258:1:2444 +2259:1:2445 +2260:1:2453 +2261:1:2461 +2262:1:2462 +2263:1:2466 +2264:1:2470 +2265:1:2471 +2266:1:2466 +2267:1:2470 +2268:1:2471 +2269:1:2475 +2270:1:2482 +2271:1:2489 +2272:1:2490 +2273:1:2497 +2274:1:2502 +2275:1:2509 +2276:1:2510 +2277:1:2509 +2278:1:2510 +2279:1:2517 +2280:0:4533 +2281:1:11 +2282:0:4533 +2283:2:3975 +2284:2:3976 +2285:2:3980 +2286:2:3981 +2287:2:3989 +2288:2:3990 +2289:2:3994 +2290:2:3995 +2291:2:4003 +2292:2:4008 +2293:2:4012 +2294:2:4013 +2295:2:4021 +2296:2:4022 +2297:2:4026 +2298:2:4027 +2299:2:4021 +2300:2:4022 +2301:2:4026 +2302:2:4027 +2303:2:4035 +2304:2:4040 +2305:2:4041 +2306:2:4052 +2307:2:4060 +2308:2:4061 +2309:2:4065 +2310:2:4070 +2311:2:4071 +2312:2:4082 +2313:2:4083 +2314:2:4084 +2315:2:4082 +2316:2:4083 +2317:2:4084 +2318:2:4095 +2319:2:4103 +2320:0:4533 +2321:2:3127 +2322:0:4533 +2323:2:4109 +2324:2:4110 +2325:2:4114 +2326:2:4115 +2327:2:4123 +2328:2:4124 +2329:2:4128 +2330:2:4129 +2331:2:4137 +2332:2:4142 +2333:2:4146 +2334:2:4147 +2335:2:4155 +2336:2:4156 +2337:2:4160 +2338:2:4161 +2339:2:4155 +2340:2:4156 +2341:2:4160 +2342:2:4161 +2343:2:4169 +2344:2:4174 +2345:2:4175 +2346:2:4186 +2347:2:4194 +2348:2:4195 +2349:2:4199 +2350:2:4204 +2351:2:4205 +2352:2:4216 +2353:2:4217 +2354:2:4218 +2355:2:4216 +2356:2:4217 +2357:2:4218 +2358:2:4229 +2359:0:4533 +2360:2:3127 +2361:0:4533 +2362:1:2527 +2363:1:2528 +2364:1:2532 +2365:1:2533 +2366:1:2541 +2367:1:2542 +2368:1:2546 +2369:1:2547 +2370:1:2555 +2371:1:2560 +2372:1:2564 +2373:1:2565 +2374:1:2573 +2375:1:2574 +2376:1:2578 +2377:1:2579 +2378:1:2573 +2379:1:2574 +2380:1:2578 +2381:1:2579 +2382:1:2587 +2383:1:2592 +2384:1:2593 +2385:1:2604 +2386:1:2605 +2387:1:2606 +2388:1:2617 +2389:1:2622 +2390:1:2623 +2391:1:2634 +2392:1:2635 +2393:1:2636 +2394:1:2634 +2395:1:2635 +2396:1:2636 +2397:1:2647 +2398:0:4533 +2399:1:11 +2400:0:4533 +2401:2:3975 +2402:2:3976 +2403:2:3980 +2404:2:3981 +2405:2:3989 +2406:2:3990 +2407:2:3994 +2408:2:3995 +2409:2:4003 +2410:2:4008 +2411:2:4012 +2412:2:4013 +2413:2:4021 +2414:2:4022 +2415:2:4026 +2416:2:4027 +2417:2:4021 +2418:2:4022 +2419:2:4026 +2420:2:4027 +2421:2:4035 +2422:2:4040 +2423:2:4041 +2424:2:4052 +2425:2:4060 +2426:2:4061 +2427:2:4065 +2428:2:4070 +2429:2:4071 +2430:2:4082 +2431:2:4083 +2432:2:4084 +2433:2:4082 +2434:2:4083 +2435:2:4084 +2436:2:4095 +2437:2:4103 +2438:0:4533 +2439:2:3127 +2440:0:4533 +2441:2:4109 +2442:2:4110 +2443:2:4114 +2444:2:4115 +2445:2:4123 +2446:2:4124 +2447:2:4128 +2448:2:4129 +2449:2:4137 +2450:2:4142 +2451:2:4146 +2452:2:4147 +2453:2:4155 +2454:2:4156 +2455:2:4160 +2456:2:4161 +2457:2:4155 +2458:2:4156 +2459:2:4160 +2460:2:4161 +2461:2:4169 +2462:2:4174 +2463:2:4175 +2464:2:4186 +2465:2:4194 +2466:2:4195 +2467:2:4199 +2468:2:4204 +2469:2:4205 +2470:2:4216 +2471:2:4217 +2472:2:4218 +2473:2:4216 +2474:2:4217 +2475:2:4218 +2476:2:4229 +2477:0:4533 +2478:2:3127 +2479:0:4533 +2480:1:2656 +2481:0:4533 +2482:2:3975 +2483:2:3976 +2484:2:3980 +2485:2:3981 +2486:2:3989 +2487:2:3990 +2488:2:3994 +2489:2:3995 +2490:2:4003 +2491:2:4008 +2492:2:4012 +2493:2:4013 +2494:2:4021 +2495:2:4022 +2496:2:4026 +2497:2:4027 +2498:2:4021 +2499:2:4022 +2500:2:4026 +2501:2:4027 +2502:2:4035 +2503:2:4040 +2504:2:4041 +2505:2:4052 +2506:2:4060 +2507:2:4061 +2508:2:4065 +2509:2:4070 +2510:2:4071 +2511:2:4082 +2512:2:4083 +2513:2:4084 +2514:2:4082 +2515:2:4083 +2516:2:4084 +2517:2:4095 +2518:2:4103 +2519:0:4533 +2520:2:3127 +2521:0:4533 +2522:2:4109 +2523:2:4110 +2524:2:4114 +2525:2:4115 +2526:2:4123 +2527:2:4124 +2528:2:4128 +2529:2:4129 +2530:2:4137 +2531:2:4142 +2532:2:4146 +2533:2:4147 +2534:2:4155 +2535:2:4156 +2536:2:4160 +2537:2:4161 +2538:2:4155 +2539:2:4156 +2540:2:4160 +2541:2:4161 +2542:2:4169 +2543:2:4174 +2544:2:4175 +2545:2:4186 +2546:2:4194 +2547:2:4195 +2548:2:4199 +2549:2:4204 +2550:2:4205 +2551:2:4216 +2552:2:4217 +2553:2:4218 +2554:2:4216 +2555:2:4217 +2556:2:4218 +2557:2:4229 +2558:0:4533 +2559:2:3127 +2560:0:4533 +2561:1:3066 +2562:1:3073 +2563:1:3074 +2564:1:3081 +2565:1:3086 +2566:1:3093 +2567:1:3094 +2568:1:3093 +2569:1:3094 +2570:1:3101 +2571:1:3105 +2572:0:4533 +2573:2:3975 +2574:2:3976 +2575:2:3980 +2576:2:3981 +2577:2:3989 +2578:2:3990 +2579:2:3994 +2580:2:3995 +2581:2:4003 +2582:2:4008 +2583:2:4012 +2584:2:4013 +2585:2:4021 +2586:2:4022 +2587:2:4026 +2588:2:4027 +2589:2:4021 +2590:2:4022 +2591:2:4026 +2592:2:4027 +2593:2:4035 +2594:2:4040 +2595:2:4041 +2596:2:4052 +2597:2:4060 +2598:2:4061 +2599:2:4065 +2600:2:4070 +2601:2:4071 +2602:2:4082 +2603:2:4083 +2604:2:4084 +2605:2:4082 +2606:2:4083 +2607:2:4084 +2608:2:4095 +2609:2:4103 +2610:0:4533 +2611:2:3127 +2612:0:4533 +2613:2:4109 +2614:2:4110 +2615:2:4114 +2616:2:4115 +2617:2:4123 +2618:2:4124 +2619:2:4128 +2620:2:4129 +2621:2:4137 +2622:2:4142 +2623:2:4146 +2624:2:4147 +2625:2:4155 +2626:2:4156 +2627:2:4160 +2628:2:4161 +2629:2:4155 +2630:2:4156 +2631:2:4160 +2632:2:4161 +2633:2:4169 +2634:2:4174 +2635:2:4175 +2636:2:4186 +2637:2:4194 +2638:2:4195 +2639:2:4199 +2640:2:4204 +2641:2:4205 +2642:2:4216 +2643:2:4217 +2644:2:4218 +2645:2:4216 +2646:2:4217 +2647:2:4218 +2648:2:4229 +2649:0:4533 +2650:2:3127 +2651:0:4533 +2652:1:2658 +2653:1:2659 +2654:0:4533 +2655:1:11 +2656:0:4533 +2657:2:3975 +2658:2:3976 +2659:2:3980 +2660:2:3981 +2661:2:3989 +2662:2:3990 +2663:2:3994 +2664:2:3995 +2665:2:4003 +2666:2:4008 +2667:2:4012 +2668:2:4013 +2669:2:4021 +2670:2:4022 +2671:2:4026 +2672:2:4027 +2673:2:4021 +2674:2:4022 +2675:2:4026 +2676:2:4027 +2677:2:4035 +2678:2:4040 +2679:2:4041 +2680:2:4052 +2681:2:4060 +2682:2:4061 +2683:2:4065 +2684:2:4070 +2685:2:4071 +2686:2:4082 +2687:2:4083 +2688:2:4084 +2689:2:4082 +2690:2:4083 +2691:2:4084 +2692:2:4095 +2693:2:4103 +2694:0:4533 +2695:2:3127 +2696:0:4533 +2697:2:4109 +2698:2:4110 +2699:2:4114 +2700:2:4115 +2701:2:4123 +2702:2:4124 +2703:2:4128 +2704:2:4129 +2705:2:4137 +2706:2:4142 +2707:2:4146 +2708:2:4147 +2709:2:4155 +2710:2:4156 +2711:2:4160 +2712:2:4161 +2713:2:4155 +2714:2:4156 +2715:2:4160 +2716:2:4161 +2717:2:4169 +2718:2:4174 +2719:2:4175 +2720:2:4186 +2721:2:4194 +2722:2:4195 +2723:2:4199 +2724:2:4204 +2725:2:4205 +2726:2:4216 +2727:2:4217 +2728:2:4218 +2729:2:4216 +2730:2:4217 +2731:2:4218 +2732:2:4229 +2733:0:4533 +2734:2:3127 +2735:0:4533 +2736:1:2660 +2737:1:2664 +2738:1:2665 +2739:1:2669 +2740:1:2673 +2741:1:2674 +2742:1:2678 +2743:1:2686 +2744:1:2687 +2745:1:2691 +2746:1:2695 +2747:1:2696 +2748:1:2691 +2749:1:2695 +2750:1:2696 +2751:1:2700 +2752:1:2707 +2753:1:2714 +2754:1:2715 +2755:1:2722 +2756:1:2727 +2757:1:2734 +2758:1:2735 +2759:1:2734 +2760:1:2735 +2761:1:2742 +2762:0:4533 +2763:1:11 +2764:0:4533 +2765:2:3975 +2766:2:3976 +2767:2:3980 +2768:2:3981 +2769:2:3989 +2770:2:3990 +2771:2:3994 +2772:2:3995 +2773:2:4003 +2774:2:4008 +2775:2:4012 +2776:2:4013 +2777:2:4021 +2778:2:4022 +2779:2:4026 +2780:2:4027 +2781:2:4021 +2782:2:4022 +2783:2:4026 +2784:2:4027 +2785:2:4035 +2786:2:4040 +2787:2:4041 +2788:2:4052 +2789:2:4060 +2790:2:4061 +2791:2:4065 +2792:2:4070 +2793:2:4071 +2794:2:4082 +2795:2:4083 +2796:2:4084 +2797:2:4082 +2798:2:4083 +2799:2:4084 +2800:2:4095 +2801:2:4103 +2802:0:4533 +2803:2:3127 +2804:0:4533 +2805:2:4109 +2806:2:4110 +2807:2:4114 +2808:2:4115 +2809:2:4123 +2810:2:4124 +2811:2:4128 +2812:2:4129 +2813:2:4137 +2814:2:4142 +2815:2:4146 +2816:2:4147 +2817:2:4155 +2818:2:4156 +2819:2:4160 +2820:2:4161 +2821:2:4155 +2822:2:4156 +2823:2:4160 +2824:2:4161 +2825:2:4169 +2826:2:4174 +2827:2:4175 +2828:2:4186 +2829:2:4194 +2830:2:4195 +2831:2:4199 +2832:2:4204 +2833:2:4205 +2834:2:4216 +2835:2:4217 +2836:2:4218 +2837:2:4216 +2838:2:4217 +2839:2:4218 +2840:2:4229 +2841:0:4533 +2842:2:3127 +2843:0:4533 +2844:1:2752 +2845:1:2753 +2846:1:2757 +2847:1:2758 +2848:1:2766 +2849:1:2767 +2850:1:2771 +2851:1:2772 +2852:1:2780 +2853:1:2785 +2854:1:2789 +2855:1:2790 +2856:1:2798 +2857:1:2799 +2858:1:2803 +2859:1:2804 +2860:1:2798 +2861:1:2799 +2862:1:2803 +2863:1:2804 +2864:1:2812 +2865:1:2817 +2866:1:2818 +2867:1:2829 +2868:1:2830 +2869:1:2831 +2870:1:2842 +2871:1:2847 +2872:1:2848 +2873:1:2859 +2874:1:2860 +2875:1:2861 +2876:1:2859 +2877:1:2860 +2878:1:2861 +2879:1:2872 +2880:0:4533 +2881:1:11 +2882:0:4533 +2883:2:3975 +2884:2:3976 +2885:2:3980 +2886:2:3981 +2887:2:3989 +2888:2:3990 +2889:2:3994 +2890:2:3995 +2891:2:4003 +2892:2:4008 +2893:2:4012 +2894:2:4013 +2895:2:4021 +2896:2:4022 +2897:2:4026 +2898:2:4027 +2899:2:4021 +2900:2:4022 +2901:2:4026 +2902:2:4027 +2903:2:4035 +2904:2:4040 +2905:2:4041 +2906:2:4052 +2907:2:4060 +2908:2:4061 +2909:2:4065 +2910:2:4070 +2911:2:4071 +2912:2:4082 +2913:2:4083 +2914:2:4084 +2915:2:4082 +2916:2:4083 +2917:2:4084 +2918:2:4095 +2919:2:4103 +2920:0:4533 +2921:2:3127 +2922:0:4533 +2923:2:4109 +2924:2:4110 +2925:2:4114 +2926:2:4115 +2927:2:4123 +2928:2:4124 +2929:2:4128 +2930:2:4129 +2931:2:4137 +2932:2:4142 +2933:2:4146 +2934:2:4147 +2935:2:4155 +2936:2:4156 +2937:2:4160 +2938:2:4161 +2939:2:4155 +2940:2:4156 +2941:2:4160 +2942:2:4161 +2943:2:4169 +2944:2:4174 +2945:2:4175 +2946:2:4186 +2947:2:4194 +2948:2:4195 +2949:2:4199 +2950:2:4204 +2951:2:4205 +2952:2:4216 +2953:2:4217 +2954:2:4218 +2955:2:4216 +2956:2:4217 +2957:2:4218 +2958:2:4229 +2959:0:4533 +2960:2:3127 +2961:0:4533 +2962:1:2881 +2963:1:2882 +2964:1:2886 +2965:1:2887 +2966:1:2895 +2967:1:2896 +2968:1:2900 +2969:1:2901 +2970:1:2909 +2971:1:2914 +2972:1:2918 +2973:1:2919 +2974:1:2927 +2975:1:2928 +2976:1:2932 +2977:1:2933 +2978:1:2927 +2979:1:2928 +2980:1:2932 +2981:1:2933 +2982:1:2941 +2983:1:2946 +2984:1:2947 +2985:1:2958 +2986:1:2959 +2987:1:2960 +2988:1:2971 +2989:1:2976 +2990:1:2977 +2991:1:2988 +2992:1:2989 +2993:1:2990 +2994:1:2988 +2995:1:2989 +2996:1:2990 +2997:1:3001 +2998:1:3008 +2999:1:3012 +3000:0:4533 +3001:1:11 +3002:0:4533 +3003:2:3975 +3004:2:3976 +3005:2:3980 +3006:2:3981 +3007:2:3989 +3008:2:3990 +3009:2:3994 +3010:2:3995 +3011:2:4003 +3012:2:4008 +3013:2:4012 +3014:2:4013 +3015:2:4021 +3016:2:4022 +3017:2:4026 +3018:2:4027 +3019:2:4021 +3020:2:4022 +3021:2:4026 +3022:2:4027 +3023:2:4035 +3024:2:4040 +3025:2:4041 +3026:2:4052 +3027:2:4060 +3028:2:4061 +3029:2:4065 +3030:2:4070 +3031:2:4071 +3032:2:4082 +3033:2:4083 +3034:2:4084 +3035:2:4082 +3036:2:4083 +3037:2:4084 +3038:2:4095 +3039:2:4103 +3040:0:4533 +3041:2:3127 +3042:0:4533 +3043:2:4109 +3044:2:4110 +3045:2:4114 +3046:2:4115 +3047:2:4123 +3048:2:4124 +3049:2:4128 +3050:2:4129 +3051:2:4137 +3052:2:4142 +3053:2:4146 +3054:2:4147 +3055:2:4155 +3056:2:4156 +3057:2:4160 +3058:2:4161 +3059:2:4155 +3060:2:4156 +3061:2:4160 +3062:2:4161 +3063:2:4169 +3064:2:4174 +3065:2:4175 +3066:2:4186 +3067:2:4194 +3068:2:4195 +3069:2:4199 +3070:2:4204 +3071:2:4205 +3072:2:4216 +3073:2:4217 +3074:2:4218 +3075:2:4216 +3076:2:4217 +3077:2:4218 +3078:2:4229 +3079:0:4533 +3080:2:3127 +3081:0:4533 +3082:1:3013 +3083:0:4533 +3084:1:3021 +3085:0:4533 +3086:1:3109 +3087:0:4533 +3088:1:9 +3089:0:4533 +3090:2:3975 +3091:2:3976 +3092:2:3980 +3093:2:3981 +3094:2:3989 +3095:2:3990 +3096:2:3994 +3097:2:3995 +3098:2:4003 +3099:2:4008 +3100:2:4012 +3101:2:4013 +3102:2:4021 +3103:2:4022 +3104:2:4026 +3105:2:4027 +3106:2:4021 +3107:2:4022 +3108:2:4026 +3109:2:4027 +3110:2:4035 +3111:2:4040 +3112:2:4041 +3113:2:4052 +3114:2:4060 +3115:2:4061 +3116:2:4065 +3117:2:4070 +3118:2:4071 +3119:2:4082 +3120:2:4083 +3121:2:4084 +3122:2:4082 +3123:2:4083 +3124:2:4084 +3125:2:4095 +3126:2:4103 +3127:0:4533 +3128:2:3127 +3129:0:4533 +3130:2:4109 +3131:2:4110 +3132:2:4114 +3133:2:4115 +3134:2:4123 +3135:2:4124 +3136:2:4128 +3137:2:4129 +3138:2:4137 +3139:2:4142 +3140:2:4146 +3141:2:4147 +3142:2:4155 +3143:2:4156 +3144:2:4160 +3145:2:4161 +3146:2:4155 +3147:2:4156 +3148:2:4160 +3149:2:4161 +3150:2:4169 +3151:2:4174 +3152:2:4175 +3153:2:4186 +3154:2:4194 +3155:2:4195 +3156:2:4199 +3157:2:4204 +3158:2:4205 +3159:2:4216 +3160:2:4217 +3161:2:4218 +3162:2:4216 +3163:2:4217 +3164:2:4218 +3165:2:4229 +3166:0:4533 +3167:2:3127 +3168:0:4533 +3169:1:10 +3170:0:4533 +3171:1:11 +3172:0:4533 +3173:2:3975 +3174:2:3976 +3175:2:3980 +3176:2:3981 +3177:2:3989 +3178:2:3990 +3179:2:3994 +3180:2:3995 +3181:2:4003 +3182:2:4008 +3183:2:4012 +3184:2:4013 +3185:2:4021 +3186:2:4022 +3187:2:4026 +3188:2:4027 +3189:2:4021 +3190:2:4022 +3191:2:4026 +3192:2:4027 +3193:2:4035 +3194:2:4040 +3195:2:4041 +3196:2:4052 +3197:2:4060 +3198:2:4061 +3199:2:4065 +3200:2:4070 +3201:2:4071 +3202:2:4082 +3203:2:4083 +3204:2:4084 +3205:2:4082 +3206:2:4083 +3207:2:4084 +3208:2:4095 +3209:2:4103 +3210:0:4533 +3211:2:3127 +3212:0:4533 +3213:2:4109 +3214:2:4110 +3215:2:4114 +3216:2:4115 +3217:2:4123 +3218:2:4124 +3219:2:4128 +3220:2:4129 +3221:2:4137 +3222:2:4142 +3223:2:4146 +3224:2:4147 +3225:2:4155 +3226:2:4156 +3227:2:4160 +3228:2:4161 +3229:2:4155 +3230:2:4156 +3231:2:4160 +3232:2:4161 +3233:2:4169 +3234:2:4174 +3235:2:4175 +3236:2:4186 +3237:2:4194 +3238:2:4195 +3239:2:4199 +3240:2:4204 +3241:2:4205 +3242:2:4216 +3243:2:4217 +3244:2:4218 +3245:2:4216 +3246:2:4217 +3247:2:4218 +3248:2:4229 +3249:0:4533 +3250:2:3127 +3251:0:4533 +3252:1:12 +3253:1:13 +3254:1:17 +3255:1:18 +3256:1:26 +3257:1:27 +3258:1:28 +3259:1:40 +3260:1:45 +3261:1:49 +3262:1:50 +3263:1:58 +3264:1:59 +3265:1:63 +3266:1:64 +3267:1:58 +3268:1:59 +3269:1:63 +3270:1:64 +3271:1:72 +3272:1:77 +3273:1:78 +3274:1:89 +3275:1:90 +3276:1:91 +3277:1:102 +3278:1:107 +3279:1:108 +3280:1:119 +3281:1:120 +3282:1:121 +3283:1:119 +3284:1:120 +3285:1:121 +3286:1:132 +3287:0:4533 +3288:1:11 +3289:0:4533 +3290:2:3975 +3291:2:3976 +3292:2:3980 +3293:2:3981 +3294:2:3989 +3295:2:3990 +3296:2:3994 +3297:2:3995 +3298:2:4003 +3299:2:4008 +3300:2:4012 +3301:2:4013 +3302:2:4021 +3303:2:4022 +3304:2:4026 +3305:2:4027 +3306:2:4021 +3307:2:4022 +3308:2:4026 +3309:2:4027 +3310:2:4035 +3311:2:4040 +3312:2:4041 +3313:2:4052 +3314:2:4060 +3315:2:4061 +3316:2:4065 +3317:2:4070 +3318:2:4071 +3319:2:4082 +3320:2:4083 +3321:2:4084 +3322:2:4082 +3323:2:4083 +3324:2:4084 +3325:2:4095 +3326:2:4103 +3327:0:4533 +3328:2:3127 +3329:0:4533 +3330:2:4109 +3331:2:4110 +3332:2:4114 +3333:2:4115 +3334:2:4123 +3335:2:4124 +3336:2:4128 +3337:2:4129 +3338:2:4137 +3339:2:4142 +3340:2:4146 +3341:2:4147 +3342:2:4155 +3343:2:4156 +3344:2:4160 +3345:2:4161 +3346:2:4155 +3347:2:4156 +3348:2:4160 +3349:2:4161 +3350:2:4169 +3351:2:4174 +3352:2:4175 +3353:2:4186 +3354:2:4194 +3355:2:4195 +3356:2:4199 +3357:2:4204 +3358:2:4205 +3359:2:4216 +3360:2:4217 +3361:2:4218 +3362:2:4216 +3363:2:4217 +3364:2:4218 +3365:2:4229 +3366:0:4533 +3367:2:3127 +3368:0:4533 +3369:1:141 +3370:1:142 +3371:0:4533 +3372:1:11 +3373:0:4533 +3374:2:3975 +3375:2:3976 +3376:2:3980 +3377:2:3981 +3378:2:3989 +3379:2:3990 +3380:2:3994 +3381:2:3995 +3382:2:4003 +3383:2:4008 +3384:2:4012 +3385:2:4013 +3386:2:4021 +3387:2:4022 +3388:2:4026 +3389:2:4027 +3390:2:4021 +3391:2:4022 +3392:2:4026 +3393:2:4027 +3394:2:4035 +3395:2:4040 +3396:2:4041 +3397:2:4052 +3398:2:4060 +3399:2:4061 +3400:2:4065 +3401:2:4070 +3402:2:4071 +3403:2:4082 +3404:2:4083 +3405:2:4084 +3406:2:4082 +3407:2:4083 +3408:2:4084 +3409:2:4095 +3410:2:4103 +3411:0:4533 +3412:2:3127 +3413:0:4533 +3414:2:4109 +3415:2:4110 +3416:2:4114 +3417:2:4115 +3418:2:4123 +3419:2:4124 +3420:2:4128 +3421:2:4129 +3422:2:4137 +3423:2:4142 +3424:2:4146 +3425:2:4147 +3426:2:4155 +3427:2:4156 +3428:2:4160 +3429:2:4161 +3430:2:4155 +3431:2:4156 +3432:2:4160 +3433:2:4161 +3434:2:4169 +3435:2:4174 +3436:2:4175 +3437:2:4186 +3438:2:4194 +3439:2:4195 +3440:2:4199 +3441:2:4204 +3442:2:4205 +3443:2:4216 +3444:2:4217 +3445:2:4218 +3446:2:4216 +3447:2:4217 +3448:2:4218 +3449:2:4229 +3450:0:4533 +3451:2:3127 +3452:0:4533 +3453:1:148 +3454:1:149 +3455:1:153 +3456:1:154 +3457:1:162 +3458:1:163 +3459:1:167 +3460:1:168 +3461:1:176 +3462:1:181 +3463:1:185 +3464:1:186 +3465:1:194 +3466:1:195 +3467:1:199 +3468:1:200 +3469:1:194 +3470:1:195 +3471:1:199 +3472:1:200 +3473:1:208 +3474:1:213 +3475:1:214 +3476:1:225 +3477:1:226 +3478:1:227 +3479:1:238 +3480:1:243 +3481:1:244 +3482:1:255 +3483:1:256 +3484:1:257 +3485:1:255 +3486:1:256 +3487:1:257 +3488:1:268 +3489:0:4533 +3490:1:11 +3491:0:4533 +3492:2:3975 +3493:2:3976 +3494:2:3980 +3495:2:3981 +3496:2:3989 +3497:2:3990 +3498:2:3994 +3499:2:3995 +3500:2:4003 +3501:2:4008 +3502:2:4012 +3503:2:4013 +3504:2:4021 +3505:2:4022 +3506:2:4026 +3507:2:4027 +3508:2:4021 +3509:2:4022 +3510:2:4026 +3511:2:4027 +3512:2:4035 +3513:2:4040 +3514:2:4041 +3515:2:4052 +3516:2:4060 +3517:2:4061 +3518:2:4065 +3519:2:4070 +3520:2:4071 +3521:2:4082 +3522:2:4083 +3523:2:4084 +3524:2:4082 +3525:2:4083 +3526:2:4084 +3527:2:4095 +3528:2:4103 +3529:0:4533 +3530:2:3127 +3531:0:4533 +3532:2:4109 +3533:2:4110 +3534:2:4114 +3535:2:4115 +3536:2:4123 +3537:2:4124 +3538:2:4128 +3539:2:4129 +3540:2:4137 +3541:2:4142 +3542:2:4146 +3543:2:4147 +3544:2:4155 +3545:2:4156 +3546:2:4160 +3547:2:4161 +3548:2:4155 +3549:2:4156 +3550:2:4160 +3551:2:4161 +3552:2:4169 +3553:2:4174 +3554:2:4175 +3555:2:4186 +3556:2:4194 +3557:2:4195 +3558:2:4199 +3559:2:4204 +3560:2:4205 +3561:2:4216 +3562:2:4217 +3563:2:4218 +3564:2:4216 +3565:2:4217 +3566:2:4218 +3567:2:4229 +3568:0:4533 +3569:2:3127 +3570:0:4533 +3571:1:277 +3572:1:278 +3573:1:282 +3574:1:283 +3575:1:291 +3576:1:292 +3577:1:296 +3578:1:297 +3579:1:305 +3580:1:310 +3581:1:314 +3582:1:315 +3583:1:323 +3584:1:324 +3585:1:328 +3586:1:329 +3587:1:323 +3588:1:324 +3589:1:328 +3590:1:329 +3591:1:337 +3592:1:342 +3593:1:343 +3594:1:354 +3595:1:355 +3596:1:356 +3597:1:367 +3598:1:372 +3599:1:373 +3600:1:384 +3601:1:385 +3602:1:386 +3603:1:384 +3604:1:385 +3605:1:386 +3606:1:397 +3607:1:404 +3608:0:4533 +3609:1:11 +3610:0:4533 +3611:2:3975 +3612:2:3976 +3613:2:3980 +3614:2:3981 +3615:2:3989 +3616:2:3990 +3617:2:3994 +3618:2:3995 +3619:2:4003 +3620:2:4008 +3621:2:4012 +3622:2:4013 +3623:2:4021 +3624:2:4022 +3625:2:4026 +3626:2:4027 +3627:2:4021 +3628:2:4022 +3629:2:4026 +3630:2:4027 +3631:2:4035 +3632:2:4040 +3633:2:4041 +3634:2:4052 +3635:2:4060 +3636:2:4061 +3637:2:4065 +3638:2:4070 +3639:2:4071 +3640:2:4082 +3641:2:4083 +3642:2:4084 +3643:2:4082 +3644:2:4083 +3645:2:4084 +3646:2:4095 +3647:2:4103 +3648:0:4533 +3649:2:3127 +3650:0:4533 +3651:2:4109 +3652:2:4110 +3653:2:4114 +3654:2:4115 +3655:2:4123 +3656:2:4124 +3657:2:4128 +3658:2:4129 +3659:2:4137 +3660:2:4142 +3661:2:4146 +3662:2:4147 +3663:2:4155 +3664:2:4156 +3665:2:4160 +3666:2:4161 +3667:2:4155 +3668:2:4156 +3669:2:4160 +3670:2:4161 +3671:2:4169 +3672:2:4174 +3673:2:4175 +3674:2:4186 +3675:2:4194 +3676:2:4195 +3677:2:4199 +3678:2:4204 +3679:2:4205 +3680:2:4216 +3681:2:4217 +3682:2:4218 +3683:2:4216 +3684:2:4217 +3685:2:4218 +3686:2:4229 +3687:0:4533 +3688:2:3127 +3689:0:4533 +3690:1:540 +3691:1:544 +3692:1:545 +3693:1:549 +3694:1:550 +3695:1:558 +3696:1:566 +3697:1:567 +3698:1:571 +3699:1:575 +3700:1:576 +3701:1:571 +3702:1:575 +3703:1:576 +3704:1:580 +3705:1:587 +3706:1:594 +3707:1:595 +3708:1:602 +3709:1:607 +3710:1:614 +3711:1:615 +3712:1:614 +3713:1:615 +3714:1:622 +3715:0:4533 +3716:1:11 +3717:0:4533 +3718:2:3975 +3719:2:3976 +3720:2:3980 +3721:2:3981 +3722:2:3989 +3723:2:3990 +3724:2:3994 +3725:2:3995 +3726:2:4003 +3727:2:4008 +3728:2:4012 +3729:2:4013 +3730:2:4021 +3731:2:4022 +3732:2:4026 +3733:2:4027 +3734:2:4021 +3735:2:4022 +3736:2:4026 +3737:2:4027 +3738:2:4035 +3739:2:4040 +3740:2:4041 +3741:2:4052 +3742:2:4060 +3743:2:4061 +3744:2:4065 +3745:2:4070 +3746:2:4071 +3747:2:4082 +3748:2:4083 +3749:2:4084 +3750:2:4082 +3751:2:4083 +3752:2:4084 +3753:2:4095 +3754:2:4103 +3755:0:4533 +3756:2:3127 +3757:0:4533 +3758:2:4109 +3759:2:4110 +3760:2:4114 +3761:2:4115 +3762:2:4123 +3763:2:4124 +3764:2:4128 +3765:2:4129 +3766:2:4137 +3767:2:4142 +3768:2:4146 +3769:2:4147 +3770:2:4155 +3771:2:4156 +3772:2:4160 +3773:2:4161 +3774:2:4155 +3775:2:4156 +3776:2:4160 +3777:2:4161 +3778:2:4169 +3779:2:4174 +3780:2:4175 +3781:2:4186 +3782:2:4194 +3783:2:4195 +3784:2:4199 +3785:2:4204 +3786:2:4205 +3787:2:4216 +3788:2:4217 +3789:2:4218 +3790:2:4216 +3791:2:4217 +3792:2:4218 +3793:2:4229 +3794:0:4533 +3795:2:3127 +3796:0:4533 +3797:1:632 +3798:1:633 +3799:1:637 +3800:1:638 +3801:1:646 +3802:1:647 +3803:1:651 +3804:1:652 +3805:1:660 +3806:1:665 +3807:1:669 +3808:1:670 +3809:1:678 +3810:1:679 +3811:1:683 +3812:1:684 +3813:1:678 +3814:1:679 +3815:1:683 +3816:1:684 +3817:1:692 +3818:1:697 +3819:1:698 +3820:1:709 +3821:1:710 +3822:1:711 +3823:1:722 +3824:1:727 +3825:1:728 +3826:1:739 +3827:1:740 +3828:1:741 +3829:1:739 +3830:1:740 +3831:1:741 +3832:1:752 +3833:0:4533 +3834:1:11 +3835:0:4533 +3836:2:3975 +3837:2:3976 +3838:2:3980 +3839:2:3981 +3840:2:3989 +3841:2:3990 +3842:2:3994 +3843:2:3995 +3844:2:4003 +3845:2:4008 +3846:2:4012 +3847:2:4013 +3848:2:4021 +3849:2:4022 +3850:2:4026 +3851:2:4027 +3852:2:4021 +3853:2:4022 +3854:2:4026 +3855:2:4027 +3856:2:4035 +3857:2:4040 +3858:2:4041 +3859:2:4052 +3860:2:4060 +3861:2:4061 +3862:2:4065 +3863:2:4070 +3864:2:4071 +3865:2:4082 +3866:2:4083 +3867:2:4084 +3868:2:4082 +3869:2:4083 +3870:2:4084 +3871:2:4095 +3872:2:4103 +3873:0:4533 +3874:2:3127 +3875:0:4533 +3876:2:4109 +3877:2:4110 +3878:2:4114 +3879:2:4115 +3880:2:4123 +3881:2:4124 +3882:2:4128 +3883:2:4129 +3884:2:4137 +3885:2:4142 +3886:2:4146 +3887:2:4147 +3888:2:4155 +3889:2:4156 +3890:2:4160 +3891:2:4161 +3892:2:4155 +3893:2:4156 +3894:2:4160 +3895:2:4161 +3896:2:4169 +3897:2:4174 +3898:2:4175 +3899:2:4186 +3900:2:4194 +3901:2:4195 +3902:2:4199 +3903:2:4204 +3904:2:4205 +3905:2:4216 +3906:2:4217 +3907:2:4218 +3908:2:4216 +3909:2:4217 +3910:2:4218 +3911:2:4229 +3912:0:4533 +3913:2:3127 +3914:0:4533 +3915:1:761 +3916:1:764 +3917:1:765 +3918:0:4533 +3919:1:11 +3920:0:4533 +3921:2:3975 +3922:2:3976 +3923:2:3980 +3924:2:3981 +3925:2:3989 +3926:2:3990 +3927:2:3994 +3928:2:3995 +3929:2:4003 +3930:2:4008 +3931:2:4012 +3932:2:4013 +3933:2:4021 +3934:2:4022 +3935:2:4026 +3936:2:4027 +3937:2:4021 +3938:2:4022 +3939:2:4026 +3940:2:4027 +3941:2:4035 +3942:2:4040 +3943:2:4041 +3944:2:4052 +3945:2:4060 +3946:2:4061 +3947:2:4065 +3948:2:4070 +3949:2:4071 +3950:2:4082 +3951:2:4083 +3952:2:4084 +3953:2:4082 +3954:2:4083 +3955:2:4084 +3956:2:4095 +3957:2:4103 +3958:0:4533 +3959:2:3127 +3960:0:4533 +3961:2:4109 +3962:2:4110 +3963:2:4114 +3964:2:4115 +3965:2:4123 +3966:2:4124 +3967:2:4128 +3968:2:4129 +3969:2:4137 +3970:2:4142 +3971:2:4146 +3972:2:4147 +3973:2:4155 +3974:2:4156 +3975:2:4160 +3976:2:4161 +3977:2:4155 +3978:2:4156 +3979:2:4160 +3980:2:4161 +3981:2:4169 +3982:2:4174 +3983:2:4175 +3984:2:4186 +3985:2:4194 +3986:2:4195 +3987:2:4199 +3988:2:4204 +3989:2:4205 +3990:2:4216 +3991:2:4217 +3992:2:4218 +3993:2:4216 +3994:2:4217 +3995:2:4218 +3996:2:4229 +3997:0:4533 +3998:2:3127 +3999:0:4533 +4000:1:1028 +4001:1:1029 +4002:1:1033 +4003:1:1034 +4004:1:1042 +4005:1:1043 +4006:1:1047 +4007:1:1048 +4008:1:1056 +4009:1:1061 +4010:1:1065 +4011:1:1066 +4012:1:1074 +4013:1:1075 +4014:1:1079 +4015:1:1080 +4016:1:1074 +4017:1:1075 +4018:1:1079 +4019:1:1080 +4020:1:1088 +4021:1:1093 +4022:1:1094 +4023:1:1105 +4024:1:1106 +4025:1:1107 +4026:1:1118 +4027:1:1123 +4028:1:1124 +4029:1:1135 +4030:1:1136 +4031:1:1137 +4032:1:1135 +4033:1:1136 +4034:1:1137 +4035:1:1148 +4036:1:1155 +4037:1:1159 +4038:0:4533 +4039:1:11 +4040:0:4533 +4041:2:3975 +4042:2:3976 +4043:2:3980 +4044:2:3981 +4045:2:3989 +4046:2:3990 +4047:2:3994 +4048:2:3995 +4049:2:4003 +4050:2:4008 +4051:2:4012 +4052:2:4013 +4053:2:4021 +4054:2:4022 +4055:2:4026 +4056:2:4027 +4057:2:4021 +4058:2:4022 +4059:2:4026 +4060:2:4027 +4061:2:4035 +4062:2:4040 +4063:2:4041 +4064:2:4052 +4065:2:4060 +4066:2:4061 +4067:2:4065 +4068:2:4070 +4069:2:4071 +4070:2:4082 +4071:2:4083 +4072:2:4084 +4073:2:4082 +4074:2:4083 +4075:2:4084 +4076:2:4095 +4077:2:4103 +4078:0:4533 +4079:2:3127 +4080:0:4533 +4081:2:4109 +4082:2:4110 +4083:2:4114 +4084:2:4115 +4085:2:4123 +4086:2:4124 +4087:2:4128 +4088:2:4129 +4089:2:4137 +4090:2:4142 +4091:2:4146 +4092:2:4147 +4093:2:4155 +4094:2:4156 +4095:2:4160 +4096:2:4161 +4097:2:4155 +4098:2:4156 +4099:2:4160 +4100:2:4161 +4101:2:4169 +4102:2:4174 +4103:2:4175 +4104:2:4186 +4105:2:4194 +4106:2:4195 +4107:2:4199 +4108:2:4204 +4109:2:4205 +4110:2:4216 +4111:2:4217 +4112:2:4218 +4113:2:4216 +4114:2:4217 +4115:2:4218 +4116:2:4229 +4117:0:4533 +4118:2:3127 +4119:0:4533 +4120:1:1160 +4121:1:1161 +4122:1:1165 +4123:1:1166 +4124:1:1174 +4125:1:1175 +4126:1:1176 +4127:1:1188 +4128:1:1193 +4129:1:1197 +4130:1:1198 +4131:1:1206 +4132:1:1207 +4133:1:1211 +4134:1:1212 +4135:1:1206 +4136:1:1207 +4137:1:1211 +4138:1:1212 +4139:1:1220 +4140:1:1225 +4141:1:1226 +4142:1:1237 +4143:1:1238 +4144:1:1239 +4145:1:1250 +4146:1:1255 +4147:1:1256 +4148:1:1267 +4149:1:1268 +4150:1:1269 +4151:1:1267 +4152:1:1268 +4153:1:1269 +4154:1:1280 +4155:0:4533 +4156:1:11 +4157:0:4533 +4158:2:3975 +4159:2:3976 +4160:2:3980 +4161:2:3981 +4162:2:3989 +4163:2:3990 +4164:2:3994 +4165:2:3995 +4166:2:4003 +4167:2:4008 +4168:2:4012 +4169:2:4013 +4170:2:4021 +4171:2:4022 +4172:2:4026 +4173:2:4027 +4174:2:4021 +4175:2:4022 +4176:2:4026 +4177:2:4027 +4178:2:4035 +4179:2:4040 +4180:2:4041 +4181:2:4052 +4182:2:4060 +4183:2:4061 +4184:2:4065 +4185:2:4070 +4186:2:4071 +4187:2:4082 +4188:2:4083 +4189:2:4084 +4190:2:4082 +4191:2:4083 +4192:2:4084 +4193:2:4095 +4194:2:4103 +4195:0:4533 +4196:2:3127 +4197:0:4533 +4198:2:4109 +4199:2:4110 +4200:2:4114 +4201:2:4115 +4202:2:4123 +4203:2:4124 +4204:2:4128 +4205:2:4129 +4206:2:4137 +4207:2:4142 +4208:2:4146 +4209:2:4147 +4210:2:4155 +4211:2:4156 +4212:2:4160 +4213:2:4161 +4214:2:4155 +4215:2:4156 +4216:2:4160 +4217:2:4161 +4218:2:4169 +4219:2:4174 +4220:2:4175 +4221:2:4186 +4222:2:4194 +4223:2:4195 +4224:2:4199 +4225:2:4204 +4226:2:4205 +4227:2:4216 +4228:2:4217 +4229:2:4218 +4230:2:4216 +4231:2:4217 +4232:2:4218 +4233:2:4229 +4234:0:4533 +4235:2:3127 +4236:0:4533 +4237:1:1289 +4238:0:4533 +4239:2:3975 +4240:2:3976 +4241:2:3980 +4242:2:3981 +4243:2:3989 +4244:2:3990 +4245:2:3994 +4246:2:3995 +4247:2:4003 +4248:2:4008 +4249:2:4012 +4250:2:4013 +4251:2:4021 +4252:2:4022 +4253:2:4026 +4254:2:4027 +4255:2:4021 +4256:2:4022 +4257:2:4026 +4258:2:4027 +4259:2:4035 +4260:2:4040 +4261:2:4041 +4262:2:4052 +4263:2:4060 +4264:2:4061 +4265:2:4065 +4266:2:4070 +4267:2:4071 +4268:2:4082 +4269:2:4083 +4270:2:4084 +4271:2:4082 +4272:2:4083 +4273:2:4084 +4274:2:4095 +4275:2:4103 +4276:0:4533 +4277:2:3127 +4278:0:4533 +4279:2:4109 +4280:2:4110 +4281:2:4114 +4282:2:4115 +4283:2:4123 +4284:2:4124 +4285:2:4128 +4286:2:4129 +4287:2:4137 +4288:2:4142 +4289:2:4146 +4290:2:4147 +4291:2:4155 +4292:2:4156 +4293:2:4160 +4294:2:4161 +4295:2:4155 +4296:2:4156 +4297:2:4160 +4298:2:4161 +4299:2:4169 +4300:2:4174 +4301:2:4175 +4302:2:4186 +4303:2:4194 +4304:2:4195 +4305:2:4199 +4306:2:4204 +4307:2:4205 +4308:2:4216 +4309:2:4217 +4310:2:4218 +4311:2:4216 +4312:2:4217 +4313:2:4218 +4314:2:4229 +4315:0:4533 +4316:2:3127 +4317:0:4533 +4318:1:3023 +4319:1:3030 +4320:1:3031 +4321:1:3038 +4322:1:3043 +4323:1:3050 +4324:1:3051 +4325:1:3050 +4326:1:3051 +4327:1:3058 +4328:1:3062 +4329:0:4533 +4330:2:3975 +4331:2:3976 +4332:2:3980 +4333:2:3981 +4334:2:3989 +4335:2:3990 +4336:2:3994 +4337:2:3995 +4338:2:4003 +4339:2:4008 +4340:2:4012 +4341:2:4013 +4342:2:4021 +4343:2:4022 +4344:2:4026 +4345:2:4027 +4346:2:4021 +4347:2:4022 +4348:2:4026 +4349:2:4027 +4350:2:4035 +4351:2:4040 +4352:2:4041 +4353:2:4052 +4354:2:4060 +4355:2:4061 +4356:2:4065 +4357:2:4070 +4358:2:4071 +4359:2:4082 +4360:2:4083 +4361:2:4084 +4362:2:4082 +4363:2:4083 +4364:2:4084 +4365:2:4095 +4366:2:4103 +4367:0:4533 +4368:2:3127 +4369:0:4533 +4370:2:4109 +4371:2:4110 +4372:2:4114 +4373:2:4115 +4374:2:4123 +4375:2:4124 +4376:2:4128 +4377:2:4129 +4378:2:4137 +4379:2:4142 +4380:2:4146 +4381:2:4147 +4382:2:4155 +4383:2:4156 +4384:2:4160 +4385:2:4161 +4386:2:4155 +4387:2:4156 +4388:2:4160 +4389:2:4161 +4390:2:4169 +4391:2:4174 +4392:2:4175 +4393:2:4186 +4394:2:4194 +4395:2:4195 +4396:2:4199 +4397:2:4204 +4398:2:4205 +4399:2:4216 +4400:2:4217 +4401:2:4218 +4402:2:4216 +4403:2:4217 +4404:2:4218 +4405:2:4229 +4406:0:4533 +4407:2:3127 +4408:0:4533 +4409:1:1291 +4410:1:1292 +4411:0:4533 +4412:1:11 +4413:0:4533 +4414:2:3975 +4415:2:3976 +4416:2:3980 +4417:2:3981 +4418:2:3989 +4419:2:3990 +4420:2:3994 +4421:2:3995 +4422:2:4003 +4423:2:4008 +4424:2:4012 +4425:2:4013 +4426:2:4021 +4427:2:4022 +4428:2:4026 +4429:2:4027 +4430:2:4021 +4431:2:4022 +4432:2:4026 +4433:2:4027 +4434:2:4035 +4435:2:4040 +4436:2:4041 +4437:2:4052 +4438:2:4060 +4439:2:4061 +4440:2:4065 +4441:2:4070 +4442:2:4071 +4443:2:4082 +4444:2:4083 +4445:2:4084 +4446:2:4082 +4447:2:4083 +4448:2:4084 +4449:2:4095 +4450:2:4103 +4451:0:4533 +4452:2:3127 +4453:0:4533 +4454:2:4109 +4455:2:4110 +4456:2:4114 +4457:2:4115 +4458:2:4123 +4459:2:4124 +4460:2:4128 +4461:2:4129 +4462:2:4137 +4463:2:4142 +4464:2:4146 +4465:2:4147 +4466:2:4155 +4467:2:4156 +4468:2:4160 +4469:2:4161 +4470:2:4155 +4471:2:4156 +4472:2:4160 +4473:2:4161 +4474:2:4169 +4475:2:4174 +4476:2:4175 +4477:2:4186 +4478:2:4194 +4479:2:4195 +4480:2:4199 +4481:2:4204 +4482:2:4205 +4483:2:4216 +4484:2:4217 +4485:2:4218 +4486:2:4216 +4487:2:4217 +4488:2:4218 +4489:2:4229 +4490:0:4533 +4491:2:3127 +4492:0:4533 +4493:1:1293 +4494:1:1294 +4495:1:1298 +4496:1:1299 +4497:1:1307 +4498:1:1308 +4499:1:1312 +4500:1:1313 +4501:1:1321 +4502:1:1326 +4503:1:1330 +4504:1:1331 +4505:1:1339 +4506:1:1340 +4507:1:1344 +4508:1:1345 +4509:1:1339 +4510:1:1340 +4511:1:1344 +4512:1:1345 +4513:1:1353 +4514:1:1358 +4515:1:1359 +4516:1:1370 +4517:1:1371 +4518:1:1372 +4519:1:1383 +4520:1:1388 +4521:1:1389 +4522:1:1400 +4523:1:1401 +4524:1:1402 +4525:1:1400 +4526:1:1401 +4527:1:1402 +4528:1:1413 +4529:0:4533 +4530:1:11 +4531:0:4533 +4532:2:3975 +4533:2:3976 +4534:2:3980 +4535:2:3981 +4536:2:3989 +4537:2:3990 +4538:2:3994 +4539:2:3995 +4540:2:4003 +4541:2:4008 +4542:2:4012 +4543:2:4013 +4544:2:4021 +4545:2:4022 +4546:2:4026 +4547:2:4027 +4548:2:4021 +4549:2:4022 +4550:2:4026 +4551:2:4027 +4552:2:4035 +4553:2:4040 +4554:2:4041 +4555:2:4052 +4556:2:4060 +4557:2:4061 +4558:2:4065 +4559:2:4070 +4560:2:4071 +4561:2:4082 +4562:2:4083 +4563:2:4084 +4564:2:4082 +4565:2:4083 +4566:2:4084 +4567:2:4095 +4568:2:4103 +4569:0:4533 +4570:2:3127 +4571:0:4533 +4572:2:4109 +4573:2:4110 +4574:2:4114 +4575:2:4115 +4576:2:4123 +4577:2:4124 +4578:2:4128 +4579:2:4129 +4580:2:4137 +4581:2:4142 +4582:2:4146 +4583:2:4147 +4584:2:4155 +4585:2:4156 +4586:2:4160 +4587:2:4161 +4588:2:4155 +4589:2:4156 +4590:2:4160 +4591:2:4161 +4592:2:4169 +4593:2:4174 +4594:2:4175 +4595:2:4186 +4596:2:4194 +4597:2:4195 +4598:2:4199 +4599:2:4204 +4600:2:4205 +4601:2:4216 +4602:2:4217 +4603:2:4218 +4604:2:4216 +4605:2:4217 +4606:2:4218 +4607:2:4229 +4608:0:4533 +4609:2:3127 +4610:0:4533 +4611:1:1422 +4612:1:1423 +4613:1:1427 +4614:1:1428 +4615:1:1436 +4616:1:1437 +4617:1:1441 +4618:1:1442 +4619:1:1450 +4620:1:1455 +4621:1:1459 +4622:1:1460 +4623:1:1468 +4624:1:1469 +4625:1:1473 +4626:1:1474 +4627:1:1468 +4628:1:1469 +4629:1:1473 +4630:1:1474 +4631:1:1482 +4632:1:1487 +4633:1:1488 +4634:1:1499 +4635:1:1500 +4636:1:1501 +4637:1:1512 +4638:1:1517 +4639:1:1518 +4640:1:1529 +4641:1:1530 +4642:1:1531 +4643:1:1529 +4644:1:1530 +4645:1:1531 +4646:1:1542 +4647:1:1549 +4648:1:1553 +4649:0:4533 +4650:1:11 +4651:0:4533 +4652:2:3975 +4653:2:3976 +4654:2:3980 +4655:2:3981 +4656:2:3989 +4657:2:3990 +4658:2:3994 +4659:2:3995 +4660:2:4003 +4661:2:4008 +4662:2:4012 +4663:2:4013 +4664:2:4021 +4665:2:4022 +4666:2:4026 +4667:2:4027 +4668:2:4021 +4669:2:4022 +4670:2:4026 +4671:2:4027 +4672:2:4035 +4673:2:4040 +4674:2:4041 +4675:2:4052 +4676:2:4060 +4677:2:4061 +4678:2:4065 +4679:2:4070 +4680:2:4071 +4681:2:4082 +4682:2:4083 +4683:2:4084 +4684:2:4082 +4685:2:4083 +4686:2:4084 +4687:2:4095 +4688:2:4103 +4689:0:4533 +4690:2:3127 +4691:0:4533 +4692:2:4109 +4693:2:4110 +4694:2:4114 +4695:2:4115 +4696:2:4123 +4697:2:4124 +4698:2:4128 +4699:2:4129 +4700:2:4137 +4701:2:4142 +4702:2:4146 +4703:2:4147 +4704:2:4155 +4705:2:4156 +4706:2:4160 +4707:2:4161 +4708:2:4155 +4709:2:4156 +4710:2:4160 +4711:2:4161 +4712:2:4169 +4713:2:4174 +4714:2:4175 +4715:2:4186 +4716:2:4194 +4717:2:4195 +4718:2:4199 +4719:2:4204 +4720:2:4205 +4721:2:4216 +4722:2:4217 +4723:2:4218 +4724:2:4216 +4725:2:4217 +4726:2:4218 +4727:2:4229 +4728:0:4533 +4729:2:3127 +4730:0:4533 +4731:1:1554 +4732:1:1558 +4733:1:1559 +4734:1:1563 +4735:1:1564 +4736:1:1572 +4737:1:1580 +4738:1:1581 +4739:1:1585 +4740:1:1589 +4741:1:1590 +4742:1:1585 +4743:1:1589 +4744:1:1590 +4745:1:1594 +4746:1:1601 +4747:1:1608 +4748:1:1609 +4749:1:1616 +4750:1:1621 +4751:1:1628 +4752:1:1629 +4753:1:1628 +4754:1:1629 +4755:1:1636 +4756:0:4533 +4757:1:11 +4758:0:4533 +4759:2:3975 +4760:2:3976 +4761:2:3980 +4762:2:3981 +4763:2:3989 +4764:2:3990 +4765:2:3994 +4766:2:3995 +4767:2:4003 +4768:2:4008 +4769:2:4012 +4770:2:4013 +4771:2:4021 +4772:2:4022 +4773:2:4026 +4774:2:4027 +4775:2:4021 +4776:2:4022 +4777:2:4026 +4778:2:4027 +4779:2:4035 +4780:2:4040 +4781:2:4041 +4782:2:4052 +4783:2:4060 +4784:2:4061 +4785:2:4065 +4786:2:4070 +4787:2:4071 +4788:2:4082 +4789:2:4083 +4790:2:4084 +4791:2:4082 +4792:2:4083 +4793:2:4084 +4794:2:4095 +4795:2:4103 +4796:0:4533 +4797:2:3127 +4798:0:4533 +4799:2:4109 +4800:2:4110 +4801:2:4114 +4802:2:4115 +4803:2:4123 +4804:2:4124 +4805:2:4128 +4806:2:4129 +4807:2:4137 +4808:2:4142 +4809:2:4146 +4810:2:4147 +4811:2:4155 +4812:2:4156 +4813:2:4160 +4814:2:4161 +4815:2:4155 +4816:2:4156 +4817:2:4160 +4818:2:4161 +4819:2:4169 +4820:2:4174 +4821:2:4175 +4822:2:4186 +4823:2:4194 +4824:2:4195 +4825:2:4199 +4826:2:4204 +4827:2:4205 +4828:2:4216 +4829:2:4217 +4830:2:4218 +4831:2:4216 +4832:2:4217 +4833:2:4218 +4834:2:4229 +4835:0:4533 +4836:2:3127 +4837:0:4533 +4838:1:1646 +4839:1:1647 +4840:1:1651 +4841:1:1652 +4842:1:1660 +4843:1:1661 +4844:1:1665 +4845:1:1666 +4846:1:1674 +4847:1:1679 +4848:1:1683 +4849:1:1684 +4850:1:1692 +4851:1:1693 +4852:1:1697 +4853:1:1698 +4854:1:1692 +4855:1:1693 +4856:1:1697 +4857:1:1698 +4858:1:1706 +4859:1:1711 +4860:1:1712 +4861:1:1723 +4862:1:1724 +4863:1:1725 +4864:1:1736 +4865:1:1741 +4866:1:1742 +4867:1:1753 +4868:1:1754 +4869:1:1755 +4870:1:1753 +4871:1:1754 +4872:1:1755 +4873:1:1766 +4874:0:4533 +4875:1:11 +4876:0:4533 +4877:2:3975 +4878:2:3976 +4879:2:3980 +4880:2:3981 +4881:2:3989 +4882:2:3990 +4883:2:3994 +4884:2:3995 +4885:2:4003 +4886:2:4008 +4887:2:4012 +4888:2:4013 +4889:2:4021 +4890:2:4022 +4891:2:4026 +4892:2:4027 +4893:2:4021 +4894:2:4022 +4895:2:4026 +4896:2:4027 +4897:2:4035 +4898:2:4040 +4899:2:4041 +4900:2:4052 +4901:2:4060 +4902:2:4061 +4903:2:4065 +4904:2:4070 +4905:2:4071 +4906:2:4082 +4907:2:4083 +4908:2:4084 +4909:2:4082 +4910:2:4083 +4911:2:4084 +4912:2:4095 +4913:2:4103 +4914:0:4533 +4915:2:3127 +4916:0:4533 +4917:2:4109 +4918:2:4110 +4919:2:4114 +4920:2:4115 +4921:2:4123 +4922:2:4124 +4923:2:4128 +4924:2:4129 +4925:2:4137 +4926:2:4142 +4927:2:4146 +4928:2:4147 +4929:2:4155 +4930:2:4156 +4931:2:4160 +4932:2:4161 +4933:2:4155 +4934:2:4156 +4935:2:4160 +4936:2:4161 +4937:2:4169 +4938:2:4174 +4939:2:4175 +4940:2:4186 +4941:2:4194 +4942:2:4195 +4943:2:4199 +4944:2:4204 +4945:2:4205 +4946:2:4216 +4947:2:4217 +4948:2:4218 +4949:2:4216 +4950:2:4217 +4951:2:4218 +4952:2:4229 +4953:0:4533 +4954:2:3127 +4955:0:4533 +4956:1:1775 +4957:1:1776 +4958:1:1780 +4959:1:1781 +4960:1:1789 +4961:1:1790 +4962:1:1794 +4963:1:1795 +4964:1:1803 +4965:1:1808 +4966:1:1812 +4967:1:1813 +4968:1:1821 +4969:1:1822 +4970:1:1826 +4971:1:1827 +4972:1:1821 +4973:1:1822 +4974:1:1826 +4975:1:1827 +4976:1:1835 +4977:1:1840 +4978:1:1841 +4979:1:1852 +4980:1:1853 +4981:1:1854 +4982:1:1865 +4983:1:1870 +4984:1:1871 +4985:1:1882 +4986:1:1883 +4987:1:1884 +4988:1:1882 +4989:1:1883 +4990:1:1884 +4991:1:1895 +4992:1:1902 +4993:1:1906 +4994:0:4533 +4995:1:11 +4996:0:4533 +4997:2:3975 +4998:2:3976 +4999:2:3980 +5000:2:3981 +5001:2:3989 +5002:2:3990 +5003:2:3994 +5004:2:3995 +5005:2:4003 +5006:2:4008 +5007:2:4012 +5008:2:4013 +5009:2:4021 +5010:2:4022 +5011:2:4026 +5012:2:4027 +5013:2:4021 +5014:2:4022 +5015:2:4026 +5016:2:4027 +5017:2:4035 +5018:2:4040 +5019:2:4041 +5020:2:4052 +5021:2:4060 +5022:2:4061 +5023:2:4065 +5024:2:4070 +5025:2:4071 +5026:2:4082 +5027:2:4083 +5028:2:4084 +5029:2:4082 +5030:2:4083 +5031:2:4084 +5032:2:4095 +5033:2:4103 +5034:0:4533 +5035:2:3127 +5036:0:4533 +5037:2:4109 +5038:2:4110 +5039:2:4114 +5040:2:4115 +5041:2:4123 +5042:2:4124 +5043:2:4128 +5044:2:4129 +5045:2:4137 +5046:2:4142 +5047:2:4146 +5048:2:4147 +5049:2:4155 +5050:2:4156 +5051:2:4160 +5052:2:4161 +5053:2:4155 +5054:2:4156 +5055:2:4160 +5056:2:4161 +5057:2:4169 +5058:2:4174 +5059:2:4175 +5060:2:4186 +5061:2:4194 +5062:2:4195 +5063:2:4199 +5064:2:4204 +5065:2:4205 +5066:2:4216 +5067:2:4217 +5068:2:4218 +5069:2:4216 +5070:2:4217 +5071:2:4218 +5072:2:4229 +5073:0:4533 +5074:2:3127 +5075:0:4533 +5076:1:1907 +5077:1:1908 +5078:1:1912 +5079:1:1913 +5080:1:1921 +5081:1:1922 +5082:1:1923 +5083:1:1935 +5084:1:1940 +5085:1:1944 +5086:1:1945 +5087:1:1953 +5088:1:1954 +5089:1:1958 +5090:1:1959 +5091:1:1953 +5092:1:1954 +5093:1:1958 +5094:1:1959 +5095:1:1967 +5096:1:1972 +5097:1:1973 +5098:1:1984 +5099:1:1985 +5100:1:1986 +5101:1:1997 +5102:1:2002 +5103:1:2003 +5104:1:2014 +5105:1:2015 +5106:1:2016 +5107:1:2014 +5108:1:2015 +5109:1:2016 +5110:1:2027 +5111:0:4533 +5112:1:11 +5113:0:4533 +5114:2:3975 +5115:2:3976 +5116:2:3980 +5117:2:3981 +5118:2:3989 +5119:2:3990 +5120:2:3994 +5121:2:3995 +5122:2:4003 +5123:2:4008 +5124:2:4012 +5125:2:4013 +5126:2:4021 +5127:2:4022 +5128:2:4026 +5129:2:4027 +5130:2:4021 +5131:2:4022 +5132:2:4026 +5133:2:4027 +5134:2:4035 +5135:2:4040 +5136:2:4041 +5137:2:4052 +5138:2:4060 +5139:2:4061 +5140:2:4065 +5141:2:4070 +5142:2:4071 +5143:2:4082 +5144:2:4083 +5145:2:4084 +5146:2:4082 +5147:2:4083 +5148:2:4084 +5149:2:4095 +5150:2:4103 +5151:0:4533 +5152:2:3127 +5153:0:4533 +5154:2:4109 +5155:2:4110 +5156:2:4114 +5157:2:4115 +5158:2:4123 +5159:2:4124 +5160:2:4128 +5161:2:4129 +5162:2:4137 +5163:2:4142 +5164:2:4146 +5165:2:4147 +5166:2:4155 +5167:2:4156 +5168:2:4160 +5169:2:4161 +5170:2:4155 +5171:2:4156 +5172:2:4160 +5173:2:4161 +5174:2:4169 +5175:2:4174 +5176:2:4175 +5177:2:4186 +5178:2:4194 +5179:2:4195 +5180:2:4199 +5181:2:4204 +5182:2:4205 +5183:2:4216 +5184:2:4217 +5185:2:4218 +5186:2:4216 +5187:2:4217 +5188:2:4218 +5189:2:4229 +5190:0:4533 +5191:2:3127 +5192:0:4533 +5193:1:2036 +5194:1:2037 +5195:0:4533 +5196:1:11 +5197:0:4533 +5198:2:3975 +5199:2:3976 +5200:2:3980 +5201:2:3981 +5202:2:3989 +5203:2:3990 +5204:2:3994 +5205:2:3995 +5206:2:4003 +5207:2:4008 +5208:2:4012 +5209:2:4013 +5210:2:4021 +5211:2:4022 +5212:2:4026 +5213:2:4027 +5214:2:4021 +5215:2:4022 +5216:2:4026 +5217:2:4027 +5218:2:4035 +5219:2:4040 +5220:2:4041 +5221:2:4052 +5222:2:4060 +5223:2:4061 +5224:2:4065 +5225:2:4070 +5226:2:4071 +5227:2:4082 +5228:2:4083 +5229:2:4084 +5230:2:4082 +5231:2:4083 +5232:2:4084 +5233:2:4095 +5234:2:4103 +5235:0:4533 +5236:2:3127 +5237:0:4533 +5238:2:4109 +5239:2:4110 +5240:2:4114 +5241:2:4115 +5242:2:4123 +5243:2:4124 +5244:2:4128 +5245:2:4129 +5246:2:4137 +5247:2:4142 +5248:2:4146 +5249:2:4147 +5250:2:4155 +5251:2:4156 +5252:2:4160 +5253:2:4161 +5254:2:4155 +5255:2:4156 +5256:2:4160 +5257:2:4161 +5258:2:4169 +5259:2:4174 +5260:2:4175 +5261:2:4186 +5262:2:4194 +5263:2:4195 +5264:2:4199 +5265:2:4204 +5266:2:4205 +5267:2:4216 +5268:2:4217 +5269:2:4218 +5270:2:4216 +5271:2:4217 +5272:2:4218 +5273:2:4229 +5274:0:4533 +5275:2:3127 +5276:0:4533 +5277:1:2043 +5278:1:2044 +5279:1:2048 +5280:1:2049 +5281:1:2057 +5282:1:2058 +5283:1:2062 +5284:1:2063 +5285:1:2071 +5286:1:2076 +5287:1:2080 +5288:1:2081 +5289:1:2089 +5290:1:2090 +5291:1:2094 +5292:1:2095 +5293:1:2089 +5294:1:2090 +5295:1:2094 +5296:1:2095 +5297:1:2103 +5298:1:2108 +5299:1:2109 +5300:1:2120 +5301:1:2121 +5302:1:2122 +5303:1:2133 +5304:1:2138 +5305:1:2139 +5306:1:2150 +5307:1:2151 +5308:1:2152 +5309:1:2150 +5310:1:2151 +5311:1:2152 +5312:1:2163 +5313:0:4533 +5314:1:11 +5315:0:4533 +5316:2:3975 +5317:2:3976 +5318:2:3980 +5319:2:3981 +5320:2:3989 +5321:2:3990 +5322:2:3994 +5323:2:3995 +5324:2:4003 +5325:2:4008 +5326:2:4012 +5327:2:4013 +5328:2:4021 +5329:2:4022 +5330:2:4026 +5331:2:4027 +5332:2:4021 +5333:2:4022 +5334:2:4026 +5335:2:4027 +5336:2:4035 +5337:2:4040 +5338:2:4041 +5339:2:4052 +5340:2:4060 +5341:2:4061 +5342:2:4065 +5343:2:4070 +5344:2:4071 +5345:2:4082 +5346:2:4083 +5347:2:4084 +5348:2:4082 +5349:2:4083 +5350:2:4084 +5351:2:4095 +5352:2:4103 +5353:0:4533 +5354:2:3127 +5355:0:4533 +5356:2:4109 +5357:2:4110 +5358:2:4114 +5359:2:4115 +5360:2:4123 +5361:2:4124 +5362:2:4128 +5363:2:4129 +5364:2:4137 +5365:2:4142 +5366:2:4146 +5367:2:4147 +5368:2:4155 +5369:2:4156 +5370:2:4160 +5371:2:4161 +5372:2:4155 +5373:2:4156 +5374:2:4160 +5375:2:4161 +5376:2:4169 +5377:2:4174 +5378:2:4175 +5379:2:4186 +5380:2:4194 +5381:2:4195 +5382:2:4199 +5383:2:4204 +5384:2:4205 +5385:2:4216 +5386:2:4217 +5387:2:4218 +5388:2:4216 +5389:2:4217 +5390:2:4218 +5391:2:4229 +5392:0:4533 +5393:2:3127 +5394:0:4533 +5395:1:2172 +5396:1:2173 +5397:1:2177 +5398:1:2178 +5399:1:2186 +5400:1:2187 +5401:1:2191 +5402:1:2192 +5403:1:2200 +5404:1:2205 +5405:1:2209 +5406:1:2210 +5407:1:2218 +5408:1:2219 +5409:1:2223 +5410:1:2224 +5411:1:2218 +5412:1:2219 +5413:1:2223 +5414:1:2224 +5415:1:2232 +5416:1:2237 +5417:1:2238 +5418:1:2249 +5419:1:2250 +5420:1:2251 +5421:1:2262 +5422:1:2267 +5423:1:2268 +5424:1:2279 +5425:1:2280 +5426:1:2281 +5427:1:2279 +5428:1:2280 +5429:1:2281 +5430:1:2292 +5431:1:2299 +5432:0:4533 +5433:1:11 +5434:0:4533 +5435:2:3975 +5436:2:3976 +5437:2:3980 +5438:2:3981 +5439:2:3989 +5440:2:3990 +5441:2:3994 +5442:2:3995 +5443:2:4003 +5444:2:4008 +5445:2:4012 +5446:2:4013 +5447:2:4021 +5448:2:4022 +5449:2:4026 +5450:2:4027 +5451:2:4021 +5452:2:4022 +5453:2:4026 +5454:2:4027 +5455:2:4035 +5456:2:4040 +5457:2:4041 +5458:2:4052 +5459:2:4060 +5460:2:4061 +5461:2:4065 +5462:2:4070 +5463:2:4071 +5464:2:4082 +5465:2:4083 +5466:2:4084 +5467:2:4082 +5468:2:4083 +5469:2:4084 +5470:2:4095 +5471:2:4103 +5472:0:4533 +5473:2:3127 +5474:0:4533 +5475:2:4109 +5476:2:4110 +5477:2:4114 +5478:2:4115 +5479:2:4123 +5480:2:4124 +5481:2:4128 +5482:2:4129 +5483:2:4137 +5484:2:4142 +5485:2:4146 +5486:2:4147 +5487:2:4155 +5488:2:4156 +5489:2:4160 +5490:2:4161 +5491:2:4155 +5492:2:4156 +5493:2:4160 +5494:2:4161 +5495:2:4169 +5496:2:4174 +5497:2:4175 +5498:2:4186 +5499:2:4194 +5500:2:4195 +5501:2:4199 +5502:2:4204 +5503:2:4205 +5504:2:4216 +5505:2:4217 +5506:2:4218 +5507:2:4216 +5508:2:4217 +5509:2:4218 +5510:2:4229 +5511:0:4533 +5512:2:3127 +5513:0:4533 +5514:1:2435 +5515:1:2439 +5516:1:2440 +5517:1:2444 +5518:1:2445 +5519:1:2453 +5520:1:2461 +5521:1:2462 +5522:1:2466 +5523:1:2470 +5524:1:2471 +5525:1:2466 +5526:1:2470 +5527:1:2471 +5528:1:2475 +5529:1:2482 +5530:1:2489 +5531:1:2490 +5532:1:2497 +5533:1:2502 +5534:1:2509 +5535:1:2510 +5536:1:2509 +5537:1:2510 +5538:1:2517 +5539:0:4533 +5540:1:11 +5541:0:4533 +5542:2:3975 +5543:2:3976 +5544:2:3980 +5545:2:3981 +5546:2:3989 +5547:2:3990 +5548:2:3994 +5549:2:3995 +5550:2:4003 +5551:2:4008 +5552:2:4012 +5553:2:4013 +5554:2:4021 +5555:2:4022 +5556:2:4026 +5557:2:4027 +5558:2:4021 +5559:2:4022 +5560:2:4026 +5561:2:4027 +5562:2:4035 +5563:2:4040 +5564:2:4041 +5565:2:4052 +5566:2:4060 +5567:2:4061 +5568:2:4065 +5569:2:4070 +5570:2:4071 +5571:2:4082 +5572:2:4083 +5573:2:4084 +5574:2:4082 +5575:2:4083 +5576:2:4084 +5577:2:4095 +5578:2:4103 +5579:0:4533 +5580:2:3127 +5581:0:4533 +5582:2:4109 +5583:2:4110 +5584:2:4114 +5585:2:4115 +5586:2:4123 +5587:2:4124 +5588:2:4128 +5589:2:4129 +5590:2:4137 +5591:2:4142 +5592:2:4146 +5593:2:4147 +5594:2:4155 +5595:2:4156 +5596:2:4160 +5597:2:4161 +5598:2:4155 +5599:2:4156 +5600:2:4160 +5601:2:4161 +5602:2:4169 +5603:2:4174 +5604:2:4175 +5605:2:4186 +5606:2:4194 +5607:2:4195 +5608:2:4199 +5609:2:4204 +5610:2:4205 +5611:2:4216 +5612:2:4217 +5613:2:4218 +5614:2:4216 +5615:2:4217 +5616:2:4218 +5617:2:4229 +5618:0:4533 +5619:2:3127 +5620:0:4533 +5621:1:2527 +5622:1:2528 +5623:1:2532 +5624:1:2533 +5625:1:2541 +5626:1:2542 +5627:1:2546 +5628:1:2547 +5629:1:2555 +5630:1:2560 +5631:1:2564 +5632:1:2565 +5633:1:2573 +5634:1:2574 +5635:1:2578 +5636:1:2579 +5637:1:2573 +5638:1:2574 +5639:1:2578 +5640:1:2579 +5641:1:2587 +5642:1:2592 +5643:1:2593 +5644:1:2604 +5645:1:2605 +5646:1:2606 +5647:1:2617 +5648:1:2622 +5649:1:2623 +5650:1:2634 +5651:1:2635 +5652:1:2636 +5653:1:2634 +5654:1:2635 +5655:1:2636 +5656:1:2647 +5657:0:4533 +5658:1:11 +5659:0:4533 +5660:2:3975 +5661:2:3976 +5662:2:3980 +5663:2:3981 +5664:2:3989 +5665:2:3990 +5666:2:3994 +5667:2:3995 +5668:2:4003 +5669:2:4008 +5670:2:4012 +5671:2:4013 +5672:2:4021 +5673:2:4022 +5674:2:4026 +5675:2:4027 +5676:2:4021 +5677:2:4022 +5678:2:4026 +5679:2:4027 +5680:2:4035 +5681:2:4040 +5682:2:4041 +5683:2:4052 +5684:2:4060 +5685:2:4061 +5686:2:4065 +5687:2:4070 +5688:2:4071 +5689:2:4082 +5690:2:4083 +5691:2:4084 +5692:2:4082 +5693:2:4083 +5694:2:4084 +5695:2:4095 +5696:2:4103 +5697:0:4533 +5698:2:3127 +5699:0:4533 +5700:2:4109 +5701:2:4110 +5702:2:4114 +5703:2:4115 +5704:2:4123 +5705:2:4124 +5706:2:4128 +5707:2:4129 +5708:2:4137 +5709:2:4142 +5710:2:4146 +5711:2:4147 +5712:2:4155 +5713:2:4156 +5714:2:4160 +5715:2:4161 +5716:2:4155 +5717:2:4156 +5718:2:4160 +5719:2:4161 +5720:2:4169 +5721:2:4174 +5722:2:4175 +5723:2:4186 +5724:2:4194 +5725:2:4195 +5726:2:4199 +5727:2:4204 +5728:2:4205 +5729:2:4216 +5730:2:4217 +5731:2:4218 +5732:2:4216 +5733:2:4217 +5734:2:4218 +5735:2:4229 +5736:0:4533 +5737:2:3127 +5738:0:4533 +5739:1:2656 +5740:0:4533 +5741:2:3975 +5742:2:3976 +5743:2:3980 +5744:2:3981 +5745:2:3989 +5746:2:3990 +5747:2:3994 +5748:2:3995 +5749:2:4003 +5750:2:4008 +5751:2:4012 +5752:2:4013 +5753:2:4021 +5754:2:4022 +5755:2:4026 +5756:2:4027 +5757:2:4021 +5758:2:4022 +5759:2:4026 +5760:2:4027 +5761:2:4035 +5762:2:4040 +5763:2:4041 +5764:2:4052 +5765:2:4060 +5766:2:4061 +5767:2:4065 +5768:2:4070 +5769:2:4071 +5770:2:4082 +5771:2:4083 +5772:2:4084 +5773:2:4082 +5774:2:4083 +5775:2:4084 +5776:2:4095 +5777:2:4103 +5778:0:4533 +5779:2:3127 +5780:0:4533 +5781:2:4109 +5782:2:4110 +5783:2:4114 +5784:2:4115 +5785:2:4123 +5786:2:4124 +5787:2:4128 +5788:2:4129 +5789:2:4137 +5790:2:4142 +5791:2:4146 +5792:2:4147 +5793:2:4155 +5794:2:4156 +5795:2:4160 +5796:2:4161 +5797:2:4155 +5798:2:4156 +5799:2:4160 +5800:2:4161 +5801:2:4169 +5802:2:4174 +5803:2:4175 +5804:2:4186 +5805:2:4194 +5806:2:4195 +5807:2:4199 +5808:2:4204 +5809:2:4205 +5810:2:4216 +5811:2:4217 +5812:2:4218 +5813:2:4216 +5814:2:4217 +5815:2:4218 +5816:2:4229 +5817:0:4533 +5818:2:3127 +5819:0:4533 +5820:1:3066 +5821:1:3073 +5822:1:3074 +5823:1:3081 +5824:1:3086 +5825:1:3093 +5826:1:3094 +5827:1:3093 +5828:1:3094 +5829:1:3101 +5830:1:3105 +5831:0:4533 +5832:2:3975 +5833:2:3976 +5834:2:3980 +5835:2:3981 +5836:2:3989 +5837:2:3990 +5838:2:3994 +5839:2:3995 +5840:2:4003 +5841:2:4008 +5842:2:4012 +5843:2:4013 +5844:2:4021 +5845:2:4022 +5846:2:4026 +5847:2:4027 +5848:2:4021 +5849:2:4022 +5850:2:4026 +5851:2:4027 +5852:2:4035 +5853:2:4040 +5854:2:4041 +5855:2:4052 +5856:2:4060 +5857:2:4061 +5858:2:4065 +5859:2:4070 +5860:2:4071 +5861:2:4082 +5862:2:4083 +5863:2:4084 +5864:2:4082 +5865:2:4083 +5866:2:4084 +5867:2:4095 +5868:2:4103 +5869:0:4533 +5870:2:3127 +5871:0:4533 +5872:2:4109 +5873:2:4110 +5874:2:4114 +5875:2:4115 +5876:2:4123 +5877:2:4124 +5878:2:4128 +5879:2:4129 +5880:2:4137 +5881:2:4142 +5882:2:4146 +5883:2:4147 +5884:2:4155 +5885:2:4156 +5886:2:4160 +5887:2:4161 +5888:2:4155 +5889:2:4156 +5890:2:4160 +5891:2:4161 +5892:2:4169 +5893:2:4174 +5894:2:4175 +5895:2:4186 +5896:2:4194 +5897:2:4195 +5898:2:4199 +5899:2:4204 +5900:2:4205 +5901:2:4216 +5902:2:4217 +5903:2:4218 +5904:2:4216 +5905:2:4217 +5906:2:4218 +5907:2:4229 +5908:0:4533 +5909:2:3127 +5910:0:4533 +5911:1:2658 +5912:1:2659 +5913:0:4533 +5914:1:11 +5915:0:4533 +5916:2:3975 +5917:2:3976 +5918:2:3980 +5919:2:3981 +5920:2:3989 +5921:2:3990 +5922:2:3994 +5923:2:3995 +5924:2:4003 +5925:2:4008 +5926:2:4012 +5927:2:4013 +5928:2:4021 +5929:2:4022 +5930:2:4026 +5931:2:4027 +5932:2:4021 +5933:2:4022 +5934:2:4026 +5935:2:4027 +5936:2:4035 +5937:2:4040 +5938:2:4041 +5939:2:4052 +5940:2:4060 +5941:2:4061 +5942:2:4065 +5943:2:4070 +5944:2:4071 +5945:2:4082 +5946:2:4083 +5947:2:4084 +5948:2:4082 +5949:2:4083 +5950:2:4084 +5951:2:4095 +5952:2:4103 +5953:0:4533 +5954:2:3127 +5955:0:4533 +5956:2:4109 +5957:2:4110 +5958:2:4114 +5959:2:4115 +5960:2:4123 +5961:2:4124 +5962:2:4128 +5963:2:4129 +5964:2:4137 +5965:2:4142 +5966:2:4146 +5967:2:4147 +5968:2:4155 +5969:2:4156 +5970:2:4160 +5971:2:4161 +5972:2:4155 +5973:2:4156 +5974:2:4160 +5975:2:4161 +5976:2:4169 +5977:2:4174 +5978:2:4175 +5979:2:4186 +5980:2:4194 +5981:2:4195 +5982:2:4199 +5983:2:4204 +5984:2:4205 +5985:2:4216 +5986:2:4217 +5987:2:4218 +5988:2:4216 +5989:2:4217 +5990:2:4218 +5991:2:4229 +5992:0:4533 +5993:2:3127 +5994:0:4533 +5995:1:2660 +5996:1:2664 +5997:1:2665 +5998:1:2669 +5999:1:2673 +6000:1:2674 +6001:1:2678 +6002:1:2686 +6003:1:2687 +6004:1:2691 +6005:1:2695 +6006:1:2696 +6007:1:2691 +6008:1:2695 +6009:1:2696 +6010:1:2700 +6011:1:2707 +6012:1:2714 +6013:1:2715 +6014:1:2722 +6015:1:2727 +6016:1:2734 +6017:1:2735 +6018:1:2734 +6019:1:2735 +6020:1:2742 +6021:0:4533 +6022:1:11 +6023:0:4533 +6024:2:3975 +6025:2:3976 +6026:2:3980 +6027:2:3981 +6028:2:3989 +6029:2:3990 +6030:2:3994 +6031:2:3995 +6032:2:4003 +6033:2:4008 +6034:2:4012 +6035:2:4013 +6036:2:4021 +6037:2:4022 +6038:2:4026 +6039:2:4027 +6040:2:4021 +6041:2:4022 +6042:2:4026 +6043:2:4027 +6044:2:4035 +6045:2:4040 +6046:2:4041 +6047:2:4052 +6048:2:4060 +6049:2:4061 +6050:2:4065 +6051:2:4070 +6052:2:4071 +6053:2:4082 +6054:2:4083 +6055:2:4084 +6056:2:4082 +6057:2:4083 +6058:2:4084 +6059:2:4095 +6060:2:4103 +6061:0:4533 +6062:2:3127 +6063:0:4533 +6064:2:4109 +6065:2:4110 +6066:2:4114 +6067:2:4115 +6068:2:4123 +6069:2:4124 +6070:2:4128 +6071:2:4129 +6072:2:4137 +6073:2:4142 +6074:2:4146 +6075:2:4147 +6076:2:4155 +6077:2:4156 +6078:2:4160 +6079:2:4161 +6080:2:4155 +6081:2:4156 +6082:2:4160 +6083:2:4161 +6084:2:4169 +6085:2:4174 +6086:2:4175 +6087:2:4186 +6088:2:4194 +6089:2:4195 +6090:2:4199 +6091:2:4204 +6092:2:4205 +6093:2:4216 +6094:2:4217 +6095:2:4218 +6096:2:4216 +6097:2:4217 +6098:2:4218 +6099:2:4229 +6100:0:4533 +6101:2:3127 +6102:0:4533 +6103:1:2752 +6104:1:2753 +6105:1:2757 +6106:1:2758 +6107:1:2766 +6108:1:2767 +6109:1:2771 +6110:1:2772 +6111:1:2780 +6112:1:2785 +6113:1:2789 +6114:1:2790 +6115:1:2798 +6116:1:2799 +6117:1:2803 +6118:1:2804 +6119:1:2798 +6120:1:2799 +6121:1:2803 +6122:1:2804 +6123:1:2812 +6124:1:2817 +6125:1:2818 +6126:1:2829 +6127:1:2830 +6128:1:2831 +6129:1:2842 +6130:1:2847 +6131:1:2848 +6132:1:2859 +6133:1:2860 +6134:1:2861 +6135:1:2859 +6136:1:2860 +6137:1:2861 +6138:1:2872 +6139:0:4533 +6140:1:11 +6141:0:4533 +6142:2:3975 +6143:2:3976 +6144:2:3980 +6145:2:3981 +6146:2:3989 +6147:2:3990 +6148:2:3994 +6149:2:3995 +6150:2:4003 +6151:2:4008 +6152:2:4012 +6153:2:4013 +6154:2:4021 +6155:2:4022 +6156:2:4026 +6157:2:4027 +6158:2:4021 +6159:2:4022 +6160:2:4026 +6161:2:4027 +6162:2:4035 +6163:2:4040 +6164:2:4041 +6165:2:4052 +6166:2:4060 +6167:2:4061 +6168:2:4065 +6169:2:4070 +6170:2:4071 +6171:2:4082 +6172:2:4083 +6173:2:4084 +6174:2:4082 +6175:2:4083 +6176:2:4084 +6177:2:4095 +6178:2:4103 +6179:0:4533 +6180:2:3127 +6181:0:4533 +6182:2:4109 +6183:2:4110 +6184:2:4114 +6185:2:4115 +6186:2:4123 +6187:2:4124 +6188:2:4128 +6189:2:4129 +6190:2:4137 +6191:2:4142 +6192:2:4146 +6193:2:4147 +6194:2:4155 +6195:2:4156 +6196:2:4160 +6197:2:4161 +6198:2:4155 +6199:2:4156 +6200:2:4160 +6201:2:4161 +6202:2:4169 +6203:2:4174 +6204:2:4175 +6205:2:4186 +6206:2:4194 +6207:2:4195 +6208:2:4199 +6209:2:4204 +6210:2:4205 +6211:2:4216 +6212:2:4217 +6213:2:4218 +6214:2:4216 +6215:2:4217 +6216:2:4218 +6217:2:4229 +6218:0:4533 +6219:2:3127 +6220:0:4533 +6221:1:2881 +6222:1:2882 +6223:1:2886 +6224:1:2887 +6225:1:2895 +6226:1:2896 +6227:1:2900 +6228:1:2901 +6229:1:2909 +6230:1:2914 +6231:1:2918 +6232:1:2919 +6233:1:2927 +6234:1:2928 +6235:1:2932 +6236:1:2933 +6237:1:2927 +6238:1:2928 +6239:1:2932 +6240:1:2933 +6241:1:2941 +6242:1:2946 +6243:1:2947 +6244:1:2958 +6245:1:2959 +6246:1:2960 +6247:1:2971 +6248:1:2976 +6249:1:2977 +6250:1:2988 +6251:1:2989 +6252:1:2990 +6253:1:2988 +6254:1:2989 +6255:1:2990 +6256:1:3001 +6257:1:3008 +6258:1:3012 +6259:0:4533 +6260:1:11 +6261:0:4533 +6262:2:3975 +6263:2:3976 +6264:2:3980 +6265:2:3981 +6266:2:3989 +6267:2:3990 +6268:2:3994 +6269:2:3995 +6270:2:4003 +6271:2:4008 +6272:2:4012 +6273:2:4013 +6274:2:4021 +6275:2:4022 +6276:2:4026 +6277:2:4027 +6278:2:4021 +6279:2:4022 +6280:2:4026 +6281:2:4027 +6282:2:4035 +6283:2:4040 +6284:2:4041 +6285:2:4052 +6286:2:4060 +6287:2:4061 +6288:2:4065 +6289:2:4070 +6290:2:4071 +6291:2:4082 +6292:2:4083 +6293:2:4084 +6294:2:4082 +6295:2:4083 +6296:2:4084 +6297:2:4095 +6298:2:4103 +6299:0:4533 +6300:2:3127 +6301:0:4533 +6302:2:4109 +6303:2:4110 +6304:2:4114 +6305:2:4115 +6306:2:4123 +6307:2:4124 +6308:2:4128 +6309:2:4129 +6310:2:4137 +6311:2:4142 +6312:2:4146 +6313:2:4147 +6314:2:4155 +6315:2:4156 +6316:2:4160 +6317:2:4161 +6318:2:4155 +6319:2:4156 +6320:2:4160 +6321:2:4161 +6322:2:4169 +6323:2:4174 +6324:2:4175 +6325:2:4186 +6326:2:4194 +6327:2:4195 +6328:2:4199 +6329:2:4204 +6330:2:4205 +6331:2:4216 +6332:2:4217 +6333:2:4218 +6334:2:4216 +6335:2:4217 +6336:2:4218 +6337:2:4229 +6338:0:4533 +6339:2:3127 +6340:0:4533 +6341:1:3013 +6342:0:4533 +6343:1:3021 +6344:0:4533 +6345:1:3109 +6346:0:4533 +6347:1:9 +6348:0:4533 +6349:2:3975 +6350:2:3976 +6351:2:3980 +6352:2:3981 +6353:2:3989 +6354:2:3990 +6355:2:3994 +6356:2:3995 +6357:2:4003 +6358:2:4008 +6359:2:4012 +6360:2:4013 +6361:2:4021 +6362:2:4022 +6363:2:4026 +6364:2:4027 +6365:2:4021 +6366:2:4022 +6367:2:4026 +6368:2:4027 +6369:2:4035 +6370:2:4040 +6371:2:4041 +6372:2:4052 +6373:2:4060 +6374:2:4061 +6375:2:4065 +6376:2:4070 +6377:2:4071 +6378:2:4082 +6379:2:4083 +6380:2:4084 +6381:2:4082 +6382:2:4083 +6383:2:4084 +6384:2:4095 +6385:2:4103 +6386:0:4533 +6387:2:3127 +6388:0:4533 +6389:2:4109 +6390:2:4110 +6391:2:4114 +6392:2:4115 +6393:2:4123 +6394:2:4124 +6395:2:4128 +6396:2:4129 +6397:2:4137 +6398:2:4142 +6399:2:4146 +6400:2:4147 +6401:2:4155 +6402:2:4156 +6403:2:4160 +6404:2:4161 +6405:2:4155 +6406:2:4156 +6407:2:4160 +6408:2:4161 +6409:2:4169 +6410:2:4174 +6411:2:4175 +6412:2:4186 +6413:2:4194 +6414:2:4195 +6415:2:4199 +6416:2:4204 +6417:2:4205 +6418:2:4216 +6419:2:4217 +6420:2:4218 +6421:2:4216 +6422:2:4217 +6423:2:4218 +6424:2:4229 +6425:0:4533 +6426:2:3127 +6427:0:4533 +6428:1:10 +6429:0:4533 +6430:1:11 +6431:0:4533 +6432:2:3975 +6433:2:3976 +6434:2:3980 +6435:2:3981 +6436:2:3989 +6437:2:3990 +6438:2:3994 +6439:2:3995 +6440:2:4003 +6441:2:4008 +6442:2:4012 +6443:2:4013 +6444:2:4021 +6445:2:4022 +6446:2:4026 +6447:2:4027 +6448:2:4021 +6449:2:4022 +6450:2:4026 +6451:2:4027 +6452:2:4035 +6453:2:4040 +6454:2:4041 +6455:2:4052 +6456:2:4060 +6457:2:4061 +6458:2:4065 +6459:2:4070 +6460:2:4071 +6461:2:4082 +6462:2:4083 +6463:2:4084 +6464:2:4082 +6465:2:4083 +6466:2:4084 +6467:2:4095 +6468:2:4103 +6469:0:4533 +6470:2:3127 +6471:0:4533 +6472:2:4109 +6473:2:4110 +6474:2:4114 +6475:2:4115 +6476:2:4123 +6477:2:4124 +6478:2:4128 +6479:2:4129 +6480:2:4137 +6481:2:4142 +6482:2:4146 +6483:2:4147 +6484:2:4155 +6485:2:4156 +6486:2:4160 +6487:2:4161 +6488:2:4155 +6489:2:4156 +6490:2:4160 +6491:2:4161 +6492:2:4169 +6493:2:4174 +6494:2:4175 +6495:2:4186 +6496:2:4194 +6497:2:4195 +6498:2:4199 +6499:2:4204 +6500:2:4205 +6501:2:4216 +6502:2:4217 +6503:2:4218 +6504:2:4216 +6505:2:4217 +6506:2:4218 +6507:2:4229 +6508:0:4533 +6509:2:3127 +6510:0:4533 +6511:1:12 +6512:1:13 +6513:1:17 +6514:1:18 +6515:1:26 +6516:1:35 +6517:1:36 +6518:1:40 +6519:1:45 +6520:1:49 +6521:1:50 +6522:1:58 +6523:1:59 +6524:1:63 +6525:1:64 +6526:1:58 +6527:1:59 +6528:1:63 +6529:1:64 +6530:1:72 +6531:1:77 +6532:1:78 +6533:1:89 +6534:1:90 +6535:1:93 +6536:1:94 +6537:1:102 +6538:1:107 +6539:1:108 +6540:1:119 +6541:1:120 +6542:1:121 +6543:1:119 +6544:1:120 +6545:1:121 +6546:1:132 +6547:0:4533 +6548:1:11 +6549:0:4533 +6550:2:3975 +6551:2:3976 +6552:2:3980 +6553:2:3981 +6554:2:3989 +6555:2:3990 +6556:2:3994 +6557:2:3995 +6558:2:4003 +6559:2:4008 +6560:2:4012 +6561:2:4013 +6562:2:4021 +6563:2:4022 +6564:2:4026 +6565:2:4027 +6566:2:4021 +6567:2:4022 +6568:2:4026 +6569:2:4027 +6570:2:4035 +6571:2:4040 +6572:2:4041 +6573:2:4052 +6574:2:4060 +6575:2:4061 +6576:2:4065 +6577:2:4070 +6578:2:4071 +6579:2:4082 +6580:2:4083 +6581:2:4084 +6582:2:4082 +6583:2:4083 +6584:2:4084 +6585:2:4095 +6586:2:4103 +6587:0:4533 +6588:2:3127 +6589:0:4533 +6590:2:4109 +6591:2:4110 +6592:2:4114 +6593:2:4115 +6594:2:4123 +6595:2:4124 +6596:2:4128 +6597:2:4129 +6598:2:4137 +6599:2:4142 +6600:2:4146 +6601:2:4147 +6602:2:4155 +6603:2:4156 +6604:2:4160 +6605:2:4161 +6606:2:4155 +6607:2:4156 +6608:2:4160 +6609:2:4161 +6610:2:4169 +6611:2:4174 +6612:2:4175 +6613:2:4186 +6614:2:4194 +6615:2:4195 +6616:2:4199 +6617:2:4204 +6618:2:4205 +6619:2:4216 +6620:2:4217 +6621:2:4218 +6622:2:4216 +6623:2:4217 +6624:2:4218 +6625:2:4229 +6626:0:4533 +6627:2:3127 +6628:0:4533 +6629:1:141 +6630:1:142 +6631:0:4533 +6632:1:11 +6633:0:4533 +6634:2:3975 +6635:2:3976 +6636:2:3980 +6637:2:3981 +6638:2:3989 +6639:2:3990 +6640:2:3994 +6641:2:3995 +6642:2:4003 +6643:2:4008 +6644:2:4012 +6645:2:4013 +6646:2:4021 +6647:2:4022 +6648:2:4026 +6649:2:4027 +6650:2:4021 +6651:2:4022 +6652:2:4026 +6653:2:4027 +6654:2:4035 +6655:2:4040 +6656:2:4041 +6657:2:4052 +6658:2:4060 +6659:2:4061 +6660:2:4065 +6661:2:4070 +6662:2:4071 +6663:2:4082 +6664:2:4083 +6665:2:4084 +6666:2:4082 +6667:2:4083 +6668:2:4084 +6669:2:4095 +6670:2:4103 +6671:0:4533 +6672:2:3127 +6673:0:4533 +6674:2:4109 +6675:2:4110 +6676:2:4114 +6677:2:4115 +6678:2:4123 +6679:2:4124 +6680:2:4128 +6681:2:4129 +6682:2:4137 +6683:2:4142 +6684:2:4146 +6685:2:4147 +6686:2:4155 +6687:2:4156 +6688:2:4160 +6689:2:4161 +6690:2:4155 +6691:2:4156 +6692:2:4160 +6693:2:4161 +6694:2:4169 +6695:2:4174 +6696:2:4175 +6697:2:4186 +6698:2:4194 +6699:2:4195 +6700:2:4199 +6701:2:4204 +6702:2:4205 +6703:2:4216 +6704:2:4217 +6705:2:4218 +6706:2:4216 +6707:2:4217 +6708:2:4218 +6709:2:4229 +6710:0:4533 +6711:2:3127 +6712:0:4533 +6713:1:148 +6714:1:149 +6715:1:153 +6716:1:154 +6717:1:162 +6718:1:171 +6719:1:172 +6720:1:176 +6721:1:181 +6722:1:185 +6723:1:186 +6724:1:194 +6725:1:195 +6726:1:199 +6727:1:200 +6728:1:194 +6729:1:195 +6730:1:199 +6731:1:200 +6732:1:208 +6733:1:213 +6734:1:214 +6735:1:225 +6736:1:226 +6737:1:229 +6738:1:230 +6739:1:238 +6740:1:243 +6741:1:244 +6742:1:255 +6743:1:256 +6744:1:257 +6745:1:255 +6746:1:256 +6747:1:257 +6748:1:268 +6749:0:4533 +6750:1:11 +6751:0:4533 +6752:2:3975 +6753:2:3976 +6754:2:3980 +6755:2:3981 +6756:2:3989 +6757:2:3990 +6758:2:3994 +6759:2:3995 +6760:2:4003 +6761:2:4008 +6762:2:4012 +6763:2:4013 +6764:2:4021 +6765:2:4022 +6766:2:4026 +6767:2:4027 +6768:2:4021 +6769:2:4022 +6770:2:4026 +6771:2:4027 +6772:2:4035 +6773:2:4040 +6774:2:4041 +6775:2:4052 +6776:2:4060 +6777:2:4061 +6778:2:4065 +6779:2:4070 +6780:2:4071 +6781:2:4082 +6782:2:4083 +6783:2:4084 +6784:2:4082 +6785:2:4083 +6786:2:4084 +6787:2:4095 +6788:2:4103 +6789:0:4533 +6790:2:3127 +6791:0:4533 +6792:2:4109 +6793:2:4110 +6794:2:4114 +6795:2:4115 +6796:2:4123 +6797:2:4124 +6798:2:4128 +6799:2:4129 +6800:2:4137 +6801:2:4142 +6802:2:4146 +6803:2:4147 +6804:2:4155 +6805:2:4156 +6806:2:4160 +6807:2:4161 +6808:2:4155 +6809:2:4156 +6810:2:4160 +6811:2:4161 +6812:2:4169 +6813:2:4174 +6814:2:4175 +6815:2:4186 +6816:2:4194 +6817:2:4195 +6818:2:4199 +6819:2:4204 +6820:2:4205 +6821:2:4216 +6822:2:4217 +6823:2:4218 +6824:2:4216 +6825:2:4217 +6826:2:4218 +6827:2:4229 +6828:0:4533 +6829:2:3127 +6830:0:4533 +6831:1:277 +6832:1:278 +6833:1:282 +6834:1:283 +6835:1:291 +6836:1:300 +6837:1:301 +6838:1:305 +6839:1:310 +6840:1:314 +6841:1:315 +6842:1:323 +6843:1:324 +6844:1:328 +6845:1:329 +6846:1:323 +6847:1:324 +6848:1:328 +6849:1:329 +6850:1:337 +6851:1:342 +6852:1:343 +6853:1:354 +6854:1:355 +6855:1:358 +6856:1:359 +6857:1:367 +6858:1:372 +6859:1:373 +6860:1:384 +6861:1:385 +6862:1:386 +6863:1:384 +6864:1:385 +6865:1:386 +6866:1:397 +6867:1:404 +6868:0:4533 +6869:1:11 +6870:0:4533 +6871:2:3975 +6872:2:3976 +6873:2:3980 +6874:2:3981 +6875:2:3989 +6876:2:3990 +6877:2:3994 +6878:2:3995 +6879:2:4003 +6880:2:4008 +6881:2:4012 +6882:2:4013 +6883:2:4021 +6884:2:4022 +6885:2:4026 +6886:2:4027 +6887:2:4021 +6888:2:4022 +6889:2:4026 +6890:2:4027 +6891:2:4035 +6892:2:4040 +6893:2:4041 +6894:2:4052 +6895:2:4060 +6896:2:4061 +6897:2:4065 +6898:2:4070 +6899:2:4071 +6900:2:4082 +6901:2:4083 +6902:2:4084 +6903:2:4082 +6904:2:4083 +6905:2:4084 +6906:2:4095 +6907:2:4103 +6908:0:4533 +6909:2:3127 +6910:0:4533 +6911:1:540 +6912:1:544 +6913:1:545 +6914:1:549 +6915:1:550 +6916:1:558 +6917:1:566 +6918:1:567 +6919:1:571 +6920:1:575 +6921:1:576 +6922:1:571 +6923:1:575 +6924:1:576 +6925:1:580 +6926:1:587 +6927:1:594 +6928:1:595 +6929:1:602 +6930:1:607 +6931:1:614 +6932:1:615 +6933:1:614 +6934:1:615 +6935:1:622 +6936:0:4533 +6937:1:11 +6938:0:4533 +6939:1:632 +6940:1:633 +6941:1:637 +6942:1:638 +6943:1:646 +6944:1:647 +6945:1:651 +6946:1:652 +6947:1:660 +6948:1:665 +6949:1:669 +6950:1:670 +6951:1:678 +6952:1:679 +6953:1:683 +6954:1:684 +6955:1:678 +6956:1:679 +6957:1:683 +6958:1:684 +6959:1:692 +6960:1:697 +6961:1:698 +6962:1:709 +6963:1:710 +6964:1:711 +6965:1:722 +6966:1:727 +6967:1:728 +6968:1:739 +6969:1:740 +6970:1:741 +6971:1:739 +6972:1:740 +6973:1:741 +6974:1:752 +6975:0:4533 +6976:1:11 +6977:0:4533 +6978:1:761 +6979:1:764 +6980:1:765 +6981:0:4533 +6982:1:11 +6983:0:4533 +6984:1:1028 +6985:1:1029 +6986:1:1033 +6987:1:1034 +6988:1:1042 +6989:1:1043 +6990:1:1047 +6991:1:1048 +6992:1:1056 +6993:1:1061 +6994:1:1065 +6995:1:1066 +6996:1:1074 +6997:1:1075 +6998:1:1079 +6999:1:1080 +7000:1:1074 +7001:1:1075 +7002:1:1079 +7003:1:1080 +7004:1:1088 +7005:1:1093 +7006:1:1094 +7007:1:1105 +7008:1:1106 +7009:1:1107 +7010:1:1118 +7011:1:1123 +7012:1:1124 +7013:1:1135 +7014:1:1136 +7015:1:1137 +7016:1:1135 +7017:1:1136 +7018:1:1137 +7019:1:1148 +7020:1:1155 +7021:1:1159 +7022:0:4533 +7023:1:11 +7024:0:4533 +7025:1:1160 +7026:1:1161 +7027:1:1165 +7028:1:1166 +7029:1:1174 +7030:1:1175 +7031:1:1176 +7032:1:1188 +7033:1:1193 +7034:1:1197 +7035:1:1198 +7036:1:1206 +7037:1:1207 +7038:1:1211 +7039:1:1212 +7040:1:1206 +7041:1:1207 +7042:1:1211 +7043:1:1212 +7044:1:1220 +7045:1:1225 +7046:1:1226 +7047:1:1237 +7048:1:1238 +7049:1:1239 +7050:1:1250 +7051:1:1255 +7052:1:1256 +7053:1:1267 +7054:1:1268 +7055:1:1269 +7056:1:1267 +7057:1:1268 +7058:1:1269 +7059:1:1280 +7060:0:4533 +7061:1:11 +7062:0:4533 +7063:1:1289 +7064:0:4533 +7065:1:3023 +7066:1:3030 +7067:1:3031 +7068:1:3038 +7069:1:3043 +7070:1:3050 +7071:1:3051 +7072:1:3050 +7073:1:3051 +7074:1:3058 +7075:1:3062 +7076:0:4533 +7077:1:1291 +7078:1:1292 +7079:0:4533 +7080:1:11 +7081:0:4533 +7082:1:1293 +7083:1:1294 +7084:1:1298 +7085:1:1299 +7086:1:1307 +7087:1:1308 +7088:1:1312 +7089:1:1313 +7090:1:1321 +7091:1:1326 +7092:1:1330 +7093:1:1331 +7094:1:1339 +7095:1:1340 +7096:1:1344 +7097:1:1345 +7098:1:1339 +7099:1:1340 +7100:1:1344 +7101:1:1345 +7102:1:1353 +7103:1:1358 +7104:1:1359 +7105:1:1370 +7106:1:1371 +7107:1:1372 +7108:1:1383 +7109:1:1388 +7110:1:1389 +7111:1:1400 +7112:1:1401 +7113:1:1402 +7114:1:1400 +7115:1:1401 +7116:1:1402 +7117:1:1413 +7118:0:4533 +7119:1:11 +7120:0:4533 +7121:1:1422 +7122:1:1423 +7123:1:1427 +7124:1:1428 +7125:1:1436 +7126:1:1437 +7127:1:1441 +7128:1:1442 +7129:1:1450 +7130:1:1455 +7131:1:1459 +7132:1:1460 +7133:1:1468 +7134:1:1469 +7135:1:1473 +7136:1:1474 +7137:1:1468 +7138:1:1469 +7139:1:1473 +7140:1:1474 +7141:1:1482 +7142:1:1487 +7143:1:1488 +7144:1:1499 +7145:1:1500 +7146:1:1501 +7147:1:1512 +7148:1:1517 +7149:1:1518 +7150:1:1529 +7151:1:1530 +7152:1:1531 +7153:1:1529 +7154:1:1530 +7155:1:1531 +7156:1:1542 +7157:1:1549 +7158:1:1553 +7159:0:4533 +7160:1:11 +7161:0:4533 +7162:1:1554 +7163:1:1558 +7164:1:1559 +7165:1:1563 +7166:1:1564 +7167:1:1572 +7168:1:1580 +7169:1:1581 +7170:1:1585 +7171:1:1589 +7172:1:1590 +7173:1:1585 +7174:1:1589 +7175:1:1590 +7176:1:1594 +7177:1:1601 +7178:1:1608 +7179:1:1609 +7180:1:1616 +7181:1:1621 +7182:1:1628 +7183:1:1629 +7184:1:1628 +7185:1:1629 +7186:1:1636 +-1:-1:-1 +7187:0:4533 +7188:1:11 +7189:0:4533 +7190:1:1646 +7191:1:1647 +7192:1:1651 +7193:1:1652 +7194:1:1660 +7195:1:1661 +7196:1:1665 +7197:1:1666 +7198:1:1674 +7199:1:1679 +7200:1:1683 +7201:1:1684 +7202:1:1692 +7203:1:1693 +7204:1:1697 +7205:1:1698 +7206:1:1692 +7207:1:1693 +7208:1:1697 +7209:1:1698 +7210:1:1706 +7211:1:1711 +7212:1:1712 +7213:1:1723 +7214:1:1724 +7215:1:1725 +7216:1:1736 +7217:1:1741 +7218:1:1742 +7219:1:1753 +7220:1:1754 +7221:1:1755 +7222:1:1753 +7223:1:1754 +7224:1:1755 +7225:1:1766 +7226:0:4533 +7227:1:11 +7228:0:4533 +7229:1:1775 +7230:1:1776 +7231:1:1780 +7232:1:1781 +7233:1:1789 +7234:1:1790 +7235:1:1794 +7236:1:1795 +7237:1:1803 +7238:1:1808 +7239:1:1812 +7240:1:1813 +7241:1:1821 +7242:1:1822 +7243:1:1826 +7244:1:1827 +7245:1:1821 +7246:1:1822 +7247:1:1826 +7248:1:1827 +7249:1:1835 +7250:1:1840 +7251:1:1841 +7252:1:1852 +7253:1:1853 +7254:1:1854 +7255:1:1865 +7256:1:1870 +7257:1:1871 +7258:1:1882 +7259:1:1883 +7260:1:1884 +7261:1:1882 +7262:1:1883 +7263:1:1884 +7264:1:1895 +7265:1:1902 +7266:1:1906 +7267:0:4533 +7268:1:11 +7269:0:4533 +7270:1:1907 +7271:1:1908 +7272:1:1912 +7273:1:1913 +7274:1:1921 +7275:1:1922 +7276:1:1923 +7277:1:1935 +7278:1:1940 +7279:1:1944 +7280:1:1945 +7281:1:1953 +7282:1:1954 +7283:1:1958 +7284:1:1959 +7285:1:1953 +7286:1:1954 +7287:1:1958 +7288:1:1959 +7289:1:1967 +7290:1:1972 +7291:1:1973 +7292:1:1984 +7293:1:1985 +7294:1:1986 +7295:1:1997 +7296:1:2002 +7297:1:2003 +7298:1:2014 +7299:1:2015 +7300:1:2016 +7301:1:2014 +7302:1:2015 +7303:1:2016 +7304:1:2027 +7305:0:4533 +7306:1:11 +7307:0:4533 +7308:1:2036 +7309:1:2037 +7310:0:4533 +7311:1:11 +7312:0:4533 +7313:1:2043 +7314:1:2044 +7315:1:2048 +7316:1:2049 +7317:1:2057 +7318:1:2058 +7319:1:2062 +7320:1:2063 +7321:1:2071 +7322:1:2076 +7323:1:2080 +7324:1:2081 +7325:1:2089 +7326:1:2090 +7327:1:2094 +7328:1:2095 +7329:1:2089 +7330:1:2090 +7331:1:2094 +7332:1:2095 +7333:1:2103 +7334:1:2108 +7335:1:2109 +7336:1:2120 +7337:1:2121 +7338:1:2122 +7339:1:2133 +7340:1:2138 +7341:1:2139 +7342:1:2150 +7343:1:2151 +7344:1:2152 +7345:1:2150 +7346:1:2151 +7347:1:2152 +7348:1:2163 +7349:0:4533 +7350:1:11 +7351:0:4533 +7352:1:2172 +7353:1:2173 +7354:1:2177 +7355:1:2178 +7356:1:2186 +7357:1:2187 +7358:1:2191 +7359:1:2192 +7360:1:2200 +7361:1:2205 +7362:1:2209 +7363:1:2210 +7364:1:2218 +7365:1:2219 +7366:1:2223 +7367:1:2224 +7368:1:2218 +7369:1:2219 +7370:1:2223 +7371:1:2224 +7372:1:2232 +7373:1:2237 +7374:1:2238 +7375:1:2249 +7376:1:2250 +7377:1:2251 +7378:1:2262 +7379:1:2267 +7380:1:2268 +7381:1:2279 +7382:1:2280 +7383:1:2281 +7384:1:2279 +7385:1:2280 +7386:1:2281 +7387:1:2292 +7388:1:2299 +7389:0:4533 +7390:1:11 +7391:0:4533 +7392:1:2435 +7393:1:2439 +7394:1:2440 +7395:1:2444 +7396:1:2445 +7397:1:2453 +7398:1:2461 +7399:1:2462 +7400:1:2466 +7401:1:2470 +7402:1:2471 +7403:1:2466 +7404:1:2470 +7405:1:2471 +7406:1:2475 +7407:1:2482 +7408:1:2489 +7409:1:2490 +7410:1:2497 +7411:1:2502 +7412:1:2509 +7413:1:2510 +7414:1:2509 +7415:1:2510 +7416:1:2517 +7417:0:4533 +7418:1:11 +7419:0:4533 +7420:1:2527 +7421:1:2528 +7422:1:2532 +7423:1:2533 +7424:1:2541 +7425:1:2542 +7426:1:2546 +7427:1:2547 +7428:1:2555 +7429:1:2560 +7430:1:2564 +7431:1:2565 +7432:1:2573 +7433:1:2574 +7434:1:2578 +7435:1:2579 +7436:1:2573 +7437:1:2574 +7438:1:2578 +7439:1:2579 +7440:1:2587 +7441:1:2592 +7442:1:2593 +7443:1:2604 +7444:1:2605 +7445:1:2606 +7446:1:2617 +7447:1:2622 +7448:1:2623 +7449:1:2634 +7450:1:2635 +7451:1:2636 +7452:1:2634 +7453:1:2635 +7454:1:2636 +7455:1:2647 +7456:0:4533 +7457:1:11 +7458:0:4533 +7459:1:2656 +7460:0:4533 +7461:1:3066 +7462:1:3073 +7463:1:3074 +7464:1:3081 +7465:1:3086 +7466:1:3093 +7467:1:3094 +7468:1:3093 +7469:1:3094 +7470:1:3101 +7471:1:3105 +7472:0:4533 +7473:1:2658 +7474:1:2659 +7475:0:4533 +7476:1:11 +7477:0:4533 +7478:1:2660 +7479:1:2664 +7480:1:2665 +7481:1:2669 +7482:1:2673 +7483:1:2674 +7484:1:2678 +7485:1:2686 +7486:1:2687 +7487:1:2691 +7488:1:2695 +7489:1:2696 +7490:1:2691 +7491:1:2695 +7492:1:2696 +7493:1:2700 +7494:1:2707 +7495:1:2714 +7496:1:2715 +7497:1:2722 +7498:1:2727 +7499:1:2734 +7500:1:2735 +7501:1:2734 +7502:1:2735 +7503:1:2742 +7504:0:4533 +7505:1:11 +7506:0:4533 +7507:1:2752 +7508:1:2753 +7509:1:2757 +7510:1:2758 +7511:1:2766 +7512:1:2767 +7513:1:2771 +7514:1:2772 +7515:1:2780 +7516:1:2785 +7517:1:2789 +7518:1:2790 +7519:1:2798 +7520:1:2799 +7521:1:2803 +7522:1:2804 +7523:1:2798 +7524:1:2799 +7525:1:2803 +7526:1:2804 +7527:1:2812 +7528:1:2817 +7529:1:2818 +7530:1:2829 +7531:1:2830 +7532:1:2831 +7533:1:2842 +7534:1:2847 +7535:1:2848 +7536:1:2859 +7537:1:2860 +7538:1:2861 +7539:1:2859 +7540:1:2860 +7541:1:2861 +7542:1:2872 +7543:0:4533 +7544:1:11 +7545:0:4533 +7546:1:2881 +7547:1:2882 +7548:1:2886 +7549:1:2887 +7550:1:2895 +7551:1:2896 +7552:1:2900 +7553:1:2901 +7554:1:2909 +7555:1:2914 +7556:1:2918 +7557:1:2919 +7558:1:2927 +7559:1:2928 +7560:1:2932 +7561:1:2933 +7562:1:2927 +7563:1:2928 +7564:1:2932 +7565:1:2933 +7566:1:2941 +7567:1:2946 +7568:1:2947 +7569:1:2958 +7570:1:2959 +7571:1:2960 +7572:1:2971 +7573:1:2976 +7574:1:2977 +7575:1:2988 +7576:1:2989 +7577:1:2990 +7578:1:2988 +7579:1:2989 +7580:1:2990 +7581:1:3001 +7582:1:3008 +7583:1:3012 +7584:0:4533 +7585:1:11 +7586:0:4533 +7587:1:3013 +7588:0:4533 +7589:1:3021 +7590:0:4533 +7591:1:3109 +7592:0:4533 +7593:1:9 +7594:0:4533 +7595:1:10 +7596:0:4533 +7597:1:11 +7598:0:4533 +7599:1:12 +7600:1:13 +7601:1:17 +7602:1:18 +7603:1:26 +7604:1:27 +7605:1:28 +7606:1:40 +7607:1:45 +7608:1:49 +7609:1:50 +7610:1:58 +7611:1:59 +7612:1:63 +7613:1:64 +7614:1:58 +7615:1:59 +7616:1:63 +7617:1:64 +7618:1:72 +7619:1:77 +7620:1:78 +7621:1:89 +7622:1:90 +7623:1:91 +7624:1:102 +7625:1:107 +7626:1:108 +7627:1:119 +7628:1:120 +7629:1:121 +7630:1:119 +7631:1:120 +7632:1:121 +7633:1:132 +7634:0:4533 +7635:1:11 +7636:0:4533 +7637:1:141 +7638:1:142 +7639:0:4533 +7640:1:11 +7641:0:4533 +7642:1:148 +7643:1:149 +7644:1:153 +7645:1:154 +7646:1:162 +7647:1:163 +7648:1:167 +7649:1:168 +7650:1:176 +7651:1:181 +7652:1:185 +7653:1:186 +7654:1:194 +7655:1:195 +7656:1:199 +7657:1:200 +7658:1:194 +7659:1:195 +7660:1:199 +7661:1:200 +7662:1:208 +7663:1:213 +7664:1:214 +7665:1:225 +7666:1:226 +7667:1:227 +7668:1:238 +7669:1:243 +7670:1:244 +7671:1:255 +7672:1:256 +7673:1:257 +7674:1:255 +7675:1:256 +7676:1:257 +7677:1:268 +7678:0:4533 +7679:1:11 +7680:0:4533 +7681:1:277 +7682:1:278 +7683:1:282 +7684:1:283 +7685:1:291 +7686:1:292 +7687:1:296 +7688:1:297 +7689:1:305 +7690:1:310 +7691:1:314 +7692:1:315 +7693:1:323 +7694:1:324 +7695:1:328 +7696:1:329 +7697:1:323 +7698:1:324 +7699:1:328 +7700:1:329 +7701:1:337 +7702:1:342 +7703:1:343 +7704:1:354 +7705:1:355 +7706:1:356 +7707:1:367 +7708:1:372 +7709:1:373 +7710:1:384 +7711:1:385 +7712:1:386 +7713:1:384 +7714:1:385 +7715:1:386 +7716:1:397 +7717:1:404 +7718:0:4533 +7719:1:11 +7720:0:4533 +7721:1:540 +7722:1:544 +7723:1:545 +7724:1:549 +7725:1:550 +7726:1:558 +7727:1:566 +7728:1:567 +7729:1:571 +7730:1:575 +7731:1:576 +7732:1:571 +7733:1:575 +7734:1:576 +7735:1:580 +7736:1:587 +7737:1:594 +7738:1:595 +7739:1:602 +7740:1:607 +7741:1:614 +7742:1:615 +7743:1:614 +7744:1:615 +7745:1:622 +7746:0:4533 +7747:2:4109 +7748:2:4110 +7749:2:4114 +7750:2:4115 +7751:2:4123 +7752:2:4124 +7753:2:4128 +7754:2:4129 +7755:2:4137 +7756:2:4142 +7757:2:4146 +7758:2:4147 +7759:2:4155 +7760:2:4156 +7761:2:4160 +7762:2:4161 +7763:2:4155 +7764:2:4156 +7765:2:4160 +7766:2:4161 +7767:2:4169 +7768:2:4174 +7769:2:4175 +7770:2:4186 +7771:2:4194 +7772:2:4195 +7773:2:4199 +7774:2:4204 +7775:2:4205 +7776:2:4216 +7777:2:4217 +7778:2:4218 +7779:2:4216 +7780:2:4217 +7781:2:4218 +7782:2:4229 +7783:0:4533 +7784:2:3127 +7785:0:4533 +7786:1:11 +7787:0:4533 +7788:1:632 +7789:1:633 +7790:1:637 +7791:1:638 +7792:1:646 +7793:1:647 +7794:1:651 +7795:1:652 +7796:1:660 +7797:1:665 +7798:1:669 +7799:1:670 +7800:1:678 +7801:1:679 +7802:1:683 +7803:1:684 +7804:1:678 +7805:1:679 +7806:1:683 +7807:1:684 +7808:1:692 +7809:1:697 +7810:1:698 +7811:1:709 +7812:1:710 +7813:1:711 +7814:1:722 +7815:1:727 +7816:1:728 +7817:1:739 +7818:1:740 +7819:1:741 +7820:1:739 +7821:1:740 +7822:1:741 +7823:1:752 +7824:0:4533 +7825:2:3975 +7826:2:3976 +7827:2:3980 +7828:2:3981 +7829:2:3989 +7830:2:3990 +7831:2:3994 +7832:2:3995 +7833:2:4003 +7834:2:4008 +7835:2:4012 +7836:2:4013 +7837:2:4021 +7838:2:4022 +7839:2:4026 +7840:2:4027 +7841:2:4021 +7842:2:4022 +7843:2:4026 +7844:2:4027 +7845:2:4035 +7846:2:4040 +7847:2:4041 +7848:2:4052 +7849:2:4060 +7850:2:4061 +7851:2:4065 +7852:2:4070 +7853:2:4071 +7854:2:4082 +7855:2:4083 +7856:2:4084 +7857:2:4082 +7858:2:4083 +7859:2:4084 +7860:2:4095 +7861:2:4103 +7862:0:4533 +7863:2:3127 +7864:0:4533 +7865:1:11 +7866:0:4533 +7867:1:1160 +7868:1:1161 +7869:1:1165 +7870:1:1166 +7871:1:1174 +7872:1:1175 +7873:1:1179 +7874:1:1180 +7875:1:1188 +7876:1:1193 +7877:1:1197 +7878:1:1198 +7879:1:1206 +7880:1:1207 +7881:1:1211 +7882:1:1212 +7883:1:1206 +7884:1:1207 +7885:1:1211 +7886:1:1212 +7887:1:1220 +7888:1:1225 +7889:1:1226 +7890:1:1237 +7891:1:1238 +7892:1:1239 +7893:1:1250 +7894:1:1255 +7895:1:1256 +7896:1:1267 +7897:1:1268 +7898:1:1269 +7899:1:1267 +7900:1:1268 +7901:1:1269 +7902:1:1280 +7903:0:4533 +7904:1:11 +7905:0:4533 +7906:2:4109 +7907:2:4110 +7908:2:4114 +7909:2:4115 +7910:2:4123 +7911:2:4124 +7912:2:4128 +7913:2:4129 +7914:2:4137 +7915:2:4142 +7916:2:4146 +7917:2:4147 +7918:2:4155 +7919:2:4156 +7920:2:4160 +7921:2:4161 +7922:2:4155 +7923:2:4156 +7924:2:4160 +7925:2:4161 +7926:2:4169 +7927:2:4174 +7928:2:4175 +7929:2:4186 +7930:2:4194 +7931:2:4195 +7932:2:4199 +7933:2:4204 +7934:2:4205 +7935:2:4216 +7936:2:4217 +7937:2:4218 +7938:2:4216 +7939:2:4217 +7940:2:4218 +7941:2:4229 +7942:0:4533 +7943:2:3127 +7944:0:4533 +7945:2:3975 +7946:2:3976 +7947:2:3980 +7948:2:3981 +7949:2:3989 +7950:2:3990 +7951:2:3994 +7952:2:3995 +7953:2:4003 +7954:2:4008 +7955:2:4012 +7956:2:4013 +7957:2:4021 +7958:2:4022 +7959:2:4026 +7960:2:4027 +7961:2:4021 +7962:2:4022 +7963:2:4026 +7964:2:4027 +7965:2:4035 +7966:2:4040 +7967:2:4041 +7968:2:4052 +7969:2:4060 +7970:2:4061 +7971:2:4065 +7972:2:4070 +7973:2:4071 +7974:2:4082 +7975:2:4083 +7976:2:4084 +7977:2:4082 +7978:2:4083 +7979:2:4084 +7980:2:4095 +7981:2:4103 +7982:0:4533 +7983:2:3127 +7984:0:4533 +7985:1:761 +7986:1:764 +7987:1:765 +7988:0:4533 +7989:1:11 +7990:0:4533 +7991:2:4109 +7992:2:4110 +7993:2:4114 +7994:2:4115 +7995:2:4123 +7996:2:4124 +7997:2:4128 +7998:2:4129 +7999:2:4137 +8000:2:4142 +8001:2:4146 +8002:2:4147 +8003:2:4155 +8004:2:4156 +8005:2:4160 +8006:2:4161 +8007:2:4155 +8008:2:4156 +8009:2:4160 +8010:2:4161 +8011:2:4169 +8012:2:4174 +8013:2:4175 +8014:2:4186 +8015:2:4194 +8016:2:4195 +8017:2:4199 +8018:2:4204 +8019:2:4205 +8020:2:4216 +8021:2:4217 +8022:2:4218 +8023:2:4216 +8024:2:4217 +8025:2:4218 +8026:2:4229 +8027:0:4533 +8028:2:3127 +8029:0:4533 +8030:2:3975 +8031:2:3976 +8032:2:3980 +8033:2:3981 +8034:2:3989 +8035:2:3990 +8036:2:3994 +8037:2:3995 +8038:2:4003 +8039:2:4008 +8040:2:4012 +8041:2:4013 +8042:2:4021 +8043:2:4022 +8044:2:4026 +8045:2:4027 +8046:2:4021 +8047:2:4022 +8048:2:4026 +8049:2:4027 +8050:2:4035 +8051:2:4040 +8052:2:4041 +8053:2:4052 +8054:2:4060 +8055:2:4061 +8056:2:4065 +8057:2:4070 +8058:2:4071 +8059:2:4082 +8060:2:4083 +8061:2:4084 +8062:2:4082 +8063:2:4083 +8064:2:4084 +8065:2:4095 +8066:2:4103 +8067:0:4533 +8068:2:3127 +8069:0:4533 +8070:1:1028 +8071:1:1029 +8072:1:1033 +8073:1:1034 +8074:1:1042 +8075:1:1043 +8076:1:1047 +8077:1:1048 +8078:1:1056 +8079:1:1061 +8080:1:1065 +8081:1:1066 +8082:1:1074 +8083:1:1075 +8084:1:1079 +8085:1:1080 +8086:1:1074 +8087:1:1075 +8088:1:1079 +8089:1:1080 +8090:1:1088 +8091:1:1093 +8092:1:1094 +8093:1:1105 +8094:1:1106 +8095:1:1107 +8096:1:1118 +8097:1:1123 +8098:1:1124 +8099:1:1135 +8100:1:1136 +8101:1:1137 +8102:1:1135 +8103:1:1136 +8104:1:1137 +8105:1:1148 +8106:1:1155 +8107:1:1159 +8108:0:4533 +8109:1:11 +8110:0:4533 +8111:2:4109 +8112:2:4110 +8113:2:4114 +8114:2:4115 +8115:2:4123 +8116:2:4124 +8117:2:4128 +8118:2:4129 +8119:2:4137 +8120:2:4142 +8121:2:4146 +8122:2:4147 +8123:2:4155 +8124:2:4156 +8125:2:4160 +8126:2:4161 +8127:2:4155 +8128:2:4156 +8129:2:4160 +8130:2:4161 +8131:2:4169 +8132:2:4174 +8133:2:4175 +8134:2:4186 +8135:2:4194 +8136:2:4195 +8137:2:4199 +8138:2:4204 +8139:2:4205 +8140:2:4216 +8141:2:4217 +8142:2:4218 +8143:2:4216 +8144:2:4217 +8145:2:4218 +8146:2:4229 +8147:0:4533 +8148:2:3127 +8149:0:4533 +8150:2:3975 +8151:2:3976 +8152:2:3980 +8153:2:3981 +8154:2:3989 +8155:2:3990 +8156:2:3994 +8157:2:3995 +8158:2:4003 +8159:2:4008 +8160:2:4012 +8161:2:4013 +8162:2:4021 +8163:2:4022 +8164:2:4026 +8165:2:4027 +8166:2:4021 +8167:2:4022 +8168:2:4026 +8169:2:4027 +8170:2:4035 +8171:2:4040 +8172:2:4041 +8173:2:4052 +8174:2:4060 +8175:2:4061 +8176:2:4065 +8177:2:4070 +8178:2:4071 +8179:2:4082 +8180:2:4083 +8181:2:4084 +8182:2:4082 +8183:2:4083 +8184:2:4084 +8185:2:4095 +8186:2:4103 +8187:0:4533 +8188:2:3127 +8189:0:4533 +8190:1:1289 +8191:0:4533 +8192:2:4109 +8193:2:4110 +8194:2:4114 +8195:2:4115 +8196:2:4123 +8197:2:4124 +8198:2:4128 +8199:2:4129 +8200:2:4137 +8201:2:4142 +8202:2:4146 +8203:2:4147 +8204:2:4155 +8205:2:4156 +8206:2:4160 +8207:2:4161 +8208:2:4155 +8209:2:4156 +8210:2:4160 +8211:2:4161 +8212:2:4169 +8213:2:4174 +8214:2:4175 +8215:2:4186 +8216:2:4194 +8217:2:4195 +8218:2:4199 +8219:2:4204 +8220:2:4205 +8221:2:4216 +8222:2:4217 +8223:2:4218 +8224:2:4216 +8225:2:4217 +8226:2:4218 +8227:2:4229 +8228:0:4533 +8229:2:3127 +8230:0:4533 +8231:2:3975 +8232:2:3976 +8233:2:3980 +8234:2:3981 +8235:2:3989 +8236:2:3990 +8237:2:3994 +8238:2:3995 +8239:2:4003 +8240:2:4008 +8241:2:4012 +8242:2:4013 +8243:2:4021 +8244:2:4022 +8245:2:4026 +8246:2:4027 +8247:2:4021 +8248:2:4022 +8249:2:4026 +8250:2:4027 +8251:2:4035 +8252:2:4040 +8253:2:4041 +8254:2:4052 +8255:2:4060 +8256:2:4061 +8257:2:4065 +8258:2:4070 +8259:2:4071 +8260:2:4082 +8261:2:4083 +8262:2:4084 +8263:2:4082 +8264:2:4083 +8265:2:4084 +8266:2:4095 +8267:2:4103 +8268:0:4533 +8269:2:3127 +8270:0:4533 +8271:1:3023 +8272:1:3030 +8273:1:3033 +8274:1:3034 +8275:1:3038 +8276:1:3043 +8277:1:3050 +8278:1:3051 +8279:1:3050 +8280:1:3051 +8281:1:3058 +8282:1:3062 +8283:0:4533 +8284:2:4109 +8285:2:4110 +8286:2:4114 +8287:2:4115 +8288:2:4123 +8289:2:4124 +8290:2:4128 +8291:2:4129 +8292:2:4137 +8293:2:4142 +8294:2:4146 +8295:2:4147 +8296:2:4155 +8297:2:4156 +8298:2:4160 +8299:2:4161 +8300:2:4155 +8301:2:4156 +8302:2:4160 +8303:2:4161 +8304:2:4169 +8305:2:4174 +8306:2:4175 +8307:2:4186 +8308:2:4194 +8309:2:4195 +8310:2:4199 +8311:2:4204 +8312:2:4205 +8313:2:4216 +8314:2:4217 +8315:2:4218 +8316:2:4216 +8317:2:4217 +8318:2:4218 +8319:2:4229 +8320:0:4533 +8321:2:3127 +8322:0:4533 +8323:2:3975 +8324:2:3976 +8325:2:3980 +8326:2:3981 +8327:2:3989 +8328:2:3990 +8329:2:3994 +8330:2:3995 +8331:2:4003 +8332:2:4008 +8333:2:4012 +8334:2:4013 +8335:2:4021 +8336:2:4022 +8337:2:4026 +8338:2:4027 +8339:2:4021 +8340:2:4022 +8341:2:4026 +8342:2:4027 +8343:2:4035 +8344:2:4040 +8345:2:4041 +8346:2:4052 +8347:2:4060 +8348:2:4061 +8349:2:4065 +8350:2:4070 +8351:2:4071 +8352:2:4082 +8353:2:4083 +8354:2:4084 +8355:2:4082 +8356:2:4083 +8357:2:4084 +8358:2:4095 +8359:2:4103 +8360:0:4533 +8361:2:3127 +8362:0:4533 +8363:1:1291 +8364:1:1292 +8365:0:4533 +8366:1:11 +8367:0:4533 +8368:2:4109 +8369:2:4110 +8370:2:4114 +8371:2:4115 +8372:2:4123 +8373:2:4124 +8374:2:4128 +8375:2:4129 +8376:2:4137 +8377:2:4142 +8378:2:4146 +8379:2:4147 +8380:2:4155 +8381:2:4156 +8382:2:4160 +8383:2:4161 +8384:2:4155 +8385:2:4156 +8386:2:4160 +8387:2:4161 +8388:2:4169 +8389:2:4174 +8390:2:4175 +8391:2:4186 +8392:2:4194 +8393:2:4195 +8394:2:4199 +8395:2:4204 +8396:2:4205 +8397:2:4216 +8398:2:4217 +8399:2:4218 +8400:2:4216 +8401:2:4217 +8402:2:4218 +8403:2:4229 +8404:0:4533 +8405:2:3127 +8406:0:4533 +8407:2:3975 +8408:2:3976 +8409:2:3980 +8410:2:3981 +8411:2:3989 +8412:2:3990 +8413:2:3994 +8414:2:3995 +8415:2:4003 +8416:2:4008 +8417:2:4012 +8418:2:4013 +8419:2:4021 +8420:2:4022 +8421:2:4026 +8422:2:4027 +8423:2:4021 +8424:2:4022 +8425:2:4026 +8426:2:4027 +8427:2:4035 +8428:2:4040 +8429:2:4041 +8430:2:4052 +8431:2:4060 +8432:2:4061 +8433:2:4065 +8434:2:4070 +8435:2:4071 +8436:2:4082 +8437:2:4083 +8438:2:4084 +8439:2:4082 +8440:2:4083 +8441:2:4084 +8442:2:4095 +8443:2:4103 +8444:0:4533 +8445:2:3127 +8446:0:4533 +8447:1:1293 +8448:1:1294 +8449:1:1298 +8450:1:1299 +8451:1:1307 +8452:1:1308 +8453:1:1309 +8454:1:1321 +8455:1:1326 +8456:1:1330 +8457:1:1331 +8458:1:1339 +8459:1:1340 +8460:1:1344 +8461:1:1345 +8462:1:1339 +8463:1:1340 +8464:1:1344 +8465:1:1345 +8466:1:1353 +8467:1:1358 +8468:1:1359 +8469:1:1370 +8470:1:1371 +8471:1:1372 +8472:1:1383 +8473:1:1388 +8474:1:1389 +8475:1:1400 +8476:1:1401 +8477:1:1402 +8478:1:1400 +8479:1:1401 +8480:1:1402 +8481:1:1413 +8482:0:4533 +8483:2:4109 +8484:2:4110 +8485:2:4114 +8486:2:4115 +8487:2:4123 +8488:2:4124 +8489:2:4128 +8490:2:4129 +8491:2:4137 +8492:2:4142 +8493:2:4146 +8494:2:4147 +8495:2:4155 +8496:2:4156 +8497:2:4160 +8498:2:4161 +8499:2:4155 +8500:2:4156 +8501:2:4160 +8502:2:4161 +8503:2:4169 +8504:2:4174 +8505:2:4175 +8506:2:4186 +8507:2:4194 +8508:2:4195 +8509:2:4199 +8510:2:4204 +8511:2:4205 +8512:2:4216 +8513:2:4217 +8514:2:4218 +8515:2:4216 +8516:2:4217 +8517:2:4218 +8518:2:4229 +8519:0:4533 +8520:2:3127 +8521:0:4533 +8522:1:11 +8523:0:4533 +8524:1:1422 +8525:1:1423 +8526:1:1427 +8527:1:1428 +8528:1:1436 +8529:1:1437 +8530:1:1441 +8531:1:1442 +8532:1:1450 +8533:1:1455 +8534:1:1459 +8535:1:1460 +8536:1:1468 +8537:1:1469 +8538:1:1473 +8539:1:1474 +8540:1:1468 +8541:1:1469 +8542:1:1473 +8543:1:1474 +8544:1:1482 +8545:1:1487 +8546:1:1488 +8547:1:1499 +8548:1:1500 +8549:1:1501 +8550:1:1512 +8551:1:1517 +8552:1:1518 +8553:1:1529 +8554:1:1530 +8555:1:1531 +8556:1:1529 +8557:1:1530 +8558:1:1531 +8559:1:1542 +8560:1:1549 +8561:1:1553 +8562:0:4533 +8563:2:3975 +8564:2:3976 +8565:2:3980 +8566:2:3981 +8567:2:3989 +8568:2:3990 +8569:2:3994 +8570:2:3995 +8571:2:4003 +8572:2:4008 +8573:2:4012 +8574:2:4013 +8575:2:4021 +8576:2:4022 +8577:2:4026 +8578:2:4027 +8579:2:4021 +8580:2:4022 +8581:2:4026 +8582:2:4027 +8583:2:4035 +8584:2:4040 +8585:2:4041 +8586:2:4052 +8587:2:4060 +8588:2:4061 +8589:2:4065 +8590:2:4070 +8591:2:4071 +8592:2:4082 +8593:2:4083 +8594:2:4084 +8595:2:4082 +8596:2:4083 +8597:2:4084 +8598:2:4095 +8599:2:4103 +8600:0:4533 +8601:2:3127 +8602:0:4533 +8603:1:11 +8604:0:4533 +8605:2:4109 +8606:2:4110 +8607:2:4114 +8608:2:4115 +8609:2:4123 +8610:2:4124 +8611:2:4128 +8612:2:4129 +8613:2:4137 +8614:2:4142 +8615:2:4146 +8616:2:4147 +8617:2:4155 +8618:2:4156 +8619:2:4160 +8620:2:4161 +8621:2:4155 +8622:2:4156 +8623:2:4160 +8624:2:4161 +8625:2:4169 +8626:2:4174 +8627:2:4175 +8628:2:4186 +8629:2:4194 +8630:2:4195 +8631:2:4199 +8632:2:4204 +8633:2:4205 +8634:2:4216 +8635:2:4217 +8636:2:4218 +8637:2:4216 +8638:2:4217 +8639:2:4218 +8640:2:4229 +8641:0:4533 +8642:2:3127 +8643:0:4533 +8644:2:3975 +8645:2:3976 +8646:2:3980 +8647:2:3981 +8648:2:3989 +8649:2:3990 +8650:2:3994 +8651:2:3995 +8652:2:4003 +8653:2:4008 +8654:2:4012 +8655:2:4013 +8656:2:4021 +8657:2:4022 +8658:2:4026 +8659:2:4027 +8660:2:4021 +8661:2:4022 +8662:2:4026 +8663:2:4027 +8664:2:4035 +8665:2:4040 +8666:2:4041 +8667:2:4052 +8668:2:4060 +8669:2:4061 +8670:2:4065 +8671:2:4070 +8672:2:4071 +8673:2:4082 +8674:2:4083 +8675:2:4084 +8676:2:4082 +8677:2:4083 +8678:2:4084 +8679:2:4095 +8680:2:4103 +8681:0:4533 +8682:2:3127 +8683:0:4533 +8684:1:1554 +8685:1:1558 +8686:1:1559 +8687:1:1563 +8688:1:1564 +8689:1:1572 +8690:1:1580 +8691:1:1581 +8692:1:1585 +8693:1:1589 +8694:1:1590 +8695:1:1585 +8696:1:1589 +8697:1:1590 +8698:1:1594 +8699:1:1601 +8700:1:1608 +8701:1:1609 +8702:1:1616 +8703:1:1621 +8704:1:1628 +8705:1:1629 +8706:1:1628 +8707:1:1629 +8708:1:1636