The existing arch_atomic operations are implemented by inserting fence
instrucitons before or after atomic instructions. This commit replaces
them with real acquire/release semantics.

|-----------------------------------------------|
|    | arch_atomic(64)_{add|sub}_return_release |
| rl |------------------------------------------|
|    |                amoadd.rl                 |
|-----------------------------------------------|
|    | arch_atomic(64)_{add|sub}_return_acquire |
| aq |------------------------------------------|
|    |                amoadd.aq                 |
|-----------------------------------------------|

|---------------------------------------------------------|
|    | arch_atomic(64)_fetch_{add|sub|and|or|xor}_release |
| rl |----------------------------------------------------|
|    |               amo{add|and|or|xor}.rl               |
|---------------------------------------------------------|
|    | arch_atomic(64)_fetch_{add|sub|and|or|xor}_acquire |
| aq |----------------------------------------------------|
|    |               amo{add|and|or|xor}.aq               |
|---------------------------------------------------------|

Signed-off-by: Xu Lu <[email protected]>
---
 arch/riscv/include/asm/atomic.h | 64 +++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/arch/riscv/include/asm/atomic.h b/arch/riscv/include/asm/atomic.h
index 5b96c2f61adb5..86291de07de62 100644
--- a/arch/riscv/include/asm/atomic.h
+++ b/arch/riscv/include/asm/atomic.h
@@ -98,6 +98,30 @@ c_type arch_atomic##prefix##_fetch_##op##_relaxed(c_type i,  
        \
        return ret;                                                     \
 }                                                                      \
 static __always_inline                                                 \
+c_type arch_atomic##prefix##_fetch_##op##_acquire(c_type i,            \
+                                                 atomic##prefix##_t *v)        
\
+{                                                                      \
+       register c_type ret;                                            \
+       __asm__ __volatile__ (                                          \
+               "       amo" #asm_op "." #asm_type ".aq %1, %2, %0"     \
+               : "+A" (v->counter), "=r" (ret)                         \
+               : "r" (I)                                               \
+               : "memory");                                            \
+       return ret;                                                     \
+}                                                                      \
+static __always_inline                                                 \
+c_type arch_atomic##prefix##_fetch_##op##_release(c_type i,            \
+                                                 atomic##prefix##_t *v)        
\
+{                                                                      \
+       register c_type ret;                                            \
+       __asm__ __volatile__ (                                          \
+               "       amo" #asm_op "." #asm_type ".rl %1, %2, %0"     \
+               : "+A" (v->counter), "=r" (ret)                         \
+               : "r" (I)                                               \
+               : "memory");                                            \
+       return ret;                                                     \
+}                                                                      \
+static __always_inline                                                 \
 c_type arch_atomic##prefix##_fetch_##op(c_type i, atomic##prefix##_t *v)       
\
 {                                                                      \
        register c_type ret;                                            \
@@ -117,6 +141,18 @@ c_type arch_atomic##prefix##_##op##_return_relaxed(c_type 
i,               \
         return arch_atomic##prefix##_fetch_##op##_relaxed(i, v) c_op I;        
\
 }                                                                      \
 static __always_inline                                                 \
+c_type arch_atomic##prefix##_##op##_return_acquire(c_type i,           \
+                                                  atomic##prefix##_t *v)       
\
+{                                                                      \
+       return arch_atomic##prefix##_fetch_##op##_acquire(i, v) c_op I; \
+}                                                                      \
+static __always_inline                                                 \
+c_type arch_atomic##prefix##_##op##_return_release(c_type i,           \
+                                                  atomic##prefix##_t *v)       
\
+{                                                                      \
+       return arch_atomic##prefix##_fetch_##op##_release(i, v) c_op I; \
+}                                                                      \
+static __always_inline                                                 \
 c_type arch_atomic##prefix##_##op##_return(c_type i, atomic##prefix##_t *v)    
\
 {                                                                      \
         return arch_atomic##prefix##_fetch_##op(i, v) c_op I;          \
@@ -139,22 +175,38 @@ ATOMIC_OPS(sub, add, +, -i)
 
 #define arch_atomic_add_return_relaxed arch_atomic_add_return_relaxed
 #define arch_atomic_sub_return_relaxed arch_atomic_sub_return_relaxed
+#define arch_atomic_add_return_acquire arch_atomic_add_return_acquire
+#define arch_atomic_sub_return_acquire arch_atomic_sub_return_acquire
+#define arch_atomic_add_return_release arch_atomic_add_return_release
+#define arch_atomic_sub_return_release arch_atomic_sub_return_release
 #define arch_atomic_add_return         arch_atomic_add_return
 #define arch_atomic_sub_return         arch_atomic_sub_return
 
 #define arch_atomic_fetch_add_relaxed  arch_atomic_fetch_add_relaxed
 #define arch_atomic_fetch_sub_relaxed  arch_atomic_fetch_sub_relaxed
+#define arch_atomic_fetch_add_acquire  arch_atomic_fetch_add_acquire
+#define arch_atomic_fetch_sub_acquire  arch_atomic_fetch_sub_acquire
+#define arch_atomic_fetch_add_release  arch_atomic_fetch_add_release
+#define arch_atomic_fetch_sub_release  arch_atomic_fetch_sub_release
 #define arch_atomic_fetch_add          arch_atomic_fetch_add
 #define arch_atomic_fetch_sub          arch_atomic_fetch_sub
 
 #ifndef CONFIG_GENERIC_ATOMIC64
 #define arch_atomic64_add_return_relaxed       arch_atomic64_add_return_relaxed
 #define arch_atomic64_sub_return_relaxed       arch_atomic64_sub_return_relaxed
+#define arch_atomic64_add_return_acquire       arch_atomic64_add_return_acquire
+#define arch_atomic64_sub_return_acquire       arch_atomic64_sub_return_acquire
+#define arch_atomic64_add_return_release       arch_atomic64_add_return_release
+#define arch_atomic64_sub_return_release       arch_atomic64_sub_return_release
 #define arch_atomic64_add_return               arch_atomic64_add_return
 #define arch_atomic64_sub_return               arch_atomic64_sub_return
 
 #define arch_atomic64_fetch_add_relaxed        arch_atomic64_fetch_add_relaxed
 #define arch_atomic64_fetch_sub_relaxed        arch_atomic64_fetch_sub_relaxed
+#define arch_atomic64_fetch_add_acquire        arch_atomic64_fetch_add_acquire
+#define arch_atomic64_fetch_sub_acquire        arch_atomic64_fetch_sub_acquire
+#define arch_atomic64_fetch_add_release        arch_atomic64_fetch_add_release
+#define arch_atomic64_fetch_sub_release        arch_atomic64_fetch_sub_release
 #define arch_atomic64_fetch_add                arch_atomic64_fetch_add
 #define arch_atomic64_fetch_sub                arch_atomic64_fetch_sub
 #endif
@@ -177,6 +229,12 @@ ATOMIC_OPS(xor, xor, i)
 #define arch_atomic_fetch_and_relaxed  arch_atomic_fetch_and_relaxed
 #define arch_atomic_fetch_or_relaxed   arch_atomic_fetch_or_relaxed
 #define arch_atomic_fetch_xor_relaxed  arch_atomic_fetch_xor_relaxed
+#define arch_atomic_fetch_and_acquire  arch_atomic_fetch_and_acquire
+#define arch_atomic_fetch_or_acquire   arch_atomic_fetch_or_acquire
+#define arch_atomic_fetch_xor_acquire  arch_atomic_fetch_xor_acquire
+#define arch_atomic_fetch_and_release  arch_atomic_fetch_and_release
+#define arch_atomic_fetch_or_release   arch_atomic_fetch_or_release
+#define arch_atomic_fetch_xor_release  arch_atomic_fetch_xor_release
 #define arch_atomic_fetch_and          arch_atomic_fetch_and
 #define arch_atomic_fetch_or           arch_atomic_fetch_or
 #define arch_atomic_fetch_xor          arch_atomic_fetch_xor
@@ -185,6 +243,12 @@ ATOMIC_OPS(xor, xor, i)
 #define arch_atomic64_fetch_and_relaxed        arch_atomic64_fetch_and_relaxed
 #define arch_atomic64_fetch_or_relaxed arch_atomic64_fetch_or_relaxed
 #define arch_atomic64_fetch_xor_relaxed        arch_atomic64_fetch_xor_relaxed
+#define arch_atomic64_fetch_and_acquire        arch_atomic64_fetch_and_acquire
+#define arch_atomic64_fetch_or_acquire arch_atomic64_fetch_or_acquire
+#define arch_atomic64_fetch_xor_acquire        arch_atomic64_fetch_xor_acquire
+#define arch_atomic64_fetch_and_release        arch_atomic64_fetch_and_release
+#define arch_atomic64_fetch_or_release arch_atomic64_fetch_or_release
+#define arch_atomic64_fetch_xor_release        arch_atomic64_fetch_xor_release
 #define arch_atomic64_fetch_and                arch_atomic64_fetch_and
 #define arch_atomic64_fetch_or         arch_atomic64_fetch_or
 #define arch_atomic64_fetch_xor                arch_atomic64_fetch_xor
-- 
2.20.1


Reply via email to