OLD | NEW |
| (Empty) |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // This file is an internal atomic implementation, include base/atomicops.h | |
6 // instead. This file is for platforms that use GCC intrinsics rather than | |
7 // platform-specific assembly code for atomic operations. | |
8 | |
9 #ifndef BASE_ATOMICOPS_INTERNALS_GCC_H_ | |
10 #define BASE_ATOMICOPS_INTERNALS_GCC_H_ | |
11 | |
12 namespace base { | |
13 namespace subtle { | |
14 | |
15 inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, | |
16 Atomic32 old_value, | |
17 Atomic32 new_value) { | |
18 Atomic32 prev_value; | |
19 do { | |
20 if (__sync_bool_compare_and_swap(ptr, old_value, new_value)) | |
21 return old_value; | |
22 prev_value = *ptr; | |
23 } while (prev_value == old_value); | |
24 return prev_value; | |
25 } | |
26 | |
27 inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, | |
28 Atomic32 new_value) { | |
29 Atomic32 old_value; | |
30 do { | |
31 old_value = *ptr; | |
32 } while (!__sync_bool_compare_and_swap(ptr, old_value, new_value)); | |
33 return old_value; | |
34 } | |
35 | |
36 inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, | |
37 Atomic32 increment) { | |
38 return Barrier_AtomicIncrement(ptr, increment); | |
39 } | |
40 | |
41 inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, | |
42 Atomic32 increment) { | |
43 for (;;) { | |
44 // Atomic exchange the old value with an incremented one. | |
45 Atomic32 old_value = *ptr; | |
46 Atomic32 new_value = old_value + increment; | |
47 if (__sync_bool_compare_and_swap(ptr, old_value, new_value)) { | |
48 // The exchange took place as expected. | |
49 return new_value; | |
50 } | |
51 // Otherwise, *ptr changed mid-loop and we need to retry. | |
52 } | |
53 } | |
54 | |
55 inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, | |
56 Atomic32 old_value, | |
57 Atomic32 new_value) { | |
58 // Since NoBarrier_CompareAndSwap uses __sync_bool_compare_and_swap, which | |
59 // is a full memory barrier, none is needed here or below in Release. | |
60 return NoBarrier_CompareAndSwap(ptr, old_value, new_value); | |
61 } | |
62 | |
63 inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, | |
64 Atomic32 old_value, | |
65 Atomic32 new_value) { | |
66 return NoBarrier_CompareAndSwap(ptr, old_value, new_value); | |
67 } | |
68 | |
69 inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { | |
70 *ptr = value; | |
71 } | |
72 | |
73 inline void MemoryBarrier() { | |
74 __sync_synchronize(); | |
75 } | |
76 | |
77 inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { | |
78 *ptr = value; | |
79 MemoryBarrier(); | |
80 } | |
81 | |
82 inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { | |
83 MemoryBarrier(); | |
84 *ptr = value; | |
85 } | |
86 | |
87 inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { | |
88 return *ptr; | |
89 } | |
90 | |
91 inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { | |
92 Atomic32 value = *ptr; | |
93 MemoryBarrier(); | |
94 return value; | |
95 } | |
96 | |
97 inline Atomic32 Release_Load(volatile const Atomic32* ptr) { | |
98 MemoryBarrier(); | |
99 return *ptr; | |
100 } | |
101 | |
102 } // namespace subtle | |
103 } // namespace base | |
104 | |
105 #endif // BASE_ATOMICOPS_INTERNALS_GCC_H_ | |
106 | |
OLD | NEW |