37fb89f407c6efb4ddd6b257c94747bf3817fd8f
[urcu.git] / arch_atomic_s390.h
1 #ifndef _ARCH_ATOMIC_S390_H
2 #define _ARCH_ATOMIC_S390_H
3
4 /*
5 * Atomic exchange operations for the S390 architecture.
6 *
7 * Copyright (C) 2009 Novell, Inc.
8 * Author: Jan Blunck <jblunck@suse.de>
9 *
10 * This is taken from the Principles of Operation Appendix A "Conditional
11 * Swapping Instructions (CS, CDS)".
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU Lesser General Public License version 2.1 as
15 * published by the Free Software Foundation.
16 */
17
18 #ifndef __SIZEOF_LONG__
19 #ifdef __s390x__
20 #define __SIZEOF_LONG__ 8
21 #else
22 #define __SIZEOF_LONG__ 4
23 #endif
24 #endif
25
26 #ifndef BITS_PER_LONG
27 #define BITS_PER_LONG (__SIZEOF_LONG__ * 8)
28 #endif
29
30 #ifndef _INCLUDE_API_H
31
32 static inline __attribute__((always_inline))
33 unsigned int atomic_exchange_32(volatile unsigned int *addr, unsigned int val)
34 {
35 unsigned int result;
36
37 __asm__ __volatile__(
38 "0: cs %0,%2,%1\n"
39 " brc 4,0b\n"
40 : "=&r"(result), "=m" (*addr)
41 : "r"(val), "m" (*addr)
42 : "memory", "cc");
43
44 return result;
45 }
46
47 #if (BITS_PER_LONG == 64)
48
49 static inline __attribute__((always_inline))
50 unsigned long atomic_exchange_64(volatile unsigned long *addr,
51 unsigned long val)
52 {
53 unsigned long result;
54
55 __asm__ __volatile__(
56 "0: csg %0,%2,%1\n"
57 " brc 4,0b\n"
58 : "=&r"(result), "=m" (*addr)
59 : "r"(val), "m" (*addr)
60 : "memory", "cc");
61
62 return result;
63 }
64
65 #endif
66
67 static inline __attribute__((always_inline))
68 unsigned long _atomic_exchange(volatile void *addr, unsigned long val, int len)
69 {
70 switch (len) {
71 case 4:
72 return atomic_exchange_32(addr, val);
73 #if (BITS_PER_LONG == 64)
74 case 8:
75 return atomic_exchange_64(addr, val);
76 #endif
77 default:
78 __asm__ __volatile__(".long 0xd00d00");
79 }
80
81 return 0;
82 }
83
84 #define xchg(addr, v) \
85 (__typeof__(*(addr))) _atomic_exchange((addr), (unsigned long)(v), \
86 sizeof(*(addr)))
87
88 #endif /* #ifndef _INCLUDE_API_H */
89
90 #endif /* ARCH_ATOMIC_S390_H */
This page took 0.02994 seconds and 3 git commands to generate.