- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / tcmalloc / vendor / src / base / atomicops.h
1 /* Copyright (c) 2006, 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: Sanjay Ghemawat
32  */
33
34 // For atomic operations on statistics counters, see atomic_stats_counter.h.
35 // For atomic operations on sequence numbers, see atomic_sequence_num.h.
36 // For atomic operations on reference counts, see atomic_refcount.h.
37
38 // Some fast atomic operations -- typically with machine-dependent
39 // implementations.  This file may need editing as Google code is
40 // ported to different architectures.
41
42 // The routines exported by this module are subtle.  If you use them, even if
43 // you get the code right, it will depend on careful reasoning about atomicity
44 // and memory ordering; it will be less readable, and harder to maintain.  If
45 // you plan to use these routines, you should have a good reason, such as solid
46 // evidence that performance would otherwise suffer, or there being no
47 // alternative.  You should assume only properties explicitly guaranteed by the
48 // specifications in this file.  You are almost certainly _not_ writing code
49 // just for the x86; if you assume x86 semantics, x86 hardware bugs and
50 // implementations on other archtectures will cause your code to break.  If you
51 // do not know what you are doing, avoid these routines, and use a Mutex.
52 //
53 // It is incorrect to make direct assignments to/from an atomic variable.
54 // You should use one of the Load or Store routines.  The NoBarrier
55 // versions are provided when no barriers are needed:
56 //   NoBarrier_Store()
57 //   NoBarrier_Load()
58 // Although there are currently no compiler enforcement, you are encouraged
59 // to use these.  Moreover, if you choose to use base::subtle::Atomic64 type,
60 // you MUST use one of the Load or Store routines to get correct behavior
61 // on 32-bit platforms.
62 //
63 // The intent is eventually to put all of these routines in namespace
64 // base::subtle
65
66 #ifndef THREAD_ATOMICOPS_H_
67 #define THREAD_ATOMICOPS_H_
68
69 #include <config.h>
70 #ifdef HAVE_STDINT_H
71 #include <stdint.h>
72 #endif
73
74 // ------------------------------------------------------------------------
75 // Include the platform specific implementations of the types
76 // and operations listed below.  Implementations are to provide Atomic32
77 // and Atomic64 operations. If there is a mismatch between intptr_t and
78 // the Atomic32 or Atomic64 types for a platform, the platform-specific header
79 // should define the macro, AtomicWordCastType in a clause similar to the
80 // following:
81 // #if ...pointers are 64 bits...
82 // # define AtomicWordCastType base::subtle::Atomic64
83 // #else
84 // # define AtomicWordCastType Atomic32
85 // #endif
86 // TODO(csilvers): figure out ARCH_PIII/ARCH_K8 (perhaps via ./configure?)
87 // ------------------------------------------------------------------------
88
89 #include "base/arm_instruction_set_select.h"
90
91 // TODO(csilvers): match piii, not just __i386.  Also, match k8
92 #if defined(__MACH__) && defined(__APPLE__)
93 #include "base/atomicops-internals-macosx.h"
94 #elif defined(__GNUC__) && defined(ARMV6)
95 #include "base/atomicops-internals-arm-v6plus.h"
96 #elif defined(ARMV3)
97 #include "base/atomicops-internals-arm-generic.h"
98 #elif defined(_WIN32)
99 #include "base/atomicops-internals-windows.h"
100 #elif defined(__GNUC__) && (defined(__i386) || defined(__x86_64__))
101 #include "base/atomicops-internals-x86.h"
102 #elif defined(__linux__) && defined(__PPC__)
103 #include "base/atomicops-internals-linuxppc.h"
104 #else
105 // Assume x86 for now.  If you need to support a new architecture and
106 // don't know how to implement atomic ops, you can probably get away
107 // with using pthreads, since atomicops is only used by spinlock.h/cc
108 //#error You need to implement atomic operations for this architecture
109 #include "base/atomicops-internals-x86.h"
110 #endif
111
112 // Signed type that can hold a pointer and supports the atomic ops below, as
113 // well as atomic loads and stores.  Instances must be naturally-aligned.
114 typedef intptr_t AtomicWord;
115
116 #ifdef AtomicWordCastType
117 // ------------------------------------------------------------------------
118 // This section is needed only when explicit type casting is required to
119 // cast AtomicWord to one of the basic atomic types (Atomic64 or Atomic32).
120 // It also serves to document the AtomicWord interface.
121 // ------------------------------------------------------------------------
122
123 namespace base {
124 namespace subtle {
125
126 // Atomically execute:
127 //      result = *ptr;
128 //      if (*ptr == old_value)
129 //        *ptr = new_value;
130 //      return result;
131 //
132 // I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
133 // Always return the old value of "*ptr"
134 //
135 // This routine implies no memory barriers.
136 inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr,
137                                            AtomicWord old_value,
138                                            AtomicWord new_value) {
139   return NoBarrier_CompareAndSwap(
140       reinterpret_cast<volatile AtomicWordCastType*>(ptr),
141       old_value, new_value);
142 }
143
144 // Atomically store new_value into *ptr, returning the previous value held in
145 // *ptr.  This routine implies no memory barriers.
146 inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr,
147                                            AtomicWord new_value) {
148   return NoBarrier_AtomicExchange(
149       reinterpret_cast<volatile AtomicWordCastType*>(ptr), new_value);
150 }
151
152 // Atomically increment *ptr by "increment".  Returns the new value of
153 // *ptr with the increment applied.  This routine implies no memory
154 // barriers.
155 inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr,
156                                             AtomicWord increment) {
157   return NoBarrier_AtomicIncrement(
158       reinterpret_cast<volatile AtomicWordCastType*>(ptr), increment);
159 }
160
161 inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr,
162                                           AtomicWord increment) {
163   return Barrier_AtomicIncrement(
164       reinterpret_cast<volatile AtomicWordCastType*>(ptr), increment);
165 }
166
167 // ------------------------------------------------------------------------
168 // These following lower-level operations are typically useful only to people
169 // implementing higher-level synchronization operations like spinlocks,
170 // mutexes, and condition-variables.  They combine CompareAndSwap(), a load, or
171 // a store with appropriate memory-ordering instructions.  "Acquire" operations
172 // ensure that no later memory access can be reordered ahead of the operation.
173 // "Release" operations ensure that no previous memory access can be reordered
174 // after the operation.  "Barrier" operations have both "Acquire" and "Release"
175 // semantics.   A MemoryBarrier() has "Barrier" semantics, but does no memory
176 // access.
177 // ------------------------------------------------------------------------
178 inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr,
179                                          AtomicWord old_value,
180                                          AtomicWord new_value) {
181   return base::subtle::Acquire_CompareAndSwap(
182       reinterpret_cast<volatile AtomicWordCastType*>(ptr),
183       old_value, new_value);
184 }
185
186 inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr,
187                                          AtomicWord old_value,
188                                          AtomicWord new_value) {
189   return base::subtle::Release_CompareAndSwap(
190       reinterpret_cast<volatile AtomicWordCastType*>(ptr),
191       old_value, new_value);
192 }
193
194 inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) {
195   NoBarrier_Store(
196       reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
197 }
198
199 inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
200   return base::subtle::Acquire_Store(
201       reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
202 }
203
204 inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) {
205   return base::subtle::Release_Store(
206       reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
207 }
208
209 inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) {
210   return NoBarrier_Load(
211       reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
212 }
213
214 inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) {
215   return base::subtle::Acquire_Load(
216       reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
217 }
218
219 inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
220   return base::subtle::Release_Load(
221       reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
222 }
223
224 }  // namespace base::subtle
225 }  // namespace base
226 #endif  // AtomicWordCastType
227
228 // ------------------------------------------------------------------------
229 // Commented out type definitions and method declarations for documentation
230 // of the interface provided by this module.
231 // ------------------------------------------------------------------------
232
233 #if 0
234
235 // Signed 32-bit type that supports the atomic ops below, as well as atomic
236 // loads and stores.  Instances must be naturally aligned.  This type differs
237 // from AtomicWord in 64-bit binaries where AtomicWord is 64-bits.
238 typedef int32_t Atomic32;
239
240 // Corresponding operations on Atomic32
241 namespace base {
242 namespace subtle {
243
244 // Signed 64-bit type that supports the atomic ops below, as well as atomic
245 // loads and stores.  Instances must be naturally aligned.  This type differs
246 // from AtomicWord in 32-bit binaries where AtomicWord is 32-bits.
247 typedef int64_t Atomic64;
248
249 Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
250                                   Atomic32 old_value,
251                                   Atomic32 new_value);
252 Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value);
253 Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment);
254 Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
255                                  Atomic32 increment);
256 Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
257                                 Atomic32 old_value,
258                                 Atomic32 new_value);
259 Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
260                                 Atomic32 old_value,
261                                 Atomic32 new_value);
262 void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value);
263 void Acquire_Store(volatile Atomic32* ptr, Atomic32 value);
264 void Release_Store(volatile Atomic32* ptr, Atomic32 value);
265 Atomic32 NoBarrier_Load(volatile const Atomic32* ptr);
266 Atomic32 Acquire_Load(volatile const Atomic32* ptr);
267 Atomic32 Release_Load(volatile const Atomic32* ptr);
268
269 // Corresponding operations on Atomic64
270 Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
271                                   Atomic64 old_value,
272                                   Atomic64 new_value);
273 Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value);
274 Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
275 Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
276
277 Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
278                                 Atomic64 old_value,
279                                 Atomic64 new_value);
280 Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
281                                 Atomic64 old_value,
282                                 Atomic64 new_value);
283 void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value);
284 void Acquire_Store(volatile Atomic64* ptr, Atomic64 value);
285 void Release_Store(volatile Atomic64* ptr, Atomic64 value);
286 Atomic64 NoBarrier_Load(volatile const Atomic64* ptr);
287 Atomic64 Acquire_Load(volatile const Atomic64* ptr);
288 Atomic64 Release_Load(volatile const Atomic64* ptr);
289 }  // namespace base::subtle
290 }  // namespace base
291
292 void MemoryBarrier();
293
294 #endif  // 0
295
296
297 // ------------------------------------------------------------------------
298 // The following are to be deprecated when all uses have been changed to
299 // use the base::subtle namespace.
300 // ------------------------------------------------------------------------
301
302 #ifdef AtomicWordCastType
303 // AtomicWord versions to be deprecated
304 inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr,
305                                          AtomicWord old_value,
306                                          AtomicWord new_value) {
307   return base::subtle::Acquire_CompareAndSwap(ptr, old_value, new_value);
308 }
309
310 inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr,
311                                          AtomicWord old_value,
312                                          AtomicWord new_value) {
313   return base::subtle::Release_CompareAndSwap(ptr, old_value, new_value);
314 }
315
316 inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
317   return base::subtle::Acquire_Store(ptr, value);
318 }
319
320 inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) {
321   return base::subtle::Release_Store(ptr, value);
322 }
323
324 inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) {
325   return base::subtle::Acquire_Load(ptr);
326 }
327
328 inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
329   return base::subtle::Release_Load(ptr);
330 }
331 #endif  // AtomicWordCastType
332
333 // 32-bit Acquire/Release operations to be deprecated.
334
335 inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
336                                        Atomic32 old_value,
337                                        Atomic32 new_value) {
338   return base::subtle::Acquire_CompareAndSwap(ptr, old_value, new_value);
339 }
340 inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
341                                        Atomic32 old_value,
342                                        Atomic32 new_value) {
343   return base::subtle::Release_CompareAndSwap(ptr, old_value, new_value);
344 }
345 inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
346   base::subtle::Acquire_Store(ptr, value);
347 }
348 inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
349   return base::subtle::Release_Store(ptr, value);
350 }
351 inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
352   return base::subtle::Acquire_Load(ptr);
353 }
354 inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
355   return base::subtle::Release_Load(ptr);
356 }
357
358 #ifdef BASE_HAS_ATOMIC64
359
360 // 64-bit Acquire/Release operations to be deprecated.
361
362 inline base::subtle::Atomic64 Acquire_CompareAndSwap(
363     volatile base::subtle::Atomic64* ptr,
364     base::subtle::Atomic64 old_value, base::subtle::Atomic64 new_value) {
365   return base::subtle::Acquire_CompareAndSwap(ptr, old_value, new_value);
366 }
367 inline base::subtle::Atomic64 Release_CompareAndSwap(
368     volatile base::subtle::Atomic64* ptr,
369     base::subtle::Atomic64 old_value, base::subtle::Atomic64 new_value) {
370   return base::subtle::Release_CompareAndSwap(ptr, old_value, new_value);
371 }
372 inline void Acquire_Store(
373     volatile base::subtle::Atomic64* ptr, base::subtle::Atomic64 value) {
374   base::subtle::Acquire_Store(ptr, value);
375 }
376 inline void Release_Store(
377     volatile base::subtle::Atomic64* ptr, base::subtle::Atomic64 value) {
378   return base::subtle::Release_Store(ptr, value);
379 }
380 inline base::subtle::Atomic64 Acquire_Load(
381     volatile const base::subtle::Atomic64* ptr) {
382   return base::subtle::Acquire_Load(ptr);
383 }
384 inline base::subtle::Atomic64 Release_Load(
385     volatile const base::subtle::Atomic64* ptr) {
386   return base::subtle::Release_Load(ptr);
387 }
388
389 #endif  // BASE_HAS_ATOMIC64
390
391 #endif  // THREAD_ATOMICOPS_H_