^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright IBM Corp. 1999, 2016
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Denis Joseph Barrow,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Arnd Bergmann,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #ifndef __ARCH_S390_ATOMIC__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #define __ARCH_S390_ATOMIC__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/atomic_ops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/barrier.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/cmpxchg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static inline int atomic_read(const atomic_t *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) int c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) " l %0,%1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) : "=d" (c) : "Q" (v->counter));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) return c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static inline void atomic_set(atomic_t *v, int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) " st %1,%0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) : "=Q" (v->counter) : "d" (i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static inline int atomic_add_return(int i, atomic_t *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return __atomic_add_barrier(i, &v->counter) + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static inline int atomic_fetch_add(int i, atomic_t *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return __atomic_add_barrier(i, &v->counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static inline void atomic_add(int i, atomic_t *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * Order of conditions is important to circumvent gcc 10 bug:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * https://gcc.gnu.org/pipermail/gcc-patches/2020-July/549318.html
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if ((i > -129) && (i < 128) && __builtin_constant_p(i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) __atomic_add_const(i, &v->counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) __atomic_add(i, &v->counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define atomic_sub(_i, _v) atomic_add(-(int)(_i), _v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define atomic_sub_return(_i, _v) atomic_add_return(-(int)(_i), _v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define atomic_fetch_sub(_i, _v) atomic_fetch_add(-(int)(_i), _v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define ATOMIC_OPS(op) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static inline void atomic_##op(int i, atomic_t *v) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) __atomic_##op(i, &v->counter); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static inline int atomic_fetch_##op(int i, atomic_t *v) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return __atomic_##op##_barrier(i, &v->counter); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) ATOMIC_OPS(and)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ATOMIC_OPS(or)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) ATOMIC_OPS(xor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #undef ATOMIC_OPS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return __atomic_cmpxchg(&v->counter, old, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define ATOMIC64_INIT(i) { (i) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static inline s64 atomic64_read(const atomic64_t *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) s64 c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) " lg %0,%1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) : "=d" (c) : "Q" (v->counter));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static inline void atomic64_set(atomic64_t *v, s64 i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) " stg %1,%0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) : "=Q" (v->counter) : "d" (i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static inline s64 atomic64_add_return(s64 i, atomic64_t *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return __atomic64_add_barrier(i, (long *)&v->counter) + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static inline s64 atomic64_fetch_add(s64 i, atomic64_t *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return __atomic64_add_barrier(i, (long *)&v->counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static inline void atomic64_add(s64 i, atomic64_t *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * Order of conditions is important to circumvent gcc 10 bug:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * https://gcc.gnu.org/pipermail/gcc-patches/2020-July/549318.html
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if ((i > -129) && (i < 128) && __builtin_constant_p(i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) __atomic64_add_const(i, (long *)&v->counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) __atomic64_add(i, (long *)&v->counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static inline s64 atomic64_cmpxchg(atomic64_t *v, s64 old, s64 new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return __atomic64_cmpxchg((long *)&v->counter, old, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define ATOMIC64_OPS(op) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static inline void atomic64_##op(s64 i, atomic64_t *v) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) __atomic64_##op(i, (long *)&v->counter); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static inline long atomic64_fetch_##op(s64 i, atomic64_t *v) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return __atomic64_##op##_barrier(i, (long *)&v->counter); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ATOMIC64_OPS(and)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ATOMIC64_OPS(or)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ATOMIC64_OPS(xor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #undef ATOMIC64_OPS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #define atomic64_sub_return(_i, _v) atomic64_add_return(-(s64)(_i), _v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define atomic64_fetch_sub(_i, _v) atomic64_fetch_add(-(s64)(_i), _v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define atomic64_sub(_i, _v) atomic64_add(-(s64)(_i), _v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #endif /* __ARCH_S390_ATOMIC__ */