* Nested calls are not supported.
*/
+/*
+ * Only Alpha has out-of-order cache bank loads. Other architectures (intel,
+ * powerpc, arm) ensure that dependent reads won't be reordered. c.f.
+ * http://www.linuxjournal.com/article/8212)
+#ifdef ARCH_ALPHA
+#define HAVE_OOO_CACHE_READ
+#endif
+
/*
* 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
fi;
/* Must consume all prior read tokens. All subsequent reads depend on it. */
-inline smp_rmb(i, j)
+inline smp_rmb(i)
{
atomic {
CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid());
}
/* Must consume all prior write tokens. All subsequent writes depend on it. */
-inline smp_wmb(i, j)
+inline smp_wmb(i)
{
atomic {
CACHE_WRITE_TO_MEM(urcu_gp_ctr, 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)
+inline smp_mb(i)
{
atomic {
- smp_wmb(i, j);
- smp_rmb(i, j);
+ smp_wmb(i);
+ smp_rmb(i);
}
}
{
do
:: (reader_barrier[get_readerid()] == 1) ->
- smp_mb(i, j);
+ /*
+ * 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);
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
+ /*
+ * 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) progress_writer_progid_##progressid:
-#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); \
+ smp_mb(i); \
i = 0; \
do \
:: i < NR_READERS -> \
* interest, given the reader has the ability to totally ignore \
* barrier requests. \
*/ \
-PROGRESS_LABEL(progressid) \
do \
- :: (reader_barrier[i] == 1) -> skip; \
+ :: (reader_barrier[i] == 1) -> \
+PROGRESS_LABEL(progressid) \
+ skip; \
:: (reader_barrier[i] == 0) -> break; \
od; \
i++; \
:: i >= NR_READERS -> \
break \
od; \
- smp_mb(i, j); \
+ smp_mb(i); \
}
#else
-#define smp_mb_send(i, j, progressid) smp_mb(i, j)
-#define smp_mb_reader smp_mb
+#define smp_mb_send(i, j, progressid) smp_mb(i)
+#define smp_mb_reader smp_mb(i)
#define smp_mb_recv(i, j)
#endif
i++
:: i >= SLAB_SIZE -> break
od;
+#ifdef HAVE_OOO_CACHE_READ
RANDOM_CACHE_READ_FROM_MEM(urcu_gp_ctr, get_pid());
i = 0;
do
i++
:: i >= SLAB_SIZE -> break
od;
+#else
+ smp_rmb(i);
+#endif /* HAVE_OOO_CACHE_READ */
}
}
skip;
fi;
}
- :: 1 -> skip;
fi;
goto non_atomic3_skip;
goto end;
rmb1:
#ifndef NO_RMB
- smp_rmb(i, j);
+ smp_rmb(i);
#else
ooo_mem(i);
#endif
goto rmb1_end;
rmb2:
#ifndef NO_RMB
- smp_rmb(i, j);
+ smp_rmb(i);
#else
ooo_mem(i);
#endif
assert(get_pid() < NR_PROCS);
do
- :: (loop_nr < 4) ->
+ :: (loop_nr < 3) ->
#ifdef WRITER_PROGRESS
progress_writer1:
#endif
:: CONSUME_TOKENS(proc_urcu_writer,
WRITE_DATA,
WRITE_PROC_WMB) ->
- smp_wmb(i, j);
+ smp_wmb(i);
PRODUCE_TOKENS(proc_urcu_writer, WRITE_PROC_WMB);
:: CONSUME_TOKENS(proc_urcu_writer,
:: 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;