Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(396)

Side by Side Diff: third_party/tcmalloc/chromium/src/base/atomicops-internals-arm-v6plus.h

Issue 1549913002: tcmalloc: Use C++11 atomics where appropriate. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2011, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 // ---
30 //
31 // Author: Sasha Levitskiy
32 // based on atomicops-internals by Sanjay Ghemawat
33 //
34 // This file is an internal atomic implementation, use base/atomicops.h instead.
35 //
36 // This code implements ARM atomics for architectures V6 and newer.
37
38 #ifndef BASE_ATOMICOPS_INTERNALS_ARM_V6PLUS_H_
39 #define BASE_ATOMICOPS_INTERNALS_ARM_V6PLUS_H_
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include "base/abort.h"
44 #include "base/basictypes.h" // For COMPILE_ASSERT
45
46 // The LDREXD and STREXD instructions in ARM all v7 variants or above. In v6,
47 // only some variants support it. For simplicity, we only use exclusive
48 // 64-bit load/store in V7 or above.
49 #if defined(ARMV7)
50 # define BASE_ATOMICOPS_HAS_LDREXD_AND_STREXD
51 #endif
52
53 typedef int32_t Atomic32;
54
55 namespace base {
56 namespace subtle {
57
58 typedef int64_t Atomic64;
59
60 // 32-bit low-level ops
61
62 inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
63 Atomic32 old_value,
64 Atomic32 new_value) {
65 Atomic32 oldval, res;
66 do {
67 __asm__ __volatile__(
68 "ldrex %1, [%3]\n"
69 "mov %0, #0\n"
70 "teq %1, %4\n"
71 // The following IT (if-then) instruction is needed for the subsequent
72 // conditional instruction STREXEQ when compiling in THUMB mode.
73 // In ARM mode, the compiler/assembler will not generate any code for it.
74 "it eq\n"
75 "strexeq %0, %5, [%3]\n"
76 : "=&r" (res), "=&r" (oldval), "+Qo" (*ptr)
77 : "r" (ptr), "Ir" (old_value), "r" (new_value)
78 : "cc");
79 } while (res);
80 return oldval;
81 }
82
83 inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
84 Atomic32 new_value) {
85 Atomic32 tmp, old;
86 __asm__ __volatile__(
87 "1:\n"
88 "ldrex %1, [%2]\n"
89 "strex %0, %3, [%2]\n"
90 "teq %0, #0\n"
91 "bne 1b"
92 : "=&r" (tmp), "=&r" (old)
93 : "r" (ptr), "r" (new_value)
94 : "cc", "memory");
95 return old;
96 }
97
98 inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
99 Atomic32 increment) {
100 Atomic32 tmp, res;
101 __asm__ __volatile__(
102 "1:\n"
103 "ldrex %1, [%2]\n"
104 "add %1, %1, %3\n"
105 "strex %0, %1, [%2]\n"
106 "teq %0, #0\n"
107 "bne 1b"
108 : "=&r" (tmp), "=&r"(res)
109 : "r" (ptr), "r"(increment)
110 : "cc", "memory");
111 return res;
112 }
113
114 inline void MemoryBarrier() {
115 __asm__ __volatile__("dmb" : : : "memory");
116 }
117
118 inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
119 Atomic32 increment) {
120 Atomic32 tmp, res;
121 __asm__ __volatile__(
122 "1:\n"
123 "ldrex %1, [%2]\n"
124 "add %1, %1, %3\n"
125 "dmb\n"
126 "strex %0, %1, [%2]\n"
127 "teq %0, #0\n"
128 "bne 1b"
129 : "=&r" (tmp), "=&r"(res)
130 : "r" (ptr), "r"(increment)
131 : "cc", "memory");
132 return res;
133 }
134
135 inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
136 Atomic32 old_value,
137 Atomic32 new_value) {
138 Atomic32 value = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
139 MemoryBarrier();
140 return value;
141 }
142
143 inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
144 Atomic32 old_value,
145 Atomic32 new_value) {
146 MemoryBarrier();
147 return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
148 }
149
150 inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
151 *ptr = value;
152 }
153
154 inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
155 *ptr = value;
156 MemoryBarrier();
157 }
158
159 inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
160 MemoryBarrier();
161 *ptr = value;
162 }
163
164 inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
165 return *ptr;
166 }
167
168 inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
169 Atomic32 value = *ptr;
170 MemoryBarrier();
171 return value;
172 }
173
174 inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
175 MemoryBarrier();
176 return *ptr;
177 }
178
179 // 64-bit versions are only available if LDREXD and STREXD instructions
180 // are available.
181 #ifdef BASE_ATOMICOPS_HAS_LDREXD_AND_STREXD
182
183 #define BASE_HAS_ATOMIC64 1
184
185 inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
186 Atomic64 old_value,
187 Atomic64 new_value) {
188 Atomic64 oldval, res;
189 do {
190 __asm__ __volatile__(
191 "ldrexd %1, [%3]\n"
192 "mov %0, #0\n"
193 "teq %Q1, %Q4\n"
194 // The following IT (if-then) instructions are needed for the subsequent
195 // conditional instructions when compiling in THUMB mode.
196 // In ARM mode, the compiler/assembler will not generate any code for it.
197 "it eq\n"
198 "teqeq %R1, %R4\n"
199 "it eq\n"
200 "strexdeq %0, %5, [%3]\n"
201 : "=&r" (res), "=&r" (oldval), "+Q" (*ptr)
202 : "r" (ptr), "Ir" (old_value), "r" (new_value)
203 : "cc");
204 } while (res);
205 return oldval;
206 }
207
208 inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
209 Atomic64 new_value) {
210 int store_failed;
211 Atomic64 old;
212 __asm__ __volatile__(
213 "1:\n"
214 "ldrexd %1, [%2]\n"
215 "strexd %0, %3, [%2]\n"
216 "teq %0, #0\n"
217 "bne 1b"
218 : "=&r" (store_failed), "=&r" (old)
219 : "r" (ptr), "r" (new_value)
220 : "cc", "memory");
221 return old;
222 }
223
224 inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
225 Atomic64 increment) {
226 int store_failed;
227 Atomic64 res;
228 __asm__ __volatile__(
229 "1:\n"
230 "ldrexd %1, [%2]\n"
231 "adds %Q1, %Q1, %Q3\n"
232 "adc %R1, %R1, %R3\n"
233 "strexd %0, %1, [%2]\n"
234 "teq %0, #0\n"
235 "bne 1b"
236 : "=&r" (store_failed), "=&r"(res)
237 : "r" (ptr), "r"(increment)
238 : "cc", "memory");
239 return res;
240 }
241
242 inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
243 Atomic64 increment) {
244 int store_failed;
245 Atomic64 res;
246 __asm__ __volatile__(
247 "1:\n"
248 "ldrexd %1, [%2]\n"
249 "adds %Q1, %Q1, %Q3\n"
250 "adc %R1, %R1, %R3\n"
251 "dmb\n"
252 "strexd %0, %1, [%2]\n"
253 "teq %0, #0\n"
254 "bne 1b"
255 : "=&r" (store_failed), "=&r"(res)
256 : "r" (ptr), "r"(increment)
257 : "cc", "memory");
258 return res;
259 }
260
261 inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
262 int store_failed;
263 Atomic64 dummy;
264 __asm__ __volatile__(
265 "1:\n"
266 // Dummy load to lock cache line.
267 "ldrexd %1, [%3]\n"
268 "strexd %0, %2, [%3]\n"
269 "teq %0, #0\n"
270 "bne 1b"
271 : "=&r" (store_failed), "=&r"(dummy)
272 : "r"(value), "r" (ptr)
273 : "cc", "memory");
274 }
275
276 inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
277 Atomic64 res;
278 __asm__ __volatile__(
279 "ldrexd %0, [%1]\n"
280 "clrex\n"
281 : "=r" (res)
282 : "r"(ptr), "Q"(*ptr));
283 return res;
284 }
285
286 #else // BASE_ATOMICOPS_HAS_LDREXD_AND_STREXD
287
288 inline void NotImplementedFatalError(const char *function_name) {
289 fprintf(stderr, "64-bit %s() not implemented on this platform\n",
290 function_name);
291 tcmalloc::Abort();
292 }
293
294 inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
295 Atomic64 old_value,
296 Atomic64 new_value) {
297 NotImplementedFatalError("NoBarrier_CompareAndSwap");
298 return 0;
299 }
300
301 inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
302 Atomic64 new_value) {
303 NotImplementedFatalError("NoBarrier_AtomicExchange");
304 return 0;
305 }
306
307 inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
308 Atomic64 increment) {
309 NotImplementedFatalError("NoBarrier_AtomicIncrement");
310 return 0;
311 }
312
313 inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
314 Atomic64 increment) {
315 NotImplementedFatalError("Barrier_AtomicIncrement");
316 return 0;
317 }
318
319 inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
320 NotImplementedFatalError("NoBarrier_Store");
321 }
322
323 inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
324 NotImplementedFatalError("NoBarrier_Load");
325 return 0;
326 }
327
328 #endif // BASE_ATOMICOPS_HAS_LDREXD_AND_STREXD
329
330 inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
331 NoBarrier_Store(ptr, value);
332 MemoryBarrier();
333 }
334
335 inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
336 MemoryBarrier();
337 NoBarrier_Store(ptr, value);
338 }
339
340 inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
341 Atomic64 value = NoBarrier_Load(ptr);
342 MemoryBarrier();
343 return value;
344 }
345
346 inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
347 MemoryBarrier();
348 return NoBarrier_Load(ptr);
349 }
350
351 inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
352 Atomic64 old_value,
353 Atomic64 new_value) {
354 Atomic64 value = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
355 MemoryBarrier();
356 return value;
357 }
358
359 inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
360 Atomic64 old_value,
361 Atomic64 new_value) {
362 MemoryBarrier();
363 return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
364 }
365
366 } // namespace subtle ends
367 } // namespace base ends
368
369 #endif // BASE_ATOMICOPS_INTERNALS_ARM_V6PLUS_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698