1 #define WRITER_PROGRESS
2 #define GEN_ERROR_WRITER_PROGRESS
4 #define read_free_race (read_generation[0] == last_free_gen)
5 #define read_free (free_done && data_access[0])
8 //#define TEST_SIGNAL_ON_READ
9 //#define TEST_SIGNAL_ON_WRITE
11 #define RCU_GP_CTR_BIT (1 << 7)
12 #define RCU_GP_CTR_NEST_MASK (RCU_GP_CTR_BIT - 1)
14 #ifndef READER_NEST_LEVEL
15 //#define READER_NEST_LEVEL 1
16 #define READER_NEST_LEVEL 2
19 #define REMOTE_BARRIERS
21 * mem.spin: Promela code to validate memory barriers with OOO memory.
23 * This program is free software; you can redistribute it and/or modify
24 * it under the terms of the GNU General Public License as published by
25 * the Free Software Foundation; either version 2 of the License, or
26 * (at your option) any later version.
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the Free Software
35 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
37 * Copyright (c) 2009 Mathieu Desnoyers
40 /* Promela validation variables. */
42 /* specific defines "included" here */
43 /* DEFINES file "included" here */
45 /* All signal readers have same PID and uses same reader variable */
46 #ifdef TEST_SIGNAL_ON_WRITE
48 #define NR_READERS 1 /* the writer is also a signal reader */
55 #elif defined(TEST_SIGNAL_ON_READ)
57 #define get_pid() ((_pid < 2) -> 0 : 1)
66 #define get_pid() (_pid)
75 #define get_readerid() (get_pid())
78 * Each process have its own data in cache. Caches are randomly updated.
79 * smp_wmb and smp_rmb forces cache updates (write and read), smp_mb forces
83 typedef per_proc_byte {
87 /* Bitfield has a maximum of 8 procs */
88 typedef per_proc_bit {
92 #define DECLARE_CACHED_VAR(type, x) \
94 per_proc_##type cached_##x; \
95 per_proc_bit cache_dirty_##x;
97 #define INIT_CACHED_VAR(x, v, j) \
99 cache_dirty_##x.bitfield = 0; \
103 cached_##x.val[j] = v; \
105 :: j >= NR_PROCS -> break \
108 #define IS_CACHE_DIRTY(x, id) (cache_dirty_##x.bitfield & (1 << id))
110 #define READ_CACHED_VAR(x) (cached_##x.val[get_pid()])
112 #define WRITE_CACHED_VAR(x, v) \
114 cached_##x.val[get_pid()] = v; \
115 cache_dirty_##x.bitfield = \
116 cache_dirty_##x.bitfield | (1 << get_pid()); \
119 #define CACHE_WRITE_TO_MEM(x, id) \
121 :: IS_CACHE_DIRTY(x, id) -> \
122 mem_##x = cached_##x.val[id]; \
123 cache_dirty_##x.bitfield = \
124 cache_dirty_##x.bitfield & (~(1 << id)); \
129 #define CACHE_READ_FROM_MEM(x, id) \
131 :: !IS_CACHE_DIRTY(x, id) -> \
132 cached_##x.val[id] = mem_##x;\
138 * May update other caches if cache is dirty, or not.
140 #define RANDOM_CACHE_WRITE_TO_MEM(x, id)\
142 :: 1 -> CACHE_WRITE_TO_MEM(x, id); \
146 #define RANDOM_CACHE_READ_FROM_MEM(x, id)\
148 :: 1 -> CACHE_READ_FROM_MEM(x, id); \
153 * Remote barriers tests the scheme where a signal (or IPI) is sent to all
154 * reader threads to promote their compiler barrier to a smp_mb().
156 #ifdef REMOTE_BARRIERS
158 inline smp_rmb_pid(i, j)
161 CACHE_READ_FROM_MEM(urcu_gp_ctr, i);
165 CACHE_READ_FROM_MEM(urcu_active_readers[j], i);
167 :: j >= NR_READERS -> break
169 CACHE_READ_FROM_MEM(generation_ptr, i);
173 inline smp_wmb_pid(i, j)
176 CACHE_WRITE_TO_MEM(urcu_gp_ctr, i);
180 CACHE_WRITE_TO_MEM(urcu_active_readers[j], i);
182 :: j >= NR_READERS -> break
184 CACHE_WRITE_TO_MEM(generation_ptr, i);
188 inline smp_mb_pid(i, j)
206 * Readers do a simple barrier(), writers are doing a smp_mb() _and_ sending a
207 * signal or IPI to have all readers execute a smp_mb.
208 * We are not modeling the whole rendez-vous between readers and writers here,
209 * we just let the writer update each reader's caches remotely.
211 inline smp_mb_writer(i, j)
213 smp_mb_pid(get_pid(), j);
219 :: i >= NR_READERS -> break
221 smp_mb_pid(get_pid(), j);
224 inline smp_mb_reader(i, j)
234 CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid());
238 CACHE_READ_FROM_MEM(urcu_active_readers[i], get_pid());
240 :: i >= NR_READERS -> break
242 CACHE_READ_FROM_MEM(generation_ptr, get_pid());
249 CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid());
253 CACHE_WRITE_TO_MEM(urcu_active_readers[i], get_pid());
255 :: i >= NR_READERS -> break
257 CACHE_WRITE_TO_MEM(generation_ptr, get_pid());
278 inline smp_mb_writer(i, j)
283 inline smp_mb_reader(i, j)
290 /* Keep in sync manually with smp_rmb, wmp_wmb, ooo_mem and init() */
291 DECLARE_CACHED_VAR(byte, urcu_gp_ctr);
292 /* Note ! currently only two readers */
293 DECLARE_CACHED_VAR(byte, urcu_active_readers[NR_READERS]);
294 /* pointer generation */
295 DECLARE_CACHED_VAR(byte, generation_ptr);
297 byte last_free_gen = 0;
299 byte read_generation[NR_READERS];
300 bit data_access[NR_READERS];
306 bit sighand_exec = 0;
308 inline wait_init_done()
311 :: init_done == 0 -> skip;
318 inline wait_for_sighand_exec()
322 :: sighand_exec == 0 -> skip;
327 #ifdef TOO_BIG_STATE_SPACE
328 inline wait_for_sighand_exec()
332 :: sighand_exec == 0 -> skip;
336 :: 1 -> sighand_exec = 0;
345 inline wait_for_sighand_exec()
352 #ifdef TEST_SIGNAL_ON_WRITE
353 /* Block on signal handler execution */
354 inline dispatch_sighand_write_exec()
358 :: sighand_exec == 1 ->
367 inline dispatch_sighand_write_exec()
374 #ifdef TEST_SIGNAL_ON_READ
375 /* Block on signal handler execution */
376 inline dispatch_sighand_read_exec()
380 :: sighand_exec == 1 ->
389 inline dispatch_sighand_read_exec()
400 RANDOM_CACHE_WRITE_TO_MEM(urcu_gp_ctr, get_pid());
404 RANDOM_CACHE_WRITE_TO_MEM(urcu_active_readers[i],
407 :: i >= NR_READERS -> break
409 RANDOM_CACHE_WRITE_TO_MEM(generation_ptr, get_pid());
410 RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid());
414 RANDOM_CACHE_READ_FROM_MEM(urcu_active_readers[i],
417 :: i >= NR_READERS -> break
419 RANDOM_CACHE_READ_FROM_MEM(generation_ptr, get_pid());
423 inline wait_for_reader(tmp, tmp2, i, j)
427 tmp2 = READ_CACHED_VAR(urcu_active_readers[tmp]);
429 dispatch_sighand_write_exec();
431 :: (tmp2 & RCU_GP_CTR_NEST_MASK)
432 && ((tmp2 ^ READ_CACHED_VAR(urcu_gp_ctr))
434 #ifndef GEN_ERROR_WRITER_PROGRESS
439 dispatch_sighand_write_exec();
446 inline wait_for_quiescent_state(tmp, tmp2, i, j)
450 :: tmp < NR_READERS ->
451 wait_for_reader(tmp, tmp2, i, j);
453 :: (NR_READERS > 1) && (tmp < NR_READERS - 1)
455 dispatch_sighand_write_exec();
460 :: tmp >= NR_READERS -> break
464 /* Model the RCU read-side critical section. */
466 #ifndef TEST_SIGNAL_ON_WRITE
468 inline urcu_one_read(i, j, nest_i, tmp, tmp2)
472 :: nest_i < READER_NEST_LEVEL ->
474 dispatch_sighand_read_exec();
475 tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]);
477 dispatch_sighand_read_exec();
479 :: (!(tmp & RCU_GP_CTR_NEST_MASK))
481 tmp2 = READ_CACHED_VAR(urcu_gp_ctr);
483 dispatch_sighand_read_exec();
484 WRITE_CACHED_VAR(urcu_active_readers[get_readerid()],
487 WRITE_CACHED_VAR(urcu_active_readers[get_readerid()],
491 dispatch_sighand_read_exec();
493 :: nest_i >= READER_NEST_LEVEL -> break;
496 read_generation[get_readerid()] = READ_CACHED_VAR(generation_ptr);
497 data_access[get_readerid()] = 1;
498 data_access[get_readerid()] = 0;
502 :: nest_i < READER_NEST_LEVEL ->
504 dispatch_sighand_read_exec();
505 tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]);
507 dispatch_sighand_read_exec();
508 WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1);
510 :: nest_i >= READER_NEST_LEVEL -> break;
513 //dispatch_sighand_read_exec();
514 //smp_mc(i); /* added */
517 active proctype urcu_reader()
524 assert(get_pid() < NR_PROCS);
530 * We do not test reader's progress here, because we are mainly
531 * interested in writer's progress. The reader never blocks
532 * anyway. We have to test for reader/writer's progress
533 * separately, otherwise we could think the writer is doing
534 * progress when it's blocked by an always progressing reader.
536 #ifdef READER_PROGRESS
539 urcu_one_read(i, j, nest_i, tmp, tmp2);
543 #endif //!TEST_SIGNAL_ON_WRITE
546 /* signal handler reader */
548 inline urcu_one_read_sig(i, j, nest_i, tmp, tmp2)
552 :: nest_i < READER_NEST_LEVEL ->
554 tmp = READ_CACHED_VAR(urcu_active_readers[get_readerid()]);
557 :: (!(tmp & RCU_GP_CTR_NEST_MASK))
559 tmp2 = READ_CACHED_VAR(urcu_gp_ctr);
561 WRITE_CACHED_VAR(urcu_active_readers[get_readerid()],
564 WRITE_CACHED_VAR(urcu_active_readers[get_readerid()],
569 :: nest_i >= READER_NEST_LEVEL -> break;
572 read_generation[get_readerid()] = READ_CACHED_VAR(generation_ptr);
573 data_access[get_readerid()] = 1;
574 data_access[get_readerid()] = 0;
578 :: nest_i < READER_NEST_LEVEL ->
580 tmp2 = READ_CACHED_VAR(urcu_active_readers[get_readerid()]);
582 WRITE_CACHED_VAR(urcu_active_readers[get_readerid()], tmp2 - 1);
584 :: nest_i >= READER_NEST_LEVEL -> break;
587 //smp_mc(i); /* added */
590 active proctype urcu_reader_sig()
597 assert(get_pid() < NR_PROCS);
602 wait_for_sighand_exec();
604 * We do not test reader's progress here, because we are mainly
605 * interested in writer's progress. The reader never blocks
606 * anyway. We have to test for reader/writer's progress
607 * separately, otherwise we could think the writer is doing
608 * progress when it's blocked by an always progressing reader.
610 #ifdef READER_PROGRESS
613 urcu_one_read_sig(i, j, nest_i, tmp, tmp2);
619 /* Model the RCU update process. */
621 active proctype urcu_writer()
629 assert(get_pid() < NR_PROCS);
632 :: (READ_CACHED_VAR(generation_ptr) < 5) ->
633 #ifdef WRITER_PROGRESS
637 dispatch_sighand_write_exec();
639 old_gen = READ_CACHED_VAR(generation_ptr);
640 WRITE_CACHED_VAR(generation_ptr, old_gen + 1);
643 dispatch_sighand_write_exec();
649 :: write_lock == 0 ->
658 dispatch_sighand_write_exec();
659 tmp = READ_CACHED_VAR(urcu_gp_ctr);
661 dispatch_sighand_write_exec();
662 WRITE_CACHED_VAR(urcu_gp_ctr, tmp ^ RCU_GP_CTR_BIT);
664 dispatch_sighand_write_exec();
666 wait_for_quiescent_state(tmp, tmp2, i, j);
670 dispatch_sighand_write_exec();
671 tmp = READ_CACHED_VAR(urcu_gp_ctr);
673 dispatch_sighand_write_exec();
674 WRITE_CACHED_VAR(urcu_gp_ctr, tmp ^ RCU_GP_CTR_BIT);
677 dispatch_sighand_write_exec();
678 wait_for_quiescent_state(tmp, tmp2, i, j);
681 dispatch_sighand_write_exec();
683 /* free-up step, e.g., kfree(). */
685 last_free_gen = old_gen;
691 * Given the reader loops infinitely, let the writer also busy-loop
692 * with progress here so, with weak fairness, we can test the
698 #ifdef WRITER_PROGRESS
701 dispatch_sighand_write_exec();
705 /* Leave after the readers and writers so the pid count is ok. */
710 INIT_CACHED_VAR(urcu_gp_ctr, 1, j);
711 INIT_CACHED_VAR(generation_ptr, 0, j);
716 INIT_CACHED_VAR(urcu_active_readers[i], 0, j);
717 read_generation[i] = 1;
720 :: i >= NR_READERS -> break