diff options
authorRich Felker <>2014-07-19 20:42:15 -0400
committerRich Felker <>2014-07-19 20:42:15 -0400
commitcec33b2c6079195c687331beda5409f449125b06 (patch)
parent522a0de2101abd12b19a4d2ba5c09abbb7c5fc79 (diff)
fix or1k atomic store
at the very least, a compiler barrier is required no matter what, and that was missing. current or1k implementations have strong ordering, but this is not guaranteed as part of the ISA, so some sort of synchronizing operation is necessary. in principle we should use l.msync, but due to misinterpretation of the spec, it was wrongly treated as an optional instruction and is not supported by some implementations. if future kernels trap it and treat it as a nop (rather than illegal instruction) when the hardware/emulator does not support it, we could consider using it. in the absence of l.msync support, the l.lwa/l.swa instructions, which are specified to have a built-in l.msync, need to be used. the easiest way to use them to implement atomic store is to perform an atomic swap and throw away the result. using compare-and-swap would be lighter, and would probably be sufficient for all actual usage cases, but checking this is difficult and error-prone: with store implemented in terms of swap, it's guaranteed that, when another atomic operation is performed at the same time as the store, either the result of the store followed by the other operation, or just the store (clobbering the other operation's result) is seen. if store were implemented in terms of cas, there are cases where this invariant would fail to hold, and we would need detailed rules for the situations in which the store operation is well-defined.
1 files changed, 1 insertions, 1 deletions
diff --git a/arch/or1k/atomic.h b/arch/or1k/atomic.h
index 0fb61de1..10f75cbe 100644
--- a/arch/or1k/atomic.h
+++ b/arch/or1k/atomic.h
@@ -74,7 +74,7 @@ static inline void a_dec(volatile int *x)
static inline void a_store(volatile int *p, int x)
- *p=x;
+ a_swap(p, x);
static inline void a_spin()