Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cmpxchg.h
Go to the documentation of this file.
1 /*
2  * Based on arch/arm/include/asm/cmpxchg.h
3  *
4  * Copyright (C) 2012 ARM Ltd.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 #ifndef __ASM_CMPXCHG_H
19 #define __ASM_CMPXCHG_H
20 
21 #include <linux/bug.h>
22 
23 #include <asm/barrier.h>
24 
25 static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
26 {
27  unsigned long ret, tmp;
28 
29  switch (size) {
30  case 1:
31  asm volatile("// __xchg1\n"
32  "1: ldaxrb %w0, [%3]\n"
33  " stlxrb %w1, %w2, [%3]\n"
34  " cbnz %w1, 1b\n"
35  : "=&r" (ret), "=&r" (tmp)
36  : "r" (x), "r" (ptr)
37  : "memory", "cc");
38  break;
39  case 2:
40  asm volatile("// __xchg2\n"
41  "1: ldaxrh %w0, [%3]\n"
42  " stlxrh %w1, %w2, [%3]\n"
43  " cbnz %w1, 1b\n"
44  : "=&r" (ret), "=&r" (tmp)
45  : "r" (x), "r" (ptr)
46  : "memory", "cc");
47  break;
48  case 4:
49  asm volatile("// __xchg4\n"
50  "1: ldaxr %w0, [%3]\n"
51  " stlxr %w1, %w2, [%3]\n"
52  " cbnz %w1, 1b\n"
53  : "=&r" (ret), "=&r" (tmp)
54  : "r" (x), "r" (ptr)
55  : "memory", "cc");
56  break;
57  case 8:
58  asm volatile("// __xchg8\n"
59  "1: ldaxr %0, [%3]\n"
60  " stlxr %w1, %2, [%3]\n"
61  " cbnz %w1, 1b\n"
62  : "=&r" (ret), "=&r" (tmp)
63  : "r" (x), "r" (ptr)
64  : "memory", "cc");
65  break;
66  default:
67  BUILD_BUG();
68  }
69 
70  return ret;
71 }
72 
73 #define xchg(ptr,x) \
74  ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
75 
76 static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
77  unsigned long new, int size)
78 {
79  unsigned long oldval = 0, res;
80 
81  switch (size) {
82  case 1:
83  do {
84  asm volatile("// __cmpxchg1\n"
85  " ldxrb %w1, [%2]\n"
86  " mov %w0, #0\n"
87  " cmp %w1, %w3\n"
88  " b.ne 1f\n"
89  " stxrb %w0, %w4, [%2]\n"
90  "1:\n"
91  : "=&r" (res), "=&r" (oldval)
92  : "r" (ptr), "Ir" (old), "r" (new)
93  : "cc");
94  } while (res);
95  break;
96 
97  case 2:
98  do {
99  asm volatile("// __cmpxchg2\n"
100  " ldxrh %w1, [%2]\n"
101  " mov %w0, #0\n"
102  " cmp %w1, %w3\n"
103  " b.ne 1f\n"
104  " stxrh %w0, %w4, [%2]\n"
105  "1:\n"
106  : "=&r" (res), "=&r" (oldval)
107  : "r" (ptr), "Ir" (old), "r" (new)
108  : "memory", "cc");
109  } while (res);
110  break;
111 
112  case 4:
113  do {
114  asm volatile("// __cmpxchg4\n"
115  " ldxr %w1, [%2]\n"
116  " mov %w0, #0\n"
117  " cmp %w1, %w3\n"
118  " b.ne 1f\n"
119  " stxr %w0, %w4, [%2]\n"
120  "1:\n"
121  : "=&r" (res), "=&r" (oldval)
122  : "r" (ptr), "Ir" (old), "r" (new)
123  : "cc");
124  } while (res);
125  break;
126 
127  case 8:
128  do {
129  asm volatile("// __cmpxchg8\n"
130  " ldxr %1, [%2]\n"
131  " mov %w0, #0\n"
132  " cmp %1, %3\n"
133  " b.ne 1f\n"
134  " stxr %w0, %4, [%2]\n"
135  "1:\n"
136  : "=&r" (res), "=&r" (oldval)
137  : "r" (ptr), "Ir" (old), "r" (new)
138  : "cc");
139  } while (res);
140  break;
141 
142  default:
143  BUILD_BUG();
144  }
145 
146  return oldval;
147 }
148 
149 static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old,
150  unsigned long new, int size)
151 {
152  unsigned long ret;
153 
154  smp_mb();
155  ret = __cmpxchg(ptr, old, new, size);
156  smp_mb();
157 
158  return ret;
159 }
160 
161 #define cmpxchg(ptr,o,n) \
162  ((__typeof__(*(ptr)))__cmpxchg_mb((ptr), \
163  (unsigned long)(o), \
164  (unsigned long)(n), \
165  sizeof(*(ptr))))
166 
167 #define cmpxchg_local(ptr,o,n) \
168  ((__typeof__(*(ptr)))__cmpxchg((ptr), \
169  (unsigned long)(o), \
170  (unsigned long)(n), \
171  sizeof(*(ptr))))
172 
173 #endif /* __ASM_CMPXCHG_H */