summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnup Patel <anup.patel@wdc.com>2019-01-21 14:23:46 +0300
committerAnup Patel <anup@brainfault.org>2019-01-21 18:42:48 +0300
commit1ee745fe57c3ad9db64bb31564f21a4fab101f22 (patch)
treef2becf650d53144455d26636a58e2adb2c091967
parentb5be19f9e5c8f25b07375429aa5d00895a8645cc (diff)
downloadopensbi-1ee745fe57c3ad9db64bb31564f21a4fab101f22.tar.xz
lib: Use AMO instructions whenever __riscv_atomic is defined
We should use AMO instructions whenever __riscv_atomic is defined (i.e. atomics are supported). We use LR/SC only when __riscv_atomic is not defined. Signed-off-by: Anup Patel <anup.patel@wdc.com>
-rw-r--r--lib/riscv_atomic.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/lib/riscv_atomic.c b/lib/riscv_atomic.c
index 3a599f5..bef607f 100644
--- a/lib/riscv_atomic.c
+++ b/lib/riscv_atomic.c
@@ -137,16 +137,40 @@ long atomic_sub_return(atomic_t *atom, long value)
long arch_atomic_cmpxchg(atomic_t *atom, long oldval, long newval)
{
+#ifdef __riscv_atomic
+ return __sync_val_compare_and_swap(&atom->counter, oldval, newval);
+#else
return cmpxchg(&atom->counter, oldval, newval);
+#endif
}
long arch_atomic_xchg(atomic_t *atom, long newval)
{
+ /* Atomically set new value and return old value. */
+#ifdef __riscv_atomic
+ /*
+ * The name of GCC built-in macro __sync_lock_test_and_set()
+ * is misleading. A more appropriate name for GCC built-in
+ * macro would be __sync_val_exchange().
+ */
+ return __sync_lock_test_and_set(&atom->counter, newval);
+#else
return xchg(&atom->counter, newval);
+#endif
}
unsigned int atomic_raw_xchg_uint(volatile unsigned int *ptr,
unsigned int newval)
{
+ /* Atomically set new value and return old value. */
+#ifdef __riscv_atomic
+ /*
+ * The name of GCC built-in macro __sync_lock_test_and_set()
+ * is misleading. A more appropriate name for GCC built-in
+ * macro would be __sync_val_exchange().
+ */
+ return __sync_lock_test_and_set(ptr, newval);
+#else
return xchg(ptr, newval);
+#endif
}