18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 48c2ecf20Sopenharmony_ci * Copyright (C) 2012 Regents of the University of California 58c2ecf20Sopenharmony_ci * Copyright (C) 2017 SiFive 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#ifndef _ASM_RISCV_ATOMIC_H 98c2ecf20Sopenharmony_ci#define _ASM_RISCV_ATOMIC_H 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#ifdef CONFIG_GENERIC_ATOMIC64 128c2ecf20Sopenharmony_ci# include <asm-generic/atomic64.h> 138c2ecf20Sopenharmony_ci#else 148c2ecf20Sopenharmony_ci# if (__riscv_xlen < 64) 158c2ecf20Sopenharmony_ci# error "64-bit atomics require XLEN to be at least 64" 168c2ecf20Sopenharmony_ci# endif 178c2ecf20Sopenharmony_ci#endif 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <asm/cmpxchg.h> 208c2ecf20Sopenharmony_ci#include <asm/barrier.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#define __atomic_acquire_fence() \ 238c2ecf20Sopenharmony_ci __asm__ __volatile__(RISCV_ACQUIRE_BARRIER "" ::: "memory") 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define __atomic_release_fence() \ 268c2ecf20Sopenharmony_ci __asm__ __volatile__(RISCV_RELEASE_BARRIER "" ::: "memory"); 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic __always_inline int atomic_read(const atomic_t *v) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci return READ_ONCE(v->counter); 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_cistatic __always_inline void atomic_set(atomic_t *v, int i) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci WRITE_ONCE(v->counter, i); 358c2ecf20Sopenharmony_ci} 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#ifndef CONFIG_GENERIC_ATOMIC64 388c2ecf20Sopenharmony_ci#define ATOMIC64_INIT(i) { (i) } 398c2ecf20Sopenharmony_cistatic __always_inline s64 atomic64_read(const atomic64_t *v) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci return READ_ONCE(v->counter); 428c2ecf20Sopenharmony_ci} 438c2ecf20Sopenharmony_cistatic __always_inline void atomic64_set(atomic64_t *v, s64 i) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci WRITE_ONCE(v->counter, i); 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci#endif 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/* 508c2ecf20Sopenharmony_ci * First, the atomic ops that have no ordering constraints and therefor don't 518c2ecf20Sopenharmony_ci * have the AQ or RL bits set. These don't return anything, so there's only 528c2ecf20Sopenharmony_ci * one version to worry about. 538c2ecf20Sopenharmony_ci */ 548c2ecf20Sopenharmony_ci#define ATOMIC_OP(op, asm_op, I, asm_type, c_type, prefix) \ 558c2ecf20Sopenharmony_cistatic __always_inline \ 568c2ecf20Sopenharmony_civoid atomic##prefix##_##op(c_type i, atomic##prefix##_t *v) \ 578c2ecf20Sopenharmony_ci{ \ 588c2ecf20Sopenharmony_ci __asm__ __volatile__ ( \ 598c2ecf20Sopenharmony_ci " amo" #asm_op "." #asm_type " zero, %1, %0" \ 608c2ecf20Sopenharmony_ci : "+A" (v->counter) \ 618c2ecf20Sopenharmony_ci : "r" (I) \ 628c2ecf20Sopenharmony_ci : "memory"); \ 638c2ecf20Sopenharmony_ci} \ 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci#ifdef CONFIG_GENERIC_ATOMIC64 668c2ecf20Sopenharmony_ci#define ATOMIC_OPS(op, asm_op, I) \ 678c2ecf20Sopenharmony_ci ATOMIC_OP (op, asm_op, I, w, int, ) 688c2ecf20Sopenharmony_ci#else 698c2ecf20Sopenharmony_ci#define ATOMIC_OPS(op, asm_op, I) \ 708c2ecf20Sopenharmony_ci ATOMIC_OP (op, asm_op, I, w, int, ) \ 718c2ecf20Sopenharmony_ci ATOMIC_OP (op, asm_op, I, d, s64, 64) 728c2ecf20Sopenharmony_ci#endif 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ciATOMIC_OPS(add, add, i) 758c2ecf20Sopenharmony_ciATOMIC_OPS(sub, add, -i) 768c2ecf20Sopenharmony_ciATOMIC_OPS(and, and, i) 778c2ecf20Sopenharmony_ciATOMIC_OPS( or, or, i) 788c2ecf20Sopenharmony_ciATOMIC_OPS(xor, xor, i) 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci#undef ATOMIC_OP 818c2ecf20Sopenharmony_ci#undef ATOMIC_OPS 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci/* 848c2ecf20Sopenharmony_ci * Atomic ops that have ordered, relaxed, acquire, and release variants. 858c2ecf20Sopenharmony_ci * There's two flavors of these: the arithmatic ops have both fetch and return 868c2ecf20Sopenharmony_ci * versions, while the logical ops only have fetch versions. 878c2ecf20Sopenharmony_ci */ 888c2ecf20Sopenharmony_ci#define ATOMIC_FETCH_OP(op, asm_op, I, asm_type, c_type, prefix) \ 898c2ecf20Sopenharmony_cistatic __always_inline \ 908c2ecf20Sopenharmony_cic_type atomic##prefix##_fetch_##op##_relaxed(c_type i, \ 918c2ecf20Sopenharmony_ci atomic##prefix##_t *v) \ 928c2ecf20Sopenharmony_ci{ \ 938c2ecf20Sopenharmony_ci register c_type ret; \ 948c2ecf20Sopenharmony_ci __asm__ __volatile__ ( \ 958c2ecf20Sopenharmony_ci " amo" #asm_op "." #asm_type " %1, %2, %0" \ 968c2ecf20Sopenharmony_ci : "+A" (v->counter), "=r" (ret) \ 978c2ecf20Sopenharmony_ci : "r" (I) \ 988c2ecf20Sopenharmony_ci : "memory"); \ 998c2ecf20Sopenharmony_ci return ret; \ 1008c2ecf20Sopenharmony_ci} \ 1018c2ecf20Sopenharmony_cistatic __always_inline \ 1028c2ecf20Sopenharmony_cic_type atomic##prefix##_fetch_##op(c_type i, atomic##prefix##_t *v) \ 1038c2ecf20Sopenharmony_ci{ \ 1048c2ecf20Sopenharmony_ci register c_type ret; \ 1058c2ecf20Sopenharmony_ci __asm__ __volatile__ ( \ 1068c2ecf20Sopenharmony_ci " amo" #asm_op "." #asm_type ".aqrl %1, %2, %0" \ 1078c2ecf20Sopenharmony_ci : "+A" (v->counter), "=r" (ret) \ 1088c2ecf20Sopenharmony_ci : "r" (I) \ 1098c2ecf20Sopenharmony_ci : "memory"); \ 1108c2ecf20Sopenharmony_ci return ret; \ 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci#define ATOMIC_OP_RETURN(op, asm_op, c_op, I, asm_type, c_type, prefix) \ 1148c2ecf20Sopenharmony_cistatic __always_inline \ 1158c2ecf20Sopenharmony_cic_type atomic##prefix##_##op##_return_relaxed(c_type i, \ 1168c2ecf20Sopenharmony_ci atomic##prefix##_t *v) \ 1178c2ecf20Sopenharmony_ci{ \ 1188c2ecf20Sopenharmony_ci return atomic##prefix##_fetch_##op##_relaxed(i, v) c_op I; \ 1198c2ecf20Sopenharmony_ci} \ 1208c2ecf20Sopenharmony_cistatic __always_inline \ 1218c2ecf20Sopenharmony_cic_type atomic##prefix##_##op##_return(c_type i, atomic##prefix##_t *v) \ 1228c2ecf20Sopenharmony_ci{ \ 1238c2ecf20Sopenharmony_ci return atomic##prefix##_fetch_##op(i, v) c_op I; \ 1248c2ecf20Sopenharmony_ci} 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci#ifdef CONFIG_GENERIC_ATOMIC64 1278c2ecf20Sopenharmony_ci#define ATOMIC_OPS(op, asm_op, c_op, I) \ 1288c2ecf20Sopenharmony_ci ATOMIC_FETCH_OP( op, asm_op, I, w, int, ) \ 1298c2ecf20Sopenharmony_ci ATOMIC_OP_RETURN(op, asm_op, c_op, I, w, int, ) 1308c2ecf20Sopenharmony_ci#else 1318c2ecf20Sopenharmony_ci#define ATOMIC_OPS(op, asm_op, c_op, I) \ 1328c2ecf20Sopenharmony_ci ATOMIC_FETCH_OP( op, asm_op, I, w, int, ) \ 1338c2ecf20Sopenharmony_ci ATOMIC_OP_RETURN(op, asm_op, c_op, I, w, int, ) \ 1348c2ecf20Sopenharmony_ci ATOMIC_FETCH_OP( op, asm_op, I, d, s64, 64) \ 1358c2ecf20Sopenharmony_ci ATOMIC_OP_RETURN(op, asm_op, c_op, I, d, s64, 64) 1368c2ecf20Sopenharmony_ci#endif 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ciATOMIC_OPS(add, add, +, i) 1398c2ecf20Sopenharmony_ciATOMIC_OPS(sub, add, +, -i) 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci#define atomic_add_return_relaxed atomic_add_return_relaxed 1428c2ecf20Sopenharmony_ci#define atomic_sub_return_relaxed atomic_sub_return_relaxed 1438c2ecf20Sopenharmony_ci#define atomic_add_return atomic_add_return 1448c2ecf20Sopenharmony_ci#define atomic_sub_return atomic_sub_return 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci#define atomic_fetch_add_relaxed atomic_fetch_add_relaxed 1478c2ecf20Sopenharmony_ci#define atomic_fetch_sub_relaxed atomic_fetch_sub_relaxed 1488c2ecf20Sopenharmony_ci#define atomic_fetch_add atomic_fetch_add 1498c2ecf20Sopenharmony_ci#define atomic_fetch_sub atomic_fetch_sub 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci#ifndef CONFIG_GENERIC_ATOMIC64 1528c2ecf20Sopenharmony_ci#define atomic64_add_return_relaxed atomic64_add_return_relaxed 1538c2ecf20Sopenharmony_ci#define atomic64_sub_return_relaxed atomic64_sub_return_relaxed 1548c2ecf20Sopenharmony_ci#define atomic64_add_return atomic64_add_return 1558c2ecf20Sopenharmony_ci#define atomic64_sub_return atomic64_sub_return 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci#define atomic64_fetch_add_relaxed atomic64_fetch_add_relaxed 1588c2ecf20Sopenharmony_ci#define atomic64_fetch_sub_relaxed atomic64_fetch_sub_relaxed 1598c2ecf20Sopenharmony_ci#define atomic64_fetch_add atomic64_fetch_add 1608c2ecf20Sopenharmony_ci#define atomic64_fetch_sub atomic64_fetch_sub 1618c2ecf20Sopenharmony_ci#endif 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci#undef ATOMIC_OPS 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci#ifdef CONFIG_GENERIC_ATOMIC64 1668c2ecf20Sopenharmony_ci#define ATOMIC_OPS(op, asm_op, I) \ 1678c2ecf20Sopenharmony_ci ATOMIC_FETCH_OP(op, asm_op, I, w, int, ) 1688c2ecf20Sopenharmony_ci#else 1698c2ecf20Sopenharmony_ci#define ATOMIC_OPS(op, asm_op, I) \ 1708c2ecf20Sopenharmony_ci ATOMIC_FETCH_OP(op, asm_op, I, w, int, ) \ 1718c2ecf20Sopenharmony_ci ATOMIC_FETCH_OP(op, asm_op, I, d, s64, 64) 1728c2ecf20Sopenharmony_ci#endif 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ciATOMIC_OPS(and, and, i) 1758c2ecf20Sopenharmony_ciATOMIC_OPS( or, or, i) 1768c2ecf20Sopenharmony_ciATOMIC_OPS(xor, xor, i) 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci#define atomic_fetch_and_relaxed atomic_fetch_and_relaxed 1798c2ecf20Sopenharmony_ci#define atomic_fetch_or_relaxed atomic_fetch_or_relaxed 1808c2ecf20Sopenharmony_ci#define atomic_fetch_xor_relaxed atomic_fetch_xor_relaxed 1818c2ecf20Sopenharmony_ci#define atomic_fetch_and atomic_fetch_and 1828c2ecf20Sopenharmony_ci#define atomic_fetch_or atomic_fetch_or 1838c2ecf20Sopenharmony_ci#define atomic_fetch_xor atomic_fetch_xor 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci#ifndef CONFIG_GENERIC_ATOMIC64 1868c2ecf20Sopenharmony_ci#define atomic64_fetch_and_relaxed atomic64_fetch_and_relaxed 1878c2ecf20Sopenharmony_ci#define atomic64_fetch_or_relaxed atomic64_fetch_or_relaxed 1888c2ecf20Sopenharmony_ci#define atomic64_fetch_xor_relaxed atomic64_fetch_xor_relaxed 1898c2ecf20Sopenharmony_ci#define atomic64_fetch_and atomic64_fetch_and 1908c2ecf20Sopenharmony_ci#define atomic64_fetch_or atomic64_fetch_or 1918c2ecf20Sopenharmony_ci#define atomic64_fetch_xor atomic64_fetch_xor 1928c2ecf20Sopenharmony_ci#endif 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci#undef ATOMIC_OPS 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci#undef ATOMIC_FETCH_OP 1978c2ecf20Sopenharmony_ci#undef ATOMIC_OP_RETURN 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci/* This is required to provide a full barrier on success. */ 2008c2ecf20Sopenharmony_cistatic __always_inline int atomic_fetch_add_unless(atomic_t *v, int a, int u) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci int prev, rc; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci __asm__ __volatile__ ( 2058c2ecf20Sopenharmony_ci "0: lr.w %[p], %[c]\n" 2068c2ecf20Sopenharmony_ci " beq %[p], %[u], 1f\n" 2078c2ecf20Sopenharmony_ci " add %[rc], %[p], %[a]\n" 2088c2ecf20Sopenharmony_ci " sc.w.rl %[rc], %[rc], %[c]\n" 2098c2ecf20Sopenharmony_ci " bnez %[rc], 0b\n" 2108c2ecf20Sopenharmony_ci " fence rw, rw\n" 2118c2ecf20Sopenharmony_ci "1:\n" 2128c2ecf20Sopenharmony_ci : [p]"=&r" (prev), [rc]"=&r" (rc), [c]"+A" (v->counter) 2138c2ecf20Sopenharmony_ci : [a]"r" (a), [u]"r" (u) 2148c2ecf20Sopenharmony_ci : "memory"); 2158c2ecf20Sopenharmony_ci return prev; 2168c2ecf20Sopenharmony_ci} 2178c2ecf20Sopenharmony_ci#define atomic_fetch_add_unless atomic_fetch_add_unless 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci#ifndef CONFIG_GENERIC_ATOMIC64 2208c2ecf20Sopenharmony_cistatic __always_inline s64 atomic64_fetch_add_unless(atomic64_t *v, s64 a, s64 u) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci s64 prev; 2238c2ecf20Sopenharmony_ci long rc; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci __asm__ __volatile__ ( 2268c2ecf20Sopenharmony_ci "0: lr.d %[p], %[c]\n" 2278c2ecf20Sopenharmony_ci " beq %[p], %[u], 1f\n" 2288c2ecf20Sopenharmony_ci " add %[rc], %[p], %[a]\n" 2298c2ecf20Sopenharmony_ci " sc.d.rl %[rc], %[rc], %[c]\n" 2308c2ecf20Sopenharmony_ci " bnez %[rc], 0b\n" 2318c2ecf20Sopenharmony_ci " fence rw, rw\n" 2328c2ecf20Sopenharmony_ci "1:\n" 2338c2ecf20Sopenharmony_ci : [p]"=&r" (prev), [rc]"=&r" (rc), [c]"+A" (v->counter) 2348c2ecf20Sopenharmony_ci : [a]"r" (a), [u]"r" (u) 2358c2ecf20Sopenharmony_ci : "memory"); 2368c2ecf20Sopenharmony_ci return prev; 2378c2ecf20Sopenharmony_ci} 2388c2ecf20Sopenharmony_ci#define atomic64_fetch_add_unless atomic64_fetch_add_unless 2398c2ecf20Sopenharmony_ci#endif 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci/* 2428c2ecf20Sopenharmony_ci * atomic_{cmp,}xchg is required to have exactly the same ordering semantics as 2438c2ecf20Sopenharmony_ci * {cmp,}xchg and the operations that return, so they need a full barrier. 2448c2ecf20Sopenharmony_ci */ 2458c2ecf20Sopenharmony_ci#define ATOMIC_OP(c_t, prefix, size) \ 2468c2ecf20Sopenharmony_cistatic __always_inline \ 2478c2ecf20Sopenharmony_cic_t atomic##prefix##_xchg_relaxed(atomic##prefix##_t *v, c_t n) \ 2488c2ecf20Sopenharmony_ci{ \ 2498c2ecf20Sopenharmony_ci return __xchg_relaxed(&(v->counter), n, size); \ 2508c2ecf20Sopenharmony_ci} \ 2518c2ecf20Sopenharmony_cistatic __always_inline \ 2528c2ecf20Sopenharmony_cic_t atomic##prefix##_xchg_acquire(atomic##prefix##_t *v, c_t n) \ 2538c2ecf20Sopenharmony_ci{ \ 2548c2ecf20Sopenharmony_ci return __xchg_acquire(&(v->counter), n, size); \ 2558c2ecf20Sopenharmony_ci} \ 2568c2ecf20Sopenharmony_cistatic __always_inline \ 2578c2ecf20Sopenharmony_cic_t atomic##prefix##_xchg_release(atomic##prefix##_t *v, c_t n) \ 2588c2ecf20Sopenharmony_ci{ \ 2598c2ecf20Sopenharmony_ci return __xchg_release(&(v->counter), n, size); \ 2608c2ecf20Sopenharmony_ci} \ 2618c2ecf20Sopenharmony_cistatic __always_inline \ 2628c2ecf20Sopenharmony_cic_t atomic##prefix##_xchg(atomic##prefix##_t *v, c_t n) \ 2638c2ecf20Sopenharmony_ci{ \ 2648c2ecf20Sopenharmony_ci return __xchg(&(v->counter), n, size); \ 2658c2ecf20Sopenharmony_ci} \ 2668c2ecf20Sopenharmony_cistatic __always_inline \ 2678c2ecf20Sopenharmony_cic_t atomic##prefix##_cmpxchg_relaxed(atomic##prefix##_t *v, \ 2688c2ecf20Sopenharmony_ci c_t o, c_t n) \ 2698c2ecf20Sopenharmony_ci{ \ 2708c2ecf20Sopenharmony_ci return __cmpxchg_relaxed(&(v->counter), o, n, size); \ 2718c2ecf20Sopenharmony_ci} \ 2728c2ecf20Sopenharmony_cistatic __always_inline \ 2738c2ecf20Sopenharmony_cic_t atomic##prefix##_cmpxchg_acquire(atomic##prefix##_t *v, \ 2748c2ecf20Sopenharmony_ci c_t o, c_t n) \ 2758c2ecf20Sopenharmony_ci{ \ 2768c2ecf20Sopenharmony_ci return __cmpxchg_acquire(&(v->counter), o, n, size); \ 2778c2ecf20Sopenharmony_ci} \ 2788c2ecf20Sopenharmony_cistatic __always_inline \ 2798c2ecf20Sopenharmony_cic_t atomic##prefix##_cmpxchg_release(atomic##prefix##_t *v, \ 2808c2ecf20Sopenharmony_ci c_t o, c_t n) \ 2818c2ecf20Sopenharmony_ci{ \ 2828c2ecf20Sopenharmony_ci return __cmpxchg_release(&(v->counter), o, n, size); \ 2838c2ecf20Sopenharmony_ci} \ 2848c2ecf20Sopenharmony_cistatic __always_inline \ 2858c2ecf20Sopenharmony_cic_t atomic##prefix##_cmpxchg(atomic##prefix##_t *v, c_t o, c_t n) \ 2868c2ecf20Sopenharmony_ci{ \ 2878c2ecf20Sopenharmony_ci return __cmpxchg(&(v->counter), o, n, size); \ 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci#ifdef CONFIG_GENERIC_ATOMIC64 2918c2ecf20Sopenharmony_ci#define ATOMIC_OPS() \ 2928c2ecf20Sopenharmony_ci ATOMIC_OP(int, , 4) 2938c2ecf20Sopenharmony_ci#else 2948c2ecf20Sopenharmony_ci#define ATOMIC_OPS() \ 2958c2ecf20Sopenharmony_ci ATOMIC_OP(int, , 4) \ 2968c2ecf20Sopenharmony_ci ATOMIC_OP(s64, 64, 8) 2978c2ecf20Sopenharmony_ci#endif 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ciATOMIC_OPS() 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci#define atomic_xchg_relaxed atomic_xchg_relaxed 3028c2ecf20Sopenharmony_ci#define atomic_xchg_acquire atomic_xchg_acquire 3038c2ecf20Sopenharmony_ci#define atomic_xchg_release atomic_xchg_release 3048c2ecf20Sopenharmony_ci#define atomic_xchg atomic_xchg 3058c2ecf20Sopenharmony_ci#define atomic_cmpxchg_relaxed atomic_cmpxchg_relaxed 3068c2ecf20Sopenharmony_ci#define atomic_cmpxchg_acquire atomic_cmpxchg_acquire 3078c2ecf20Sopenharmony_ci#define atomic_cmpxchg_release atomic_cmpxchg_release 3088c2ecf20Sopenharmony_ci#define atomic_cmpxchg atomic_cmpxchg 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci#undef ATOMIC_OPS 3118c2ecf20Sopenharmony_ci#undef ATOMIC_OP 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_cistatic __always_inline int atomic_sub_if_positive(atomic_t *v, int offset) 3148c2ecf20Sopenharmony_ci{ 3158c2ecf20Sopenharmony_ci int prev, rc; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci __asm__ __volatile__ ( 3188c2ecf20Sopenharmony_ci "0: lr.w %[p], %[c]\n" 3198c2ecf20Sopenharmony_ci " sub %[rc], %[p], %[o]\n" 3208c2ecf20Sopenharmony_ci " bltz %[rc], 1f\n" 3218c2ecf20Sopenharmony_ci " sc.w.rl %[rc], %[rc], %[c]\n" 3228c2ecf20Sopenharmony_ci " bnez %[rc], 0b\n" 3238c2ecf20Sopenharmony_ci " fence rw, rw\n" 3248c2ecf20Sopenharmony_ci "1:\n" 3258c2ecf20Sopenharmony_ci : [p]"=&r" (prev), [rc]"=&r" (rc), [c]"+A" (v->counter) 3268c2ecf20Sopenharmony_ci : [o]"r" (offset) 3278c2ecf20Sopenharmony_ci : "memory"); 3288c2ecf20Sopenharmony_ci return prev - offset; 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci#define atomic_dec_if_positive(v) atomic_sub_if_positive(v, 1) 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci#ifndef CONFIG_GENERIC_ATOMIC64 3348c2ecf20Sopenharmony_cistatic __always_inline s64 atomic64_sub_if_positive(atomic64_t *v, s64 offset) 3358c2ecf20Sopenharmony_ci{ 3368c2ecf20Sopenharmony_ci s64 prev; 3378c2ecf20Sopenharmony_ci long rc; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci __asm__ __volatile__ ( 3408c2ecf20Sopenharmony_ci "0: lr.d %[p], %[c]\n" 3418c2ecf20Sopenharmony_ci " sub %[rc], %[p], %[o]\n" 3428c2ecf20Sopenharmony_ci " bltz %[rc], 1f\n" 3438c2ecf20Sopenharmony_ci " sc.d.rl %[rc], %[rc], %[c]\n" 3448c2ecf20Sopenharmony_ci " bnez %[rc], 0b\n" 3458c2ecf20Sopenharmony_ci " fence rw, rw\n" 3468c2ecf20Sopenharmony_ci "1:\n" 3478c2ecf20Sopenharmony_ci : [p]"=&r" (prev), [rc]"=&r" (rc), [c]"+A" (v->counter) 3488c2ecf20Sopenharmony_ci : [o]"r" (offset) 3498c2ecf20Sopenharmony_ci : "memory"); 3508c2ecf20Sopenharmony_ci return prev - offset; 3518c2ecf20Sopenharmony_ci} 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci#define atomic64_dec_if_positive(v) atomic64_sub_if_positive(v, 1) 3548c2ecf20Sopenharmony_ci#endif 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci#endif /* _ASM_RISCV_ATOMIC_H */ 357