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

Side by Side Diff: third_party/tcmalloc/chromium/src/base/atomicops-internals-linuxppc.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) 2008, 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 */
32
33 // Implementation of atomic operations for ppc-linux. This file should not
34 // be included directly. Clients should instead include
35 // "base/atomicops.h".
36
37 #ifndef BASE_ATOMICOPS_INTERNALS_LINUXPPC_H_
38 #define BASE_ATOMICOPS_INTERNALS_LINUXPPC_H_
39
40 typedef int32_t Atomic32;
41
42 #ifdef __PPC64__
43 #define BASE_HAS_ATOMIC64 1
44 #endif
45
46 namespace base {
47 namespace subtle {
48
49 static inline void _sync(void) {
50 __asm__ __volatile__("sync": : : "memory");
51 }
52
53 static inline void _lwsync(void) {
54 // gcc defines __NO_LWSYNC__ when appropriate; see
55 // http://gcc.gnu.org/ml/gcc-patches/2006-11/msg01238.html
56 #ifdef __NO_LWSYNC__
57 __asm__ __volatile__("msync": : : "memory");
58 #else
59 __asm__ __volatile__("lwsync": : : "memory");
60 #endif
61 }
62
63 static inline void _isync(void) {
64 __asm__ __volatile__("isync": : : "memory");
65 }
66
67 static inline Atomic32 OSAtomicAdd32(Atomic32 amount, Atomic32 *value) {
68 Atomic32 t;
69 __asm__ __volatile__(
70 "1: lwarx %0,0,%3\n\
71 add %0,%2,%0\n\
72 stwcx. %0,0,%3 \n\
73 bne- 1b"
74 : "=&r" (t), "+m" (*value)
75 : "r" (amount), "r" (value)
76 : "cc");
77 return t;
78 }
79
80 static inline Atomic32 OSAtomicAdd32Barrier(Atomic32 amount, Atomic32 *value) {
81 Atomic32 t;
82 _lwsync();
83 t = OSAtomicAdd32(amount, value);
84 // This is based on the code snippet in the architecture manual (Vol
85 // 2, Appendix B). It's a little tricky: correctness depends on the
86 // fact that the code right before this (in OSAtomicAdd32) has a
87 // conditional branch with a data dependency on the update.
88 // Otherwise, we'd have to use sync.
89 _isync();
90 return t;
91 }
92
93 static inline bool OSAtomicCompareAndSwap32(Atomic32 old_value,
94 Atomic32 new_value,
95 Atomic32 *value) {
96 Atomic32 prev;
97 __asm__ __volatile__(
98 "1: lwarx %0,0,%2\n\
99 cmpw 0,%0,%3\n\
100 bne- 2f\n\
101 stwcx. %4,0,%2\n\
102 bne- 1b\n\
103 2:"
104 : "=&r" (prev), "+m" (*value)
105 : "r" (value), "r" (old_value), "r" (new_value)
106 : "cc");
107 return prev == old_value;
108 }
109
110 static inline Atomic32 OSAtomicCompareAndSwap32Acquire(Atomic32 old_value,
111 Atomic32 new_value,
112 Atomic32 *value) {
113 Atomic32 t;
114 t = OSAtomicCompareAndSwap32(old_value, new_value, value);
115 // This is based on the code snippet in the architecture manual (Vol
116 // 2, Appendix B). It's a little tricky: correctness depends on the
117 // fact that the code right before this (in
118 // OSAtomicCompareAndSwap32) has a conditional branch with a data
119 // dependency on the update. Otherwise, we'd have to use sync.
120 _isync();
121 return t;
122 }
123
124 static inline Atomic32 OSAtomicCompareAndSwap32Release(Atomic32 old_value,
125 Atomic32 new_value,
126 Atomic32 *value) {
127 _lwsync();
128 return OSAtomicCompareAndSwap32(old_value, new_value, value);
129 }
130
131 typedef int64_t Atomic64;
132
133 inline void MemoryBarrier() {
134 // This can't be _lwsync(); we need to order the immediately
135 // preceding stores against any load that may follow, but lwsync
136 // doesn't guarantee that.
137 _sync();
138 }
139
140 // 32-bit Versions.
141
142 inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr,
143 Atomic32 old_value,
144 Atomic32 new_value) {
145 Atomic32 prev_value;
146 do {
147 if (OSAtomicCompareAndSwap32(old_value, new_value,
148 const_cast<Atomic32*>(ptr))) {
149 return old_value;
150 }
151 prev_value = *ptr;
152 } while (prev_value == old_value);
153 return prev_value;
154 }
155
156 inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr,
157 Atomic32 new_value) {
158 Atomic32 old_value;
159 do {
160 old_value = *ptr;
161 } while (!OSAtomicCompareAndSwap32(old_value, new_value,
162 const_cast<Atomic32*>(ptr)));
163 return old_value;
164 }
165
166 inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr,
167 Atomic32 increment) {
168 return OSAtomicAdd32(increment, const_cast<Atomic32*>(ptr));
169 }
170
171 inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr,
172 Atomic32 increment) {
173 return OSAtomicAdd32Barrier(increment, const_cast<Atomic32*>(ptr));
174 }
175
176 inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr,
177 Atomic32 old_value,
178 Atomic32 new_value) {
179 Atomic32 prev_value;
180 do {
181 if (OSAtomicCompareAndSwap32Acquire(old_value, new_value,
182 const_cast<Atomic32*>(ptr))) {
183 return old_value;
184 }
185 prev_value = *ptr;
186 } while (prev_value == old_value);
187 return prev_value;
188 }
189
190 inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr,
191 Atomic32 old_value,
192 Atomic32 new_value) {
193 Atomic32 prev_value;
194 do {
195 if (OSAtomicCompareAndSwap32Release(old_value, new_value,
196 const_cast<Atomic32*>(ptr))) {
197 return old_value;
198 }
199 prev_value = *ptr;
200 } while (prev_value == old_value);
201 return prev_value;
202 }
203
204 #ifdef __PPC64__
205
206 // 64-bit Versions.
207
208 static inline Atomic64 OSAtomicAdd64(Atomic64 amount, Atomic64 *value) {
209 Atomic64 t;
210 __asm__ __volatile__(
211 "1: ldarx %0,0,%3\n\
212 add %0,%2,%0\n\
213 stdcx. %0,0,%3 \n\
214 bne- 1b"
215 : "=&r" (t), "+m" (*value)
216 : "r" (amount), "r" (value)
217 : "cc");
218 return t;
219 }
220
221 static inline Atomic64 OSAtomicAdd64Barrier(Atomic64 amount, Atomic64 *value) {
222 Atomic64 t;
223 _lwsync();
224 t = OSAtomicAdd64(amount, value);
225 // This is based on the code snippet in the architecture manual (Vol
226 // 2, Appendix B). It's a little tricky: correctness depends on the
227 // fact that the code right before this (in OSAtomicAdd64) has a
228 // conditional branch with a data dependency on the update.
229 // Otherwise, we'd have to use sync.
230 _isync();
231 return t;
232 }
233
234 static inline bool OSAtomicCompareAndSwap64(Atomic64 old_value,
235 Atomic64 new_value,
236 Atomic64 *value) {
237 Atomic64 prev;
238 __asm__ __volatile__(
239 "1: ldarx %0,0,%2\n\
240 cmpw 0,%0,%3\n\
241 bne- 2f\n\
242 stdcx. %4,0,%2\n\
243 bne- 1b\n\
244 2:"
245 : "=&r" (prev), "+m" (*value)
246 : "r" (value), "r" (old_value), "r" (new_value)
247 : "cc");
248 return prev == old_value;
249 }
250
251 static inline Atomic64 OSAtomicCompareAndSwap64Acquire(Atomic64 old_value,
252 Atomic64 new_value,
253 Atomic64 *value) {
254 Atomic64 t;
255 t = OSAtomicCompareAndSwap64(old_value, new_value, value);
256 // This is based on the code snippet in the architecture manual (Vol
257 // 2, Appendix B). It's a little tricky: correctness depends on the
258 // fact that the code right before this (in
259 // OSAtomicCompareAndSwap64) has a conditional branch with a data
260 // dependency on the update. Otherwise, we'd have to use sync.
261 _isync();
262 return t;
263 }
264
265 static inline Atomic64 OSAtomicCompareAndSwap64Release(Atomic64 old_value,
266 Atomic64 new_value,
267 Atomic64 *value) {
268 _lwsync();
269 return OSAtomicCompareAndSwap64(old_value, new_value, value);
270 }
271
272
273 inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64 *ptr,
274 Atomic64 old_value,
275 Atomic64 new_value) {
276 Atomic64 prev_value;
277 do {
278 if (OSAtomicCompareAndSwap64(old_value, new_value,
279 const_cast<Atomic64*>(ptr))) {
280 return old_value;
281 }
282 prev_value = *ptr;
283 } while (prev_value == old_value);
284 return prev_value;
285 }
286
287 inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64 *ptr,
288 Atomic64 new_value) {
289 Atomic64 old_value;
290 do {
291 old_value = *ptr;
292 } while (!OSAtomicCompareAndSwap64(old_value, new_value,
293 const_cast<Atomic64*>(ptr)));
294 return old_value;
295 }
296
297 inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr,
298 Atomic64 increment) {
299 return OSAtomicAdd64(increment, const_cast<Atomic64*>(ptr));
300 }
301
302 inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr,
303 Atomic64 increment) {
304 return OSAtomicAdd64Barrier(increment, const_cast<Atomic64*>(ptr));
305 }
306
307 inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr,
308 Atomic64 old_value,
309 Atomic64 new_value) {
310 Atomic64 prev_value;
311 do {
312 if (OSAtomicCompareAndSwap64Acquire(old_value, new_value,
313 const_cast<Atomic64*>(ptr))) {
314 return old_value;
315 }
316 prev_value = *ptr;
317 } while (prev_value == old_value);
318 return prev_value;
319 }
320
321 inline Atomic64 Release_CompareAndSwap(volatile Atomic64 *ptr,
322 Atomic64 old_value,
323 Atomic64 new_value) {
324 Atomic64 prev_value;
325 do {
326 if (OSAtomicCompareAndSwap64Release(old_value, new_value,
327 const_cast<Atomic64*>(ptr))) {
328 return old_value;
329 }
330 prev_value = *ptr;
331 } while (prev_value == old_value);
332 return prev_value;
333 }
334
335 #endif
336
337 inline void NoBarrier_Store(volatile Atomic32 *ptr, Atomic32 value) {
338 *ptr = value;
339 }
340
341 inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
342 *ptr = value;
343 // This can't be _lwsync(); we need to order the immediately
344 // preceding stores against any load that may follow, but lwsync
345 // doesn't guarantee that.
346 _sync();
347 }
348
349 inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) {
350 _lwsync();
351 *ptr = value;
352 }
353
354 inline Atomic32 NoBarrier_Load(volatile const Atomic32 *ptr) {
355 return *ptr;
356 }
357
358 inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) {
359 Atomic32 value = *ptr;
360 _lwsync();
361 return value;
362 }
363
364 inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
365 // This can't be _lwsync(); we need to order the immediately
366 // preceding stores against any load that may follow, but lwsync
367 // doesn't guarantee that.
368 _sync();
369 return *ptr;
370 }
371
372 #ifdef __PPC64__
373
374 // 64-bit Versions.
375
376 inline void NoBarrier_Store(volatile Atomic64 *ptr, Atomic64 value) {
377 *ptr = value;
378 }
379
380 inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
381 *ptr = value;
382 // This can't be _lwsync(); we need to order the immediately
383 // preceding stores against any load that may follow, but lwsync
384 // doesn't guarantee that.
385 _sync();
386 }
387
388 inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) {
389 _lwsync();
390 *ptr = value;
391 }
392
393 inline Atomic64 NoBarrier_Load(volatile const Atomic64 *ptr) {
394 return *ptr;
395 }
396
397 inline Atomic64 Acquire_Load(volatile const Atomic64 *ptr) {
398 Atomic64 value = *ptr;
399 _lwsync();
400 return value;
401 }
402
403 inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
404 // This can't be _lwsync(); we need to order the immediately
405 // preceding stores against any load that may follow, but lwsync
406 // doesn't guarantee that.
407 _sync();
408 return *ptr;
409 }
410
411 #endif
412
413 } // namespace base::subtle
414 } // namespace base
415
416 #endif // BASE_ATOMICOPS_INTERNALS_LINUXPPC_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698