atomic-llsc.h (2751B)
1/* SPDX-License-Identifier: GPL-2.0-only */ 2 3#ifndef _ASM_ARC_ATOMIC_LLSC_H 4#define _ASM_ARC_ATOMIC_LLSC_H 5 6#define arch_atomic_set(v, i) WRITE_ONCE(((v)->counter), (i)) 7 8#define ATOMIC_OP(op, asm_op) \ 9static inline void arch_atomic_##op(int i, atomic_t *v) \ 10{ \ 11 unsigned int val; \ 12 \ 13 __asm__ __volatile__( \ 14 "1: llock %[val], [%[ctr]] \n" \ 15 " " #asm_op " %[val], %[val], %[i] \n" \ 16 " scond %[val], [%[ctr]] \n" \ 17 " bnz 1b \n" \ 18 : [val] "=&r" (val) /* Early clobber to prevent reg reuse */ \ 19 : [ctr] "r" (&v->counter), /* Not "m": llock only supports reg direct addr mode */ \ 20 [i] "ir" (i) \ 21 : "cc"); \ 22} \ 23 24#define ATOMIC_OP_RETURN(op, asm_op) \ 25static inline int arch_atomic_##op##_return_relaxed(int i, atomic_t *v) \ 26{ \ 27 unsigned int val; \ 28 \ 29 __asm__ __volatile__( \ 30 "1: llock %[val], [%[ctr]] \n" \ 31 " " #asm_op " %[val], %[val], %[i] \n" \ 32 " scond %[val], [%[ctr]] \n" \ 33 " bnz 1b \n" \ 34 : [val] "=&r" (val) \ 35 : [ctr] "r" (&v->counter), \ 36 [i] "ir" (i) \ 37 : "cc"); \ 38 \ 39 return val; \ 40} 41 42#define arch_atomic_add_return_relaxed arch_atomic_add_return_relaxed 43#define arch_atomic_sub_return_relaxed arch_atomic_sub_return_relaxed 44 45#define ATOMIC_FETCH_OP(op, asm_op) \ 46static inline int arch_atomic_fetch_##op##_relaxed(int i, atomic_t *v) \ 47{ \ 48 unsigned int val, orig; \ 49 \ 50 __asm__ __volatile__( \ 51 "1: llock %[orig], [%[ctr]] \n" \ 52 " " #asm_op " %[val], %[orig], %[i] \n" \ 53 " scond %[val], [%[ctr]] \n" \ 54 " bnz 1b \n" \ 55 : [val] "=&r" (val), \ 56 [orig] "=&r" (orig) \ 57 : [ctr] "r" (&v->counter), \ 58 [i] "ir" (i) \ 59 : "cc"); \ 60 \ 61 return orig; \ 62} 63 64#define arch_atomic_fetch_add_relaxed arch_atomic_fetch_add_relaxed 65#define arch_atomic_fetch_sub_relaxed arch_atomic_fetch_sub_relaxed 66 67#define arch_atomic_fetch_and_relaxed arch_atomic_fetch_and_relaxed 68#define arch_atomic_fetch_andnot_relaxed arch_atomic_fetch_andnot_relaxed 69#define arch_atomic_fetch_or_relaxed arch_atomic_fetch_or_relaxed 70#define arch_atomic_fetch_xor_relaxed arch_atomic_fetch_xor_relaxed 71 72#define ATOMIC_OPS(op, asm_op) \ 73 ATOMIC_OP(op, asm_op) \ 74 ATOMIC_OP_RETURN(op, asm_op) \ 75 ATOMIC_FETCH_OP(op, asm_op) 76 77ATOMIC_OPS(add, add) 78ATOMIC_OPS(sub, sub) 79 80#undef ATOMIC_OPS 81#define ATOMIC_OPS(op, asm_op) \ 82 ATOMIC_OP(op, asm_op) \ 83 ATOMIC_FETCH_OP(op, asm_op) 84 85ATOMIC_OPS(and, and) 86ATOMIC_OPS(andnot, bic) 87ATOMIC_OPS(or, or) 88ATOMIC_OPS(xor, xor) 89 90#define arch_atomic_andnot arch_atomic_andnot 91 92#undef ATOMIC_OPS 93#undef ATOMIC_FETCH_OP 94#undef ATOMIC_OP_RETURN 95#undef ATOMIC_OP 96 97#endif