xref: /aosp_15_r20/external/libchrome/base/atomicops.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker // For atomic operations on reference counts, see atomic_refcount.h.
6*635a8641SAndroid Build Coastguard Worker // For atomic operations on sequence numbers, see atomic_sequence_num.h.
7*635a8641SAndroid Build Coastguard Worker 
8*635a8641SAndroid Build Coastguard Worker // The routines exported by this module are subtle.  If you use them, even if
9*635a8641SAndroid Build Coastguard Worker // you get the code right, it will depend on careful reasoning about atomicity
10*635a8641SAndroid Build Coastguard Worker // and memory ordering; it will be less readable, and harder to maintain.  If
11*635a8641SAndroid Build Coastguard Worker // you plan to use these routines, you should have a good reason, such as solid
12*635a8641SAndroid Build Coastguard Worker // evidence that performance would otherwise suffer, or there being no
13*635a8641SAndroid Build Coastguard Worker // alternative.  You should assume only properties explicitly guaranteed by the
14*635a8641SAndroid Build Coastguard Worker // specifications in this file.  You are almost certainly _not_ writing code
15*635a8641SAndroid Build Coastguard Worker // just for the x86; if you assume x86 semantics, x86 hardware bugs and
16*635a8641SAndroid Build Coastguard Worker // implementations on other archtectures will cause your code to break.  If you
17*635a8641SAndroid Build Coastguard Worker // do not know what you are doing, avoid these routines, and use a Mutex.
18*635a8641SAndroid Build Coastguard Worker //
19*635a8641SAndroid Build Coastguard Worker // It is incorrect to make direct assignments to/from an atomic variable.
20*635a8641SAndroid Build Coastguard Worker // You should use one of the Load or Store routines.  The NoBarrier
21*635a8641SAndroid Build Coastguard Worker // versions are provided when no barriers are needed:
22*635a8641SAndroid Build Coastguard Worker //   NoBarrier_Store()
23*635a8641SAndroid Build Coastguard Worker //   NoBarrier_Load()
24*635a8641SAndroid Build Coastguard Worker // Although there are currently no compiler enforcement, you are encouraged
25*635a8641SAndroid Build Coastguard Worker // to use these.
26*635a8641SAndroid Build Coastguard Worker //
27*635a8641SAndroid Build Coastguard Worker 
28*635a8641SAndroid Build Coastguard Worker #ifndef BASE_ATOMICOPS_H_
29*635a8641SAndroid Build Coastguard Worker #define BASE_ATOMICOPS_H_
30*635a8641SAndroid Build Coastguard Worker 
31*635a8641SAndroid Build Coastguard Worker #include <stdint.h>
32*635a8641SAndroid Build Coastguard Worker 
33*635a8641SAndroid Build Coastguard Worker // Small C++ header which defines implementation specific macros used to
34*635a8641SAndroid Build Coastguard Worker // identify the STL implementation.
35*635a8641SAndroid Build Coastguard Worker // - libc++: captures __config for _LIBCPP_VERSION
36*635a8641SAndroid Build Coastguard Worker // - libstdc++: captures bits/c++config.h for __GLIBCXX__
37*635a8641SAndroid Build Coastguard Worker #include <cstddef>
38*635a8641SAndroid Build Coastguard Worker 
39*635a8641SAndroid Build Coastguard Worker #include "base/base_export.h"
40*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
41*635a8641SAndroid Build Coastguard Worker 
42*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN) && defined(ARCH_CPU_64_BITS)
43*635a8641SAndroid Build Coastguard Worker // windows.h #defines this (only on x64). This causes problems because the
44*635a8641SAndroid Build Coastguard Worker // public API also uses MemoryBarrier at the public name for this fence. So, on
45*635a8641SAndroid Build Coastguard Worker // X64, undef it, and call its documented
46*635a8641SAndroid Build Coastguard Worker // (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx)
47*635a8641SAndroid Build Coastguard Worker // implementation directly.
48*635a8641SAndroid Build Coastguard Worker #undef MemoryBarrier
49*635a8641SAndroid Build Coastguard Worker #endif
50*635a8641SAndroid Build Coastguard Worker 
51*635a8641SAndroid Build Coastguard Worker namespace base {
52*635a8641SAndroid Build Coastguard Worker namespace subtle {
53*635a8641SAndroid Build Coastguard Worker 
54*635a8641SAndroid Build Coastguard Worker typedef int32_t Atomic32;
55*635a8641SAndroid Build Coastguard Worker #ifdef ARCH_CPU_64_BITS
56*635a8641SAndroid Build Coastguard Worker // We need to be able to go between Atomic64 and AtomicWord implicitly.  This
57*635a8641SAndroid Build Coastguard Worker // means Atomic64 and AtomicWord should be the same type on 64-bit.
58*635a8641SAndroid Build Coastguard Worker #if defined(__ILP32__) || defined(OS_NACL)
59*635a8641SAndroid Build Coastguard Worker // NaCl's intptr_t is not actually 64-bits on 64-bit!
60*635a8641SAndroid Build Coastguard Worker // http://code.google.com/p/nativeclient/issues/detail?id=1162
61*635a8641SAndroid Build Coastguard Worker typedef int64_t Atomic64;
62*635a8641SAndroid Build Coastguard Worker #else
63*635a8641SAndroid Build Coastguard Worker typedef intptr_t Atomic64;
64*635a8641SAndroid Build Coastguard Worker #endif
65*635a8641SAndroid Build Coastguard Worker #endif
66*635a8641SAndroid Build Coastguard Worker 
67*635a8641SAndroid Build Coastguard Worker // Use AtomicWord for a machine-sized pointer.  It will use the Atomic32 or
68*635a8641SAndroid Build Coastguard Worker // Atomic64 routines below, depending on your architecture.
69*635a8641SAndroid Build Coastguard Worker typedef intptr_t AtomicWord;
70*635a8641SAndroid Build Coastguard Worker 
71*635a8641SAndroid Build Coastguard Worker // Atomically execute:
72*635a8641SAndroid Build Coastguard Worker //      result = *ptr;
73*635a8641SAndroid Build Coastguard Worker //      if (*ptr == old_value)
74*635a8641SAndroid Build Coastguard Worker //        *ptr = new_value;
75*635a8641SAndroid Build Coastguard Worker //      return result;
76*635a8641SAndroid Build Coastguard Worker //
77*635a8641SAndroid Build Coastguard Worker // I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
78*635a8641SAndroid Build Coastguard Worker // Always return the old value of "*ptr"
79*635a8641SAndroid Build Coastguard Worker //
80*635a8641SAndroid Build Coastguard Worker // This routine implies no memory barriers.
81*635a8641SAndroid Build Coastguard Worker Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
82*635a8641SAndroid Build Coastguard Worker                                   Atomic32 old_value,
83*635a8641SAndroid Build Coastguard Worker                                   Atomic32 new_value);
84*635a8641SAndroid Build Coastguard Worker 
85*635a8641SAndroid Build Coastguard Worker // Atomically store new_value into *ptr, returning the previous value held in
86*635a8641SAndroid Build Coastguard Worker // *ptr.  This routine implies no memory barriers.
87*635a8641SAndroid Build Coastguard Worker Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value);
88*635a8641SAndroid Build Coastguard Worker 
89*635a8641SAndroid Build Coastguard Worker // Atomically increment *ptr by "increment".  Returns the new value of
90*635a8641SAndroid Build Coastguard Worker // *ptr with the increment applied.  This routine implies no memory barriers.
91*635a8641SAndroid Build Coastguard Worker Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment);
92*635a8641SAndroid Build Coastguard Worker 
93*635a8641SAndroid Build Coastguard Worker Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
94*635a8641SAndroid Build Coastguard Worker                                  Atomic32 increment);
95*635a8641SAndroid Build Coastguard Worker 
96*635a8641SAndroid Build Coastguard Worker // These following lower-level operations are typically useful only to people
97*635a8641SAndroid Build Coastguard Worker // implementing higher-level synchronization operations like spinlocks,
98*635a8641SAndroid Build Coastguard Worker // mutexes, and condition-variables.  They combine CompareAndSwap(), a load, or
99*635a8641SAndroid Build Coastguard Worker // a store with appropriate memory-ordering instructions.  "Acquire" operations
100*635a8641SAndroid Build Coastguard Worker // ensure that no later memory access can be reordered ahead of the operation.
101*635a8641SAndroid Build Coastguard Worker // "Release" operations ensure that no previous memory access can be reordered
102*635a8641SAndroid Build Coastguard Worker // after the operation.  "Barrier" operations have both "Acquire" and "Release"
103*635a8641SAndroid Build Coastguard Worker // semantics.   A MemoryBarrier() has "Barrier" semantics, but does no memory
104*635a8641SAndroid Build Coastguard Worker // access.
105*635a8641SAndroid Build Coastguard Worker Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
106*635a8641SAndroid Build Coastguard Worker                                 Atomic32 old_value,
107*635a8641SAndroid Build Coastguard Worker                                 Atomic32 new_value);
108*635a8641SAndroid Build Coastguard Worker Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
109*635a8641SAndroid Build Coastguard Worker                                 Atomic32 old_value,
110*635a8641SAndroid Build Coastguard Worker                                 Atomic32 new_value);
111*635a8641SAndroid Build Coastguard Worker 
112*635a8641SAndroid Build Coastguard Worker void MemoryBarrier();
113*635a8641SAndroid Build Coastguard Worker void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value);
114*635a8641SAndroid Build Coastguard Worker void Acquire_Store(volatile Atomic32* ptr, Atomic32 value);
115*635a8641SAndroid Build Coastguard Worker void Release_Store(volatile Atomic32* ptr, Atomic32 value);
116*635a8641SAndroid Build Coastguard Worker 
117*635a8641SAndroid Build Coastguard Worker Atomic32 NoBarrier_Load(volatile const Atomic32* ptr);
118*635a8641SAndroid Build Coastguard Worker Atomic32 Acquire_Load(volatile const Atomic32* ptr);
119*635a8641SAndroid Build Coastguard Worker Atomic32 Release_Load(volatile const Atomic32* ptr);
120*635a8641SAndroid Build Coastguard Worker 
121*635a8641SAndroid Build Coastguard Worker // 64-bit atomic operations (only available on 64-bit processors).
122*635a8641SAndroid Build Coastguard Worker #ifdef ARCH_CPU_64_BITS
123*635a8641SAndroid Build Coastguard Worker Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
124*635a8641SAndroid Build Coastguard Worker                                   Atomic64 old_value,
125*635a8641SAndroid Build Coastguard Worker                                   Atomic64 new_value);
126*635a8641SAndroid Build Coastguard Worker Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value);
127*635a8641SAndroid Build Coastguard Worker Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
128*635a8641SAndroid Build Coastguard Worker Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
129*635a8641SAndroid Build Coastguard Worker 
130*635a8641SAndroid Build Coastguard Worker Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
131*635a8641SAndroid Build Coastguard Worker                                 Atomic64 old_value,
132*635a8641SAndroid Build Coastguard Worker                                 Atomic64 new_value);
133*635a8641SAndroid Build Coastguard Worker Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
134*635a8641SAndroid Build Coastguard Worker                                 Atomic64 old_value,
135*635a8641SAndroid Build Coastguard Worker                                 Atomic64 new_value);
136*635a8641SAndroid Build Coastguard Worker void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value);
137*635a8641SAndroid Build Coastguard Worker void Acquire_Store(volatile Atomic64* ptr, Atomic64 value);
138*635a8641SAndroid Build Coastguard Worker void Release_Store(volatile Atomic64* ptr, Atomic64 value);
139*635a8641SAndroid Build Coastguard Worker Atomic64 NoBarrier_Load(volatile const Atomic64* ptr);
140*635a8641SAndroid Build Coastguard Worker Atomic64 Acquire_Load(volatile const Atomic64* ptr);
141*635a8641SAndroid Build Coastguard Worker Atomic64 Release_Load(volatile const Atomic64* ptr);
142*635a8641SAndroid Build Coastguard Worker #endif  // ARCH_CPU_64_BITS
143*635a8641SAndroid Build Coastguard Worker 
144*635a8641SAndroid Build Coastguard Worker }  // namespace subtle
145*635a8641SAndroid Build Coastguard Worker }  // namespace base
146*635a8641SAndroid Build Coastguard Worker 
147*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
148*635a8641SAndroid Build Coastguard Worker // TODO(jfb): Try to use base/atomicops_internals_portable.h everywhere.
149*635a8641SAndroid Build Coastguard Worker // https://crbug.com/559247.
150*635a8641SAndroid Build Coastguard Worker #  include "base/atomicops_internals_x86_msvc.h"
151*635a8641SAndroid Build Coastguard Worker #else
152*635a8641SAndroid Build Coastguard Worker #  include "base/atomicops_internals_portable.h"
153*635a8641SAndroid Build Coastguard Worker #endif
154*635a8641SAndroid Build Coastguard Worker 
155*635a8641SAndroid Build Coastguard Worker // On some platforms we need additional declarations to make
156*635a8641SAndroid Build Coastguard Worker // AtomicWord compatible with our other Atomic* types.
157*635a8641SAndroid Build Coastguard Worker #if defined(OS_MACOSX) || defined(OS_OPENBSD)
158*635a8641SAndroid Build Coastguard Worker #include "base/atomicops_internals_atomicword_compat.h"
159*635a8641SAndroid Build Coastguard Worker #endif
160*635a8641SAndroid Build Coastguard Worker 
161*635a8641SAndroid Build Coastguard Worker #endif  // BASE_ATOMICOPS_H_
162