18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef _ASM_IA64_ATOMIC_H 38c2ecf20Sopenharmony_ci#define _ASM_IA64_ATOMIC_H 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci/* 68c2ecf20Sopenharmony_ci * Atomic operations that C can't guarantee us. Useful for 78c2ecf20Sopenharmony_ci * resource counting etc.. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * NOTE: don't mess with the types below! The "unsigned long" and 108c2ecf20Sopenharmony_ci * "int" types were carefully placed so as to ensure proper operation 118c2ecf20Sopenharmony_ci * of the macros. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Copyright (C) 1998, 1999, 2002-2003 Hewlett-Packard Co 148c2ecf20Sopenharmony_ci * David Mosberger-Tang <davidm@hpl.hp.com> 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci#include <linux/types.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <asm/intrinsics.h> 198c2ecf20Sopenharmony_ci#include <asm/barrier.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#define ATOMIC64_INIT(i) { (i) } 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define atomic_read(v) READ_ONCE((v)->counter) 258c2ecf20Sopenharmony_ci#define atomic64_read(v) READ_ONCE((v)->counter) 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define atomic_set(v,i) WRITE_ONCE(((v)->counter), (i)) 288c2ecf20Sopenharmony_ci#define atomic64_set(v,i) WRITE_ONCE(((v)->counter), (i)) 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define ATOMIC_OP(op, c_op) \ 318c2ecf20Sopenharmony_cistatic __inline__ int \ 328c2ecf20Sopenharmony_ciia64_atomic_##op (int i, atomic_t *v) \ 338c2ecf20Sopenharmony_ci{ \ 348c2ecf20Sopenharmony_ci __s32 old, new; \ 358c2ecf20Sopenharmony_ci CMPXCHG_BUGCHECK_DECL \ 368c2ecf20Sopenharmony_ci \ 378c2ecf20Sopenharmony_ci do { \ 388c2ecf20Sopenharmony_ci CMPXCHG_BUGCHECK(v); \ 398c2ecf20Sopenharmony_ci old = atomic_read(v); \ 408c2ecf20Sopenharmony_ci new = old c_op i; \ 418c2ecf20Sopenharmony_ci } while (ia64_cmpxchg(acq, v, old, new, sizeof(atomic_t)) != old); \ 428c2ecf20Sopenharmony_ci return new; \ 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#define ATOMIC_FETCH_OP(op, c_op) \ 468c2ecf20Sopenharmony_cistatic __inline__ int \ 478c2ecf20Sopenharmony_ciia64_atomic_fetch_##op (int i, atomic_t *v) \ 488c2ecf20Sopenharmony_ci{ \ 498c2ecf20Sopenharmony_ci __s32 old, new; \ 508c2ecf20Sopenharmony_ci CMPXCHG_BUGCHECK_DECL \ 518c2ecf20Sopenharmony_ci \ 528c2ecf20Sopenharmony_ci do { \ 538c2ecf20Sopenharmony_ci CMPXCHG_BUGCHECK(v); \ 548c2ecf20Sopenharmony_ci old = atomic_read(v); \ 558c2ecf20Sopenharmony_ci new = old c_op i; \ 568c2ecf20Sopenharmony_ci } while (ia64_cmpxchg(acq, v, old, new, sizeof(atomic_t)) != old); \ 578c2ecf20Sopenharmony_ci return old; \ 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci#define ATOMIC_OPS(op, c_op) \ 618c2ecf20Sopenharmony_ci ATOMIC_OP(op, c_op) \ 628c2ecf20Sopenharmony_ci ATOMIC_FETCH_OP(op, c_op) 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ciATOMIC_OPS(add, +) 658c2ecf20Sopenharmony_ciATOMIC_OPS(sub, -) 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci#ifdef __OPTIMIZE__ 688c2ecf20Sopenharmony_ci#define __ia64_atomic_const(i) \ 698c2ecf20Sopenharmony_ci static const int __ia64_atomic_p = __builtin_constant_p(i) ? \ 708c2ecf20Sopenharmony_ci ((i) == 1 || (i) == 4 || (i) == 8 || (i) == 16 || \ 718c2ecf20Sopenharmony_ci (i) == -1 || (i) == -4 || (i) == -8 || (i) == -16) : 0;\ 728c2ecf20Sopenharmony_ci __ia64_atomic_p 738c2ecf20Sopenharmony_ci#else 748c2ecf20Sopenharmony_ci#define __ia64_atomic_const(i) 0 758c2ecf20Sopenharmony_ci#endif 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci#define atomic_add_return(i,v) \ 788c2ecf20Sopenharmony_ci({ \ 798c2ecf20Sopenharmony_ci int __ia64_aar_i = (i); \ 808c2ecf20Sopenharmony_ci __ia64_atomic_const(i) \ 818c2ecf20Sopenharmony_ci ? ia64_fetch_and_add(__ia64_aar_i, &(v)->counter) \ 828c2ecf20Sopenharmony_ci : ia64_atomic_add(__ia64_aar_i, v); \ 838c2ecf20Sopenharmony_ci}) 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci#define atomic_sub_return(i,v) \ 868c2ecf20Sopenharmony_ci({ \ 878c2ecf20Sopenharmony_ci int __ia64_asr_i = (i); \ 888c2ecf20Sopenharmony_ci __ia64_atomic_const(i) \ 898c2ecf20Sopenharmony_ci ? ia64_fetch_and_add(-__ia64_asr_i, &(v)->counter) \ 908c2ecf20Sopenharmony_ci : ia64_atomic_sub(__ia64_asr_i, v); \ 918c2ecf20Sopenharmony_ci}) 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci#define atomic_fetch_add(i,v) \ 948c2ecf20Sopenharmony_ci({ \ 958c2ecf20Sopenharmony_ci int __ia64_aar_i = (i); \ 968c2ecf20Sopenharmony_ci __ia64_atomic_const(i) \ 978c2ecf20Sopenharmony_ci ? ia64_fetchadd(__ia64_aar_i, &(v)->counter, acq) \ 988c2ecf20Sopenharmony_ci : ia64_atomic_fetch_add(__ia64_aar_i, v); \ 998c2ecf20Sopenharmony_ci}) 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci#define atomic_fetch_sub(i,v) \ 1028c2ecf20Sopenharmony_ci({ \ 1038c2ecf20Sopenharmony_ci int __ia64_asr_i = (i); \ 1048c2ecf20Sopenharmony_ci __ia64_atomic_const(i) \ 1058c2ecf20Sopenharmony_ci ? ia64_fetchadd(-__ia64_asr_i, &(v)->counter, acq) \ 1068c2ecf20Sopenharmony_ci : ia64_atomic_fetch_sub(__ia64_asr_i, v); \ 1078c2ecf20Sopenharmony_ci}) 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ciATOMIC_FETCH_OP(and, &) 1108c2ecf20Sopenharmony_ciATOMIC_FETCH_OP(or, |) 1118c2ecf20Sopenharmony_ciATOMIC_FETCH_OP(xor, ^) 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci#define atomic_and(i,v) (void)ia64_atomic_fetch_and(i,v) 1148c2ecf20Sopenharmony_ci#define atomic_or(i,v) (void)ia64_atomic_fetch_or(i,v) 1158c2ecf20Sopenharmony_ci#define atomic_xor(i,v) (void)ia64_atomic_fetch_xor(i,v) 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci#define atomic_fetch_and(i,v) ia64_atomic_fetch_and(i,v) 1188c2ecf20Sopenharmony_ci#define atomic_fetch_or(i,v) ia64_atomic_fetch_or(i,v) 1198c2ecf20Sopenharmony_ci#define atomic_fetch_xor(i,v) ia64_atomic_fetch_xor(i,v) 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci#undef ATOMIC_OPS 1228c2ecf20Sopenharmony_ci#undef ATOMIC_FETCH_OP 1238c2ecf20Sopenharmony_ci#undef ATOMIC_OP 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci#define ATOMIC64_OP(op, c_op) \ 1268c2ecf20Sopenharmony_cistatic __inline__ s64 \ 1278c2ecf20Sopenharmony_ciia64_atomic64_##op (s64 i, atomic64_t *v) \ 1288c2ecf20Sopenharmony_ci{ \ 1298c2ecf20Sopenharmony_ci s64 old, new; \ 1308c2ecf20Sopenharmony_ci CMPXCHG_BUGCHECK_DECL \ 1318c2ecf20Sopenharmony_ci \ 1328c2ecf20Sopenharmony_ci do { \ 1338c2ecf20Sopenharmony_ci CMPXCHG_BUGCHECK(v); \ 1348c2ecf20Sopenharmony_ci old = atomic64_read(v); \ 1358c2ecf20Sopenharmony_ci new = old c_op i; \ 1368c2ecf20Sopenharmony_ci } while (ia64_cmpxchg(acq, v, old, new, sizeof(atomic64_t)) != old); \ 1378c2ecf20Sopenharmony_ci return new; \ 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci#define ATOMIC64_FETCH_OP(op, c_op) \ 1418c2ecf20Sopenharmony_cistatic __inline__ s64 \ 1428c2ecf20Sopenharmony_ciia64_atomic64_fetch_##op (s64 i, atomic64_t *v) \ 1438c2ecf20Sopenharmony_ci{ \ 1448c2ecf20Sopenharmony_ci s64 old, new; \ 1458c2ecf20Sopenharmony_ci CMPXCHG_BUGCHECK_DECL \ 1468c2ecf20Sopenharmony_ci \ 1478c2ecf20Sopenharmony_ci do { \ 1488c2ecf20Sopenharmony_ci CMPXCHG_BUGCHECK(v); \ 1498c2ecf20Sopenharmony_ci old = atomic64_read(v); \ 1508c2ecf20Sopenharmony_ci new = old c_op i; \ 1518c2ecf20Sopenharmony_ci } while (ia64_cmpxchg(acq, v, old, new, sizeof(atomic64_t)) != old); \ 1528c2ecf20Sopenharmony_ci return old; \ 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci#define ATOMIC64_OPS(op, c_op) \ 1568c2ecf20Sopenharmony_ci ATOMIC64_OP(op, c_op) \ 1578c2ecf20Sopenharmony_ci ATOMIC64_FETCH_OP(op, c_op) 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ciATOMIC64_OPS(add, +) 1608c2ecf20Sopenharmony_ciATOMIC64_OPS(sub, -) 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci#define atomic64_add_return(i,v) \ 1638c2ecf20Sopenharmony_ci({ \ 1648c2ecf20Sopenharmony_ci s64 __ia64_aar_i = (i); \ 1658c2ecf20Sopenharmony_ci __ia64_atomic_const(i) \ 1668c2ecf20Sopenharmony_ci ? ia64_fetch_and_add(__ia64_aar_i, &(v)->counter) \ 1678c2ecf20Sopenharmony_ci : ia64_atomic64_add(__ia64_aar_i, v); \ 1688c2ecf20Sopenharmony_ci}) 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci#define atomic64_sub_return(i,v) \ 1718c2ecf20Sopenharmony_ci({ \ 1728c2ecf20Sopenharmony_ci s64 __ia64_asr_i = (i); \ 1738c2ecf20Sopenharmony_ci __ia64_atomic_const(i) \ 1748c2ecf20Sopenharmony_ci ? ia64_fetch_and_add(-__ia64_asr_i, &(v)->counter) \ 1758c2ecf20Sopenharmony_ci : ia64_atomic64_sub(__ia64_asr_i, v); \ 1768c2ecf20Sopenharmony_ci}) 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci#define atomic64_fetch_add(i,v) \ 1798c2ecf20Sopenharmony_ci({ \ 1808c2ecf20Sopenharmony_ci s64 __ia64_aar_i = (i); \ 1818c2ecf20Sopenharmony_ci __ia64_atomic_const(i) \ 1828c2ecf20Sopenharmony_ci ? ia64_fetchadd(__ia64_aar_i, &(v)->counter, acq) \ 1838c2ecf20Sopenharmony_ci : ia64_atomic64_fetch_add(__ia64_aar_i, v); \ 1848c2ecf20Sopenharmony_ci}) 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci#define atomic64_fetch_sub(i,v) \ 1878c2ecf20Sopenharmony_ci({ \ 1888c2ecf20Sopenharmony_ci s64 __ia64_asr_i = (i); \ 1898c2ecf20Sopenharmony_ci __ia64_atomic_const(i) \ 1908c2ecf20Sopenharmony_ci ? ia64_fetchadd(-__ia64_asr_i, &(v)->counter, acq) \ 1918c2ecf20Sopenharmony_ci : ia64_atomic64_fetch_sub(__ia64_asr_i, v); \ 1928c2ecf20Sopenharmony_ci}) 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ciATOMIC64_FETCH_OP(and, &) 1958c2ecf20Sopenharmony_ciATOMIC64_FETCH_OP(or, |) 1968c2ecf20Sopenharmony_ciATOMIC64_FETCH_OP(xor, ^) 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci#define atomic64_and(i,v) (void)ia64_atomic64_fetch_and(i,v) 1998c2ecf20Sopenharmony_ci#define atomic64_or(i,v) (void)ia64_atomic64_fetch_or(i,v) 2008c2ecf20Sopenharmony_ci#define atomic64_xor(i,v) (void)ia64_atomic64_fetch_xor(i,v) 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci#define atomic64_fetch_and(i,v) ia64_atomic64_fetch_and(i,v) 2038c2ecf20Sopenharmony_ci#define atomic64_fetch_or(i,v) ia64_atomic64_fetch_or(i,v) 2048c2ecf20Sopenharmony_ci#define atomic64_fetch_xor(i,v) ia64_atomic64_fetch_xor(i,v) 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci#undef ATOMIC64_OPS 2078c2ecf20Sopenharmony_ci#undef ATOMIC64_FETCH_OP 2088c2ecf20Sopenharmony_ci#undef ATOMIC64_OP 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new)) 2118c2ecf20Sopenharmony_ci#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci#define atomic64_cmpxchg(v, old, new) \ 2148c2ecf20Sopenharmony_ci (cmpxchg(&((v)->counter), old, new)) 2158c2ecf20Sopenharmony_ci#define atomic64_xchg(v, new) (xchg(&((v)->counter), new)) 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci#define atomic_add(i,v) (void)atomic_add_return((i), (v)) 2188c2ecf20Sopenharmony_ci#define atomic_sub(i,v) (void)atomic_sub_return((i), (v)) 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci#define atomic64_add(i,v) (void)atomic64_add_return((i), (v)) 2218c2ecf20Sopenharmony_ci#define atomic64_sub(i,v) (void)atomic64_sub_return((i), (v)) 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci#endif /* _ASM_IA64_ATOMIC_H */ 224