Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: sw=2 ts=8 et :
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 // This file is an internal atomic implementation, use
9 // base/atomicops.h instead.
10 //
11 // This is a very slow fallback implementation of atomic operations
12 // that uses a mutex instead of atomic instructions.
13 //
14 // (NB: a small "optimization" here would be using a spinlock instead
15 // of a blocking mutex, but it's probably not worth the time.)
17 #ifndef base_atomicops_internals_mutex_h
18 #define base_atomicops_internals_mutex_h
20 #include "base/lock.h"
22 namespace base {
23 namespace subtle {
25 extern Lock gAtomicsMutex;
27 template<typename T>
28 T Locked_CAS(volatile T* ptr, T old_value, T new_value) {
29 AutoLock _(gAtomicsMutex);
31 T current_value = *ptr;
32 if (current_value == old_value)
33 *ptr = new_value;
35 return current_value;
36 }
38 template<typename T>
39 T Locked_AtomicExchange(volatile T* ptr, T new_value) {
40 AutoLock _(gAtomicsMutex);
42 T current_value = *ptr;
43 *ptr = new_value;
44 return current_value;
45 }
47 template<typename T>
48 T Locked_AtomicIncrement(volatile T* ptr, T increment) {
49 AutoLock _(gAtomicsMutex);
50 return *ptr += increment;
51 }
53 template<typename T>
54 void Locked_Store(volatile T* ptr, T value) {
55 AutoLock _(gAtomicsMutex);
56 *ptr = value;
57 }
59 template<typename T>
60 T Locked_Load(volatile const T* ptr) {
61 AutoLock _(gAtomicsMutex);
62 return *ptr;
63 }
65 inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
66 Atomic32 old_value,
67 Atomic32 new_value) {
68 return Locked_CAS(ptr, old_value, new_value);
69 }
71 inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
72 Atomic32 new_value) {
73 return Locked_AtomicExchange(ptr, new_value);
74 }
76 inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
77 Atomic32 increment) {
78 return Locked_AtomicIncrement(ptr, increment);
79 }
81 inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
82 Atomic32 increment) {
83 return Locked_AtomicIncrement(ptr, increment);
84 }
86 inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
87 Atomic32 old_value,
88 Atomic32 new_value) {
89 return Locked_CAS(ptr, old_value, new_value);
90 }
92 inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
93 Atomic32 old_value,
94 Atomic32 new_value) {
95 return Locked_CAS(ptr, old_value, new_value);
96 }
98 inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
99 return Locked_Store(ptr, value);
100 }
102 inline void MemoryBarrier() {
103 AutoLock _(gAtomicsMutex);
104 // lock/unlock work as a barrier here
105 }
107 inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
108 return Locked_Store(ptr, value);
109 }
111 inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
112 return Locked_Store(ptr, value);
113 }
115 inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
116 return Locked_Load(ptr);
117 }
119 inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
120 return NoBarrier_Load(ptr);
121 }
123 inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
124 return Locked_Load(ptr);
125 }
127 #ifdef ARCH_CPU_64_BITS
129 inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
130 Atomic64 old_value,
131 Atomic64 new_value) {
132 return Locked_CAS(ptr, old_value, new_value);
133 }
135 inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
136 Atomic64 new_value) {
137 return Locked_AtomicExchange(ptr, new_value);
138 }
140 inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
141 Atomic64 increment) {
142 return Locked_AtomicIncrement(ptr, increment);
143 }
145 inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
146 Atomic64 increment) {
147 return Locked_AtomicIncrement(ptr, increment);
148 }
150 inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
151 return Locked_Store(ptr, value);
152 }
154 inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
155 Atomic64 old_value,
156 Atomic64 new_value) {
157 return Locked_CAS(ptr, old_value, new_value);
158 }
160 inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
161 return Locked_Store(ptr, value);
162 }
164 inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
165 return Locked_Store(ptr, value);
166 }
168 inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
169 return Locked_Load(ptr);
170 }
172 inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
173 return Locked_Load(ptr);
174 }
176 inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
177 return Locked_Load(ptr);
178 }
180 #endif // ARCH_CPU_64_BITS
182 #ifdef OS_MACOSX
183 // From atomicops_internals_x86_macosx.h:
184 //
185 // MacOS uses long for intptr_t, AtomicWord and Atomic32 are always
186 // different on the Mac, even when they are the same size. We need
187 // to explicitly cast from AtomicWord to Atomic32/64 to implement
188 // the AtomicWord interface.
190 inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr,
191 AtomicWord old_value,
192 AtomicWord new_value) {
193 return Locked_CAS(ptr, old_value, new_value);
194 }
196 inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr,
197 AtomicWord new_value) {
198 return Locked_AtomicExchange(ptr, new_value);
199 }
201 inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr,
202 AtomicWord increment) {
203 return Locked_AtomicIncrement(ptr, increment);
204 }
206 inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr,
207 AtomicWord increment) {
208 return Locked_AtomicIncrement(ptr, increment);
209 }
211 inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr,
212 AtomicWord old_value,
213 AtomicWord new_value) {
214 return Locked_CAS(ptr, old_value, new_value);
215 }
217 inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr,
218 AtomicWord old_value,
219 AtomicWord new_value) {
220 return Locked_CAS(ptr, old_value, new_value);
221 }
223 inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) {
224 return Locked_Store(ptr, value);
225 }
227 inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
228 return Locked_Store(ptr, value);
229 }
231 inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) {
232 return Locked_Store(ptr, value);
233 }
235 inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) {
236 return Locked_Load(ptr);
237 }
239 inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) {
240 return Locked_Load(ptr);
241 }
243 inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
244 return Locked_Load(ptr);
245 }
247 #endif // OS_MACOSX
249 } // namespace subtle
250 } // namespace base
252 #endif // base_atomicops_internals_mutex_h