Merge branch 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[cris-mirror.git] / arch / riscv / include / asm / cmpxchg.h
blobdb249dbc7b9760c319e96e441d2f2ebc18ada3d4
1 /*
2 * Copyright (C) 2014 Regents of the University of California
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #ifndef _ASM_RISCV_CMPXCHG_H
15 #define _ASM_RISCV_CMPXCHG_H
17 #include <linux/bug.h>
19 #include <asm/barrier.h>
21 #define __xchg(new, ptr, size, asm_or) \
22 ({ \
23 __typeof__(ptr) __ptr = (ptr); \
24 __typeof__(new) __new = (new); \
25 __typeof__(*(ptr)) __ret; \
26 switch (size) { \
27 case 4: \
28 __asm__ __volatile__ ( \
29 "amoswap.w" #asm_or " %0, %2, %1" \
30 : "=r" (__ret), "+A" (*__ptr) \
31 : "r" (__new) \
32 : "memory"); \
33 break; \
34 case 8: \
35 __asm__ __volatile__ ( \
36 "amoswap.d" #asm_or " %0, %2, %1" \
37 : "=r" (__ret), "+A" (*__ptr) \
38 : "r" (__new) \
39 : "memory"); \
40 break; \
41 default: \
42 BUILD_BUG(); \
43 } \
44 __ret; \
47 #define xchg(ptr, x) (__xchg((x), (ptr), sizeof(*(ptr)), .aqrl))
49 #define xchg32(ptr, x) \
50 ({ \
51 BUILD_BUG_ON(sizeof(*(ptr)) != 4); \
52 xchg((ptr), (x)); \
55 #define xchg64(ptr, x) \
56 ({ \
57 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
58 xchg((ptr), (x)); \
62 * Atomic compare and exchange. Compare OLD with MEM, if identical,
63 * store NEW in MEM. Return the initial value in MEM. Success is
64 * indicated by comparing RETURN with OLD.
66 #define __cmpxchg(ptr, old, new, size, lrb, scb) \
67 ({ \
68 __typeof__(ptr) __ptr = (ptr); \
69 __typeof__(*(ptr)) __old = (old); \
70 __typeof__(*(ptr)) __new = (new); \
71 __typeof__(*(ptr)) __ret; \
72 register unsigned int __rc; \
73 switch (size) { \
74 case 4: \
75 __asm__ __volatile__ ( \
76 "0:" \
77 "lr.w" #scb " %0, %2\n" \
78 "bne %0, %z3, 1f\n" \
79 "sc.w" #lrb " %1, %z4, %2\n" \
80 "bnez %1, 0b\n" \
81 "1:" \
82 : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \
83 : "rJ" (__old), "rJ" (__new) \
84 : "memory"); \
85 break; \
86 case 8: \
87 __asm__ __volatile__ ( \
88 "0:" \
89 "lr.d" #scb " %0, %2\n" \
90 "bne %0, %z3, 1f\n" \
91 "sc.d" #lrb " %1, %z4, %2\n" \
92 "bnez %1, 0b\n" \
93 "1:" \
94 : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \
95 : "rJ" (__old), "rJ" (__new) \
96 : "memory"); \
97 break; \
98 default: \
99 BUILD_BUG(); \
101 __ret; \
104 #define cmpxchg(ptr, o, n) \
105 (__cmpxchg((ptr), (o), (n), sizeof(*(ptr)), .aqrl, .aqrl))
107 #define cmpxchg_local(ptr, o, n) \
108 (__cmpxchg((ptr), (o), (n), sizeof(*(ptr)), , ))
110 #define cmpxchg32(ptr, o, n) \
111 ({ \
112 BUILD_BUG_ON(sizeof(*(ptr)) != 4); \
113 cmpxchg((ptr), (o), (n)); \
116 #define cmpxchg32_local(ptr, o, n) \
117 ({ \
118 BUILD_BUG_ON(sizeof(*(ptr)) != 4); \
119 cmpxchg_local((ptr), (o), (n)); \
122 #define cmpxchg64(ptr, o, n) \
123 ({ \
124 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
125 cmpxchg((ptr), (o), (n)); \
128 #define cmpxchg64_local(ptr, o, n) \
129 ({ \
130 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
131 cmpxchg_local((ptr), (o), (n)); \
134 #endif /* _ASM_RISCV_CMPXCHG_H */