https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104831
--- Comment #9 from Patrick O'Neill <patrick at rivosinc dot com> ---
Adding this comment to summarize why LR.aq/SC.rl doesn't appear to be
an issue.
The re-orderings shown in the previous litmus tests are allowed by the
C++/GCC definition of SEQ_CST. My reasoning in prior comments are
incorrect and should be disregarded.
The ISA manual table A.6 recommends the LR.aqrl/SC.rl pairing for
SEQ_CST because of A.6's SEQ_CST store mapping. When the SEQ_CST store
is implemented as:
fence rw,w + sw
There needs to be ordering enforced to prevent the store from being
reordered into the middle of the LR/SC pairing [1][2].
GCC has a different mapping for SEQ_CST store:
fence iorw,ow + amoswap.rl
This prevents the reordering as seen in the example [2], so we can
safely use LR.aq/SC.rl pairings [3].
Relevant litmus tests:
[1] CDSChecker Litmus test - seq_cst W-RMW
#include <stdlib.h>
#include <stdio.h>
#include <threads.h>
#include <atomic>
#include "model-assert.h"
/*
* This shows that the c memory model enforces
* SEQ_CST W->(RMW) ordering
*/
std::atomic_int x;
std::atomic_int y;
int resx, resy;
static void a(void *obj)
{
x.store(1, std::memory_order_seq_cst);
resy = y.fetch_add(1, std::memory_order_seq_cst);
}
static void b(void *obj)
{
y.store(42, std::memory_order_seq_cst);
resx = x.load(std::memory_order_seq_cst);
}
int user_main(int argc, char **argv)
{
thrd_t t1, t2;
atomic_init(&x, 0);
atomic_init(&y, 0);
printf("Main thread: creating 2 threads\n");
thrd_create(&t1, (thrd_start_t)&a, NULL);
thrd_create(&t2, (thrd_start_t)&b, NULL);
thrd_join(t1);
thrd_join(t2);
printf("x: %d\n", resy);
printf("y: %d\n", resx);
MODEL_ASSERT(!(resy == 0 && resx == 0));
printf("Main thread is finished\n");
return 0;
}
[2] Herd7 Write-RMW litmus test - ISA Manual A.6 Mapping
RISCV W-RMW
(*
Table A.6 Seq_cst store along with LR.aq/SC.rl is insufficient for a
seq_cst store, seq_cst RMW mapping.
*)
{
0:x7=A; 0:x8=B;
1:x7=A; 1:x8=B;
}
P0 | P1 ;
ori x1,x0,1 | ori x1,x0,1 ;
fence rw,w | fence rw,rw ;
sw x1,0(x8) | sw x1,0(x7) ;
lr.w.aq x3,0(x7) | fence rw,rw ;
sc.w.rl x1,x1,0(x7) | lw x2,0(x8) ;
exists
(0:x3=0 /\ 1:x2=0)
[3] Herd7 Write-RMW litmus test - GCC Mapping
RISCV W-RMW
(*
GCC's current mapping for seq_cst store along with LR.aq/SC.rl is
sufficient for a seq_cst store, seq_cst RMW mapping.
*)
{
0:x7=A; 0:x8=B;
1:x7=A; 1:x8=B;
}
P0 | P1 ;
ori x1,x0,1 | ori x1,x0,1 ;
fence rw,w | fence rw,rw ;
amoswap.w.aq x0,x1,0(x8) | sw x1,0(x7) ;
lr.w.aq x3,0(x7) | fence rw,rw ;
sc.w.rl x1,x1,0(x7) | lw x2,0(x8) ;
~exists (0:x3=0 /\ 1:x2=0)