162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _ASM_IA64_ATOMIC_H 362306a36Sopenharmony_ci#define _ASM_IA64_ATOMIC_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci/* 662306a36Sopenharmony_ci * Atomic operations that C can't guarantee us. Useful for 762306a36Sopenharmony_ci * resource counting etc.. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * NOTE: don't mess with the types below! The "unsigned long" and 1062306a36Sopenharmony_ci * "int" types were carefully placed so as to ensure proper operation 1162306a36Sopenharmony_ci * of the macros. 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * Copyright (C) 1998, 1999, 2002-2003 Hewlett-Packard Co 1462306a36Sopenharmony_ci * David Mosberger-Tang <davidm@hpl.hp.com> 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci#include <linux/types.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <asm/intrinsics.h> 1962306a36Sopenharmony_ci#include <asm/barrier.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define ATOMIC64_INIT(i) { (i) } 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define arch_atomic_read(v) READ_ONCE((v)->counter) 2562306a36Sopenharmony_ci#define arch_atomic64_read(v) READ_ONCE((v)->counter) 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define arch_atomic_set(v,i) WRITE_ONCE(((v)->counter), (i)) 2862306a36Sopenharmony_ci#define arch_atomic64_set(v,i) WRITE_ONCE(((v)->counter), (i)) 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define ATOMIC_OP(op, c_op) \ 3162306a36Sopenharmony_cistatic __inline__ int \ 3262306a36Sopenharmony_ciia64_atomic_##op (int i, atomic_t *v) \ 3362306a36Sopenharmony_ci{ \ 3462306a36Sopenharmony_ci __s32 old, new; \ 3562306a36Sopenharmony_ci CMPXCHG_BUGCHECK_DECL \ 3662306a36Sopenharmony_ci \ 3762306a36Sopenharmony_ci do { \ 3862306a36Sopenharmony_ci CMPXCHG_BUGCHECK(v); \ 3962306a36Sopenharmony_ci old = arch_atomic_read(v); \ 4062306a36Sopenharmony_ci new = old c_op i; \ 4162306a36Sopenharmony_ci } while (ia64_cmpxchg(acq, v, old, new, sizeof(atomic_t)) != old); \ 4262306a36Sopenharmony_ci return new; \ 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#define ATOMIC_FETCH_OP(op, c_op) \ 4662306a36Sopenharmony_cistatic __inline__ int \ 4762306a36Sopenharmony_ciia64_atomic_fetch_##op (int i, atomic_t *v) \ 4862306a36Sopenharmony_ci{ \ 4962306a36Sopenharmony_ci __s32 old, new; \ 5062306a36Sopenharmony_ci CMPXCHG_BUGCHECK_DECL \ 5162306a36Sopenharmony_ci \ 5262306a36Sopenharmony_ci do { \ 5362306a36Sopenharmony_ci CMPXCHG_BUGCHECK(v); \ 5462306a36Sopenharmony_ci old = arch_atomic_read(v); \ 5562306a36Sopenharmony_ci new = old c_op i; \ 5662306a36Sopenharmony_ci } while (ia64_cmpxchg(acq, v, old, new, sizeof(atomic_t)) != old); \ 5762306a36Sopenharmony_ci return old; \ 5862306a36Sopenharmony_ci} 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#define ATOMIC_OPS(op, c_op) \ 6162306a36Sopenharmony_ci ATOMIC_OP(op, c_op) \ 6262306a36Sopenharmony_ci ATOMIC_FETCH_OP(op, c_op) 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ciATOMIC_OPS(add, +) 6562306a36Sopenharmony_ciATOMIC_OPS(sub, -) 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#ifdef __OPTIMIZE__ 6862306a36Sopenharmony_ci#define __ia64_atomic_const(i) \ 6962306a36Sopenharmony_ci static const int __ia64_atomic_p = __builtin_constant_p(i) ? \ 7062306a36Sopenharmony_ci ((i) == 1 || (i) == 4 || (i) == 8 || (i) == 16 || \ 7162306a36Sopenharmony_ci (i) == -1 || (i) == -4 || (i) == -8 || (i) == -16) : 0;\ 7262306a36Sopenharmony_ci __ia64_atomic_p 7362306a36Sopenharmony_ci#else 7462306a36Sopenharmony_ci#define __ia64_atomic_const(i) 0 7562306a36Sopenharmony_ci#endif 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci#define arch_atomic_add_return(i,v) \ 7862306a36Sopenharmony_ci({ \ 7962306a36Sopenharmony_ci int __ia64_aar_i = (i); \ 8062306a36Sopenharmony_ci __ia64_atomic_const(i) \ 8162306a36Sopenharmony_ci ? ia64_fetch_and_add(__ia64_aar_i, &(v)->counter) \ 8262306a36Sopenharmony_ci : ia64_atomic_add(__ia64_aar_i, v); \ 8362306a36Sopenharmony_ci}) 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci#define arch_atomic_sub_return(i,v) \ 8662306a36Sopenharmony_ci({ \ 8762306a36Sopenharmony_ci int __ia64_asr_i = (i); \ 8862306a36Sopenharmony_ci __ia64_atomic_const(i) \ 8962306a36Sopenharmony_ci ? ia64_fetch_and_add(-__ia64_asr_i, &(v)->counter) \ 9062306a36Sopenharmony_ci : ia64_atomic_sub(__ia64_asr_i, v); \ 9162306a36Sopenharmony_ci}) 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci#define arch_atomic_fetch_add(i,v) \ 9462306a36Sopenharmony_ci({ \ 9562306a36Sopenharmony_ci int __ia64_aar_i = (i); \ 9662306a36Sopenharmony_ci __ia64_atomic_const(i) \ 9762306a36Sopenharmony_ci ? ia64_fetchadd(__ia64_aar_i, &(v)->counter, acq) \ 9862306a36Sopenharmony_ci : ia64_atomic_fetch_add(__ia64_aar_i, v); \ 9962306a36Sopenharmony_ci}) 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci#define arch_atomic_fetch_sub(i,v) \ 10262306a36Sopenharmony_ci({ \ 10362306a36Sopenharmony_ci int __ia64_asr_i = (i); \ 10462306a36Sopenharmony_ci __ia64_atomic_const(i) \ 10562306a36Sopenharmony_ci ? ia64_fetchadd(-__ia64_asr_i, &(v)->counter, acq) \ 10662306a36Sopenharmony_ci : ia64_atomic_fetch_sub(__ia64_asr_i, v); \ 10762306a36Sopenharmony_ci}) 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ciATOMIC_FETCH_OP(and, &) 11062306a36Sopenharmony_ciATOMIC_FETCH_OP(or, |) 11162306a36Sopenharmony_ciATOMIC_FETCH_OP(xor, ^) 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci#define arch_atomic_and(i,v) (void)ia64_atomic_fetch_and(i,v) 11462306a36Sopenharmony_ci#define arch_atomic_or(i,v) (void)ia64_atomic_fetch_or(i,v) 11562306a36Sopenharmony_ci#define arch_atomic_xor(i,v) (void)ia64_atomic_fetch_xor(i,v) 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci#define arch_atomic_fetch_and(i,v) ia64_atomic_fetch_and(i,v) 11862306a36Sopenharmony_ci#define arch_atomic_fetch_or(i,v) ia64_atomic_fetch_or(i,v) 11962306a36Sopenharmony_ci#define arch_atomic_fetch_xor(i,v) ia64_atomic_fetch_xor(i,v) 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci#undef ATOMIC_OPS 12262306a36Sopenharmony_ci#undef ATOMIC_FETCH_OP 12362306a36Sopenharmony_ci#undef ATOMIC_OP 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci#define ATOMIC64_OP(op, c_op) \ 12662306a36Sopenharmony_cistatic __inline__ s64 \ 12762306a36Sopenharmony_ciia64_atomic64_##op (s64 i, atomic64_t *v) \ 12862306a36Sopenharmony_ci{ \ 12962306a36Sopenharmony_ci s64 old, new; \ 13062306a36Sopenharmony_ci CMPXCHG_BUGCHECK_DECL \ 13162306a36Sopenharmony_ci \ 13262306a36Sopenharmony_ci do { \ 13362306a36Sopenharmony_ci CMPXCHG_BUGCHECK(v); \ 13462306a36Sopenharmony_ci old = arch_atomic64_read(v); \ 13562306a36Sopenharmony_ci new = old c_op i; \ 13662306a36Sopenharmony_ci } while (ia64_cmpxchg(acq, v, old, new, sizeof(atomic64_t)) != old); \ 13762306a36Sopenharmony_ci return new; \ 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci#define ATOMIC64_FETCH_OP(op, c_op) \ 14162306a36Sopenharmony_cistatic __inline__ s64 \ 14262306a36Sopenharmony_ciia64_atomic64_fetch_##op (s64 i, atomic64_t *v) \ 14362306a36Sopenharmony_ci{ \ 14462306a36Sopenharmony_ci s64 old, new; \ 14562306a36Sopenharmony_ci CMPXCHG_BUGCHECK_DECL \ 14662306a36Sopenharmony_ci \ 14762306a36Sopenharmony_ci do { \ 14862306a36Sopenharmony_ci CMPXCHG_BUGCHECK(v); \ 14962306a36Sopenharmony_ci old = arch_atomic64_read(v); \ 15062306a36Sopenharmony_ci new = old c_op i; \ 15162306a36Sopenharmony_ci } while (ia64_cmpxchg(acq, v, old, new, sizeof(atomic64_t)) != old); \ 15262306a36Sopenharmony_ci return old; \ 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci#define ATOMIC64_OPS(op, c_op) \ 15662306a36Sopenharmony_ci ATOMIC64_OP(op, c_op) \ 15762306a36Sopenharmony_ci ATOMIC64_FETCH_OP(op, c_op) 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ciATOMIC64_OPS(add, +) 16062306a36Sopenharmony_ciATOMIC64_OPS(sub, -) 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci#define arch_atomic64_add_return(i,v) \ 16362306a36Sopenharmony_ci({ \ 16462306a36Sopenharmony_ci s64 __ia64_aar_i = (i); \ 16562306a36Sopenharmony_ci __ia64_atomic_const(i) \ 16662306a36Sopenharmony_ci ? ia64_fetch_and_add(__ia64_aar_i, &(v)->counter) \ 16762306a36Sopenharmony_ci : ia64_atomic64_add(__ia64_aar_i, v); \ 16862306a36Sopenharmony_ci}) 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci#define arch_atomic64_sub_return(i,v) \ 17162306a36Sopenharmony_ci({ \ 17262306a36Sopenharmony_ci s64 __ia64_asr_i = (i); \ 17362306a36Sopenharmony_ci __ia64_atomic_const(i) \ 17462306a36Sopenharmony_ci ? ia64_fetch_and_add(-__ia64_asr_i, &(v)->counter) \ 17562306a36Sopenharmony_ci : ia64_atomic64_sub(__ia64_asr_i, v); \ 17662306a36Sopenharmony_ci}) 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci#define arch_atomic64_fetch_add(i,v) \ 17962306a36Sopenharmony_ci({ \ 18062306a36Sopenharmony_ci s64 __ia64_aar_i = (i); \ 18162306a36Sopenharmony_ci __ia64_atomic_const(i) \ 18262306a36Sopenharmony_ci ? ia64_fetchadd(__ia64_aar_i, &(v)->counter, acq) \ 18362306a36Sopenharmony_ci : ia64_atomic64_fetch_add(__ia64_aar_i, v); \ 18462306a36Sopenharmony_ci}) 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci#define arch_atomic64_fetch_sub(i,v) \ 18762306a36Sopenharmony_ci({ \ 18862306a36Sopenharmony_ci s64 __ia64_asr_i = (i); \ 18962306a36Sopenharmony_ci __ia64_atomic_const(i) \ 19062306a36Sopenharmony_ci ? ia64_fetchadd(-__ia64_asr_i, &(v)->counter, acq) \ 19162306a36Sopenharmony_ci : ia64_atomic64_fetch_sub(__ia64_asr_i, v); \ 19262306a36Sopenharmony_ci}) 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ciATOMIC64_FETCH_OP(and, &) 19562306a36Sopenharmony_ciATOMIC64_FETCH_OP(or, |) 19662306a36Sopenharmony_ciATOMIC64_FETCH_OP(xor, ^) 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci#define arch_atomic64_and(i,v) (void)ia64_atomic64_fetch_and(i,v) 19962306a36Sopenharmony_ci#define arch_atomic64_or(i,v) (void)ia64_atomic64_fetch_or(i,v) 20062306a36Sopenharmony_ci#define arch_atomic64_xor(i,v) (void)ia64_atomic64_fetch_xor(i,v) 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci#define arch_atomic64_fetch_and(i,v) ia64_atomic64_fetch_and(i,v) 20362306a36Sopenharmony_ci#define arch_atomic64_fetch_or(i,v) ia64_atomic64_fetch_or(i,v) 20462306a36Sopenharmony_ci#define arch_atomic64_fetch_xor(i,v) ia64_atomic64_fetch_xor(i,v) 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci#undef ATOMIC64_OPS 20762306a36Sopenharmony_ci#undef ATOMIC64_FETCH_OP 20862306a36Sopenharmony_ci#undef ATOMIC64_OP 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci#define arch_atomic_add(i,v) (void)arch_atomic_add_return((i), (v)) 21162306a36Sopenharmony_ci#define arch_atomic_sub(i,v) (void)arch_atomic_sub_return((i), (v)) 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci#define arch_atomic64_add(i,v) (void)arch_atomic64_add_return((i), (v)) 21462306a36Sopenharmony_ci#define arch_atomic64_sub(i,v) (void)arch_atomic64_sub_return((i), (v)) 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci#endif /* _ASM_IA64_ATOMIC_H */ 217