1 /* SPDX-License-Identifier: GPL-2.0 */
3 * Low level function for atomic operations
5 * Copyright IBM Corp. 1999, 2016
8 #ifndef __ARCH_S390_ATOMIC_OPS__
9 #define __ARCH_S390_ATOMIC_OPS__
11 #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
13 #define __ATOMIC_OP(op_name, op_type, op_string, op_barrier) \
14 static inline op_type op_name(op_type val, op_type *ptr) \
19 op_string " %[old],%[val],%[ptr]\n" \
21 : [old] "=d" (old), [ptr] "+Q" (*ptr) \
22 : [val] "d" (val) : "cc", "memory"); \
26 #define __ATOMIC_OPS(op_name, op_type, op_string) \
27 __ATOMIC_OP(op_name, op_type, op_string, "\n") \
28 __ATOMIC_OP(op_name##_barrier, op_type, op_string, "bcr 14,0\n")
30 __ATOMIC_OPS(__atomic_add, int, "laa")
31 __ATOMIC_OPS(__atomic_and, int, "lan")
32 __ATOMIC_OPS(__atomic_or, int, "lao")
33 __ATOMIC_OPS(__atomic_xor, int, "lax")
35 __ATOMIC_OPS(__atomic64_add, long, "laag")
36 __ATOMIC_OPS(__atomic64_and, long, "lang")
37 __ATOMIC_OPS(__atomic64_or, long, "laog")
38 __ATOMIC_OPS(__atomic64_xor, long, "laxg")
43 static inline void __atomic_add_const(int val, int *ptr)
46 " asi %[ptr],%[val]\n"
47 : [ptr] "+Q" (*ptr) : [val] "i" (val) : "cc");
50 static inline void __atomic64_add_const(long val, long *ptr)
53 " agsi %[ptr],%[val]\n"
54 : [ptr] "+Q" (*ptr) : [val] "i" (val) : "cc");
57 #else /* CONFIG_HAVE_MARCH_Z196_FEATURES */
59 #define __ATOMIC_OP(op_name, op_string) \
60 static inline int op_name(int val, int *ptr) \
65 "0: lr %[new],%[old]\n" \
66 op_string " %[new],%[val]\n" \
67 " cs %[old],%[new],%[ptr]\n" \
69 : [old] "=d" (old), [new] "=&d" (new), [ptr] "+Q" (*ptr)\
70 : [val] "d" (val), "0" (*ptr) : "cc", "memory"); \
74 #define __ATOMIC_OPS(op_name, op_string) \
75 __ATOMIC_OP(op_name, op_string) \
76 __ATOMIC_OP(op_name##_barrier, op_string)
78 __ATOMIC_OPS(__atomic_add, "ar")
79 __ATOMIC_OPS(__atomic_and, "nr")
80 __ATOMIC_OPS(__atomic_or, "or")
81 __ATOMIC_OPS(__atomic_xor, "xr")
85 #define __ATOMIC64_OP(op_name, op_string) \
86 static inline long op_name(long val, long *ptr) \
91 "0: lgr %[new],%[old]\n" \
92 op_string " %[new],%[val]\n" \
93 " csg %[old],%[new],%[ptr]\n" \
95 : [old] "=d" (old), [new] "=&d" (new), [ptr] "+Q" (*ptr)\
96 : [val] "d" (val), "0" (*ptr) : "cc", "memory"); \
100 #define __ATOMIC64_OPS(op_name, op_string) \
101 __ATOMIC64_OP(op_name, op_string) \
102 __ATOMIC64_OP(op_name##_barrier, op_string)
104 __ATOMIC64_OPS(__atomic64_add, "agr")
105 __ATOMIC64_OPS(__atomic64_and, "ngr")
106 __ATOMIC64_OPS(__atomic64_or, "ogr")
107 __ATOMIC64_OPS(__atomic64_xor, "xgr")
109 #undef __ATOMIC64_OPS
111 #endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */
113 static inline int __atomic_cmpxchg(int *ptr, int old, int new)
115 return __sync_val_compare_and_swap(ptr, old, new);
118 static inline int __atomic_cmpxchg_bool(int *ptr, int old, int new)
120 return __sync_bool_compare_and_swap(ptr, old, new);
123 static inline long __atomic64_cmpxchg(long *ptr, long old, long new)
125 return __sync_val_compare_and_swap(ptr, old, new);
128 static inline long __atomic64_cmpxchg_bool(long *ptr, long old, long new)
130 return __sync_bool_compare_and_swap(ptr, old, new);
133 #endif /* __ARCH_S390_ATOMIC_OPS__ */