Commit | Line | Data |
---|---|---|
ac26f1a8 JB |
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 | ||
a9a05d42 | 32 | static inline __attribute__((always_inline)) |
ac26f1a8 JB |
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 | ||
a9a05d42 | 49 | static inline __attribute__((always_inline)) |
ac26f1a8 JB |
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 | ||
a9a05d42 | 67 | static inline __attribute__((always_inline)) |
ac26f1a8 JB |
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 | ||
a9a05d42 JB |
84 | #define xchg(addr, v) \ |
85 | (__typeof__(*(addr))) _atomic_exchange((addr), (unsigned long)(v), \ | |
86 | sizeof(*(addr))) | |
ac26f1a8 JB |
87 | |
88 | #endif /* #ifndef _INCLUDE_API_H */ | |
89 | ||
90 | #endif /* ARCH_ATOMIC_S390_H */ |