1 // SPDX-FileCopyrightText: 2009 Novell, Inc.
2 // SPDX-FileCopyrightText: 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 // SPDX-License-Identifier: MIT
6 #ifndef _URCU_UATOMIC_ARCH_S390_H
7 #define _URCU_UATOMIC_ARCH_S390_H
10 * Atomic exchange operations for the S390 architecture. Based on information
11 * taken from the Principles of Operation Appendix A "Conditional Swapping
12 * Instructions (CS, CDS)".
14 * Author: Jan Blunck <jblunck@suse.de>
17 #include <urcu/compiler.h>
18 #include <urcu/system.h>
24 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
25 #define COMPILER_HAVE_SHORT_MEM_OPERAND
29 * MEMOP assembler operand rules:
30 * - op refer to MEMOP_IN operand
31 * - MEMOP_IN can expand to more than a single operand. Use it at the end of
35 #ifdef COMPILER_HAVE_SHORT_MEM_OPERAND
37 #define MEMOP_OUT(addr) "=Q" (*(addr))
38 #define MEMOP_IN(addr) "Q" (*(addr))
39 #define MEMOP_REF(op) #op /* op refer to MEMOP_IN operand */
41 #else /* !COMPILER_HAVE_SHORT_MEM_OPERAND */
43 #define MEMOP_OUT(addr) "=m" (*(addr))
44 #define MEMOP_IN(addr) "a" (addr), "m" (*(addr))
45 #define MEMOP_REF(op) "0(" #op ")" /* op refer to MEMOP_IN operand */
47 #endif /* !COMPILER_HAVE_SHORT_MEM_OPERAND */
50 * The __hp() macro casts the void pointer @x to a pointer to a structure
51 * containing an array of char of the specified size. This allows passing the
52 * @addr arguments of the following inline functions as "m" and "+m" operands
53 * to the assembly. The @size parameter should be a constant to support
54 * compilers such as clang which do not support VLA. Create typedefs because
55 * C++ does not allow types be defined in casts.
58 typedef struct { char v
[4]; } __hp_4
;
59 typedef struct { char v
[8]; } __hp_8
;
61 #define __hp(size, x) ((__hp_##size *)(x))
65 static inline __attribute__((always_inline
))
66 unsigned long _uatomic_exchange(volatile void *addr
, unsigned long val
, int len
)
74 "0: cs %0,%2," MEMOP_REF(%3) "\n"
76 : "=&r" (old_val
), MEMOP_OUT (__hp(4, addr
))
77 : "r" (val
), MEMOP_IN (__hp(4, addr
))
81 #if (CAA_BITS_PER_LONG == 64)
84 unsigned long old_val
;
87 "0: csg %0,%2," MEMOP_REF(%3) "\n"
89 : "=&r" (old_val
), MEMOP_OUT (__hp(8, addr
))
90 : "r" (val
), MEMOP_IN (__hp(8, addr
))
96 __asm__
__volatile__(".long 0xd00d00");
102 #define uatomic_xchg(addr, v) \
103 (__typeof__(*(addr))) _uatomic_exchange((addr), \
104 caa_cast_long_keep_sign(v), \
109 static inline __attribute__((always_inline
))
110 unsigned long _uatomic_cmpxchg(void *addr
, unsigned long old
,
111 unsigned long _new
, int len
)
116 unsigned int old_val
= (unsigned int)old
;
118 __asm__
__volatile__(
119 " cs %0,%2," MEMOP_REF(%3) "\n"
120 : "+r" (old_val
), MEMOP_OUT (__hp(4, addr
))
121 : "r" (_new
), MEMOP_IN (__hp(4, addr
))
125 #if (CAA_BITS_PER_LONG == 64)
128 __asm__
__volatile__(
129 " csg %0,%2," MEMOP_REF(%3) "\n"
130 : "+r" (old
), MEMOP_OUT (__hp(8, addr
))
131 : "r" (_new
), MEMOP_IN (__hp(8, addr
))
137 __asm__
__volatile__(".long 0xd00d00");
143 #define uatomic_cmpxchg(addr, old, _new) \
144 (__typeof__(*(addr))) _uatomic_cmpxchg((addr), \
145 caa_cast_long_keep_sign(old), \
146 caa_cast_long_keep_sign(_new),\
153 #include <urcu/uatomic/generic.h>
155 #endif /* _URCU_UATOMIC_ARCH_S390_H */
This page took 0.0323 seconds and 4 git commands to generate.