Coverage Report

Created: 2024-11-20 21:05

/root/doris/be/src/gutil/atomicops.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2003 Google Inc.
2
// All Rights Reserved.
3
//
4
5
// For atomic operations on statistics counters, see atomic_stats_counter.h.
6
// For atomic operations on sequence numbers, see atomic_sequence_num.h.
7
// For atomic operations on reference counts, see atomic_refcount.h.
8
9
// Some fast atomic operations -- typically with machine-dependent
10
// implementations.  This file may need editing as Google code is
11
// ported to different architectures.
12
13
// The routines exported by this module are subtle.  If you use them, even if
14
// you get the code right, it will depend on careful reasoning about atomicity
15
// and memory ordering; it will be less readable, and harder to maintain.  If
16
// you plan to use these routines, you should have a good reason, such as solid
17
// evidence that performance would otherwise suffer, or there being no
18
// alternative.  You should assume only properties explicitly guaranteed by the
19
// specifications in this file.  You are almost certainly _not_ writing code
20
// just for the x86; if you assume x86 semantics, x86 hardware bugs and
21
// implementations on other architectures will cause your code to break.  If you
22
// do not know what you are doing, avoid these routines, and use a Mutex.
23
//
24
// These following lower-level operations are typically useful only to people
25
// implementing higher-level synchronization operations like spinlocks,
26
// mutexes, and condition-variables.  They combine CompareAndSwap(),
27
// addition, exchange, a load, or a store with appropriate memory-ordering
28
// instructions.  "Acquire" operations ensure that no later memory access by
29
// the same thread can be reordered ahead of the operation.  "Release"
30
// operations ensure that no previous memory access by the same thread can be
31
// reordered after the operation.  "Barrier" operations have both "Acquire" and
32
// "Release" semantics.  A MemoryBarrier() has "Barrier" semantics, but does no
33
// memory access.  "NoBarrier" operations have no barrier:  the CPU is
34
// permitted to reorder them freely (as seen by other threads), even in ways
35
// the appear to violate functional dependence, just as it can for any normal
36
// variable access.
37
//
38
// It is incorrect to make direct assignments to/from an atomic variable.
39
// You should use one of the Load or Store routines.  The NoBarrier
40
// versions are provided when no barriers are needed:
41
//   NoBarrier_Store()
42
//   NoBarrier_Load()
43
// Although there are currently no compiler enforcement, you are encouraged
44
// to use these.  Moreover, if you choose to use base::subtle::Atomic64 type,
45
// you MUST use one of the Load or Store routines to get correct behavior
46
// on 32-bit platforms.
47
//
48
// The intent is eventually to put all of these routines in namespace
49
// base::subtle
50
51
#pragma once
52
53
#include <stdint.h>
54
55
// ------------------------------------------------------------------------
56
// Include the platform specific implementations of the types
57
// and operations listed below.  Implementations are to provide Atomic32
58
// and Atomic64 operations. If there is a mismatch between intptr_t and
59
// the Atomic32 or Atomic64 types for a platform, the platform-specific header
60
// should define the macro, AtomicWordCastType in a clause similar to the
61
// following:
62
// #if ...pointers are 64 bits...
63
// # define AtomicWordCastType base::subtle::Atomic64
64
// #else
65
// # define AtomicWordCastType Atomic32
66
// #endif
67
// ------------------------------------------------------------------------
68
69
#define GUTILS_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
70
71
#define GUTILS_CLANG_VERSION \
72
    (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
73
74
// ThreadSanitizer provides own implementation of atomicops.
75
#if defined(THREAD_SANITIZER)
76
#include "gutil/atomicops-internals-tsan.h" // IWYU pragma: export
77
#elif defined(__GNUC__) && (defined(__i386) || defined(__x86_64__))
78
#include "gutil/atomicops-internals-x86.h" // IWYU pragma: export
79
#elif defined(__GNUC__) && GUTILS_GCC_VERSION >= 40700
80
#include "gutil/atomicops-internals-gcc.h" // IWYU pragma: export
81
#elif defined(__clang__) && GUTILS_CLANG_VERSION >= 30400
82
#include "gutil/atomicops-internals-gcc.h" // IWYU pragma: export
83
#else
84
#error You need to implement atomic operations for this architecture
85
#endif
86
87
// Signed type that can hold a pointer and supports the atomic ops below, as
88
// well as atomic loads and stores.  Instances must be naturally-aligned.
89
typedef intptr_t AtomicWord;
90
91
#ifdef AtomicWordCastType
92
// ------------------------------------------------------------------------
93
// This section is needed only when explicit type casting is required to
94
// cast AtomicWord to one of the basic atomic types (Atomic64 or Atomic32).
95
// It also serves to document the AtomicWord interface.
96
// ------------------------------------------------------------------------
97
98
namespace base {
99
namespace subtle {
100
101
// Atomically execute:
102
//      result = *ptr;
103
//      if (*ptr == old_value)
104
//        *ptr = new_value;
105
//      return result;
106
//
107
// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
108
// Always return the old value of "*ptr"
109
//
110
// This routine implies no memory barriers.
111
inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr, AtomicWord old_value,
112
                                           AtomicWord new_value) {
113
    return NoBarrier_CompareAndSwap(reinterpret_cast<volatile AtomicWordCastType*>(ptr), old_value,
114
                                    new_value);
115
}
116
117
// Atomically store new_value into *ptr, returning the previous value held in
118
// *ptr.  This routine implies no memory barriers.
119
inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr, AtomicWord new_value) {
120
    return NoBarrier_AtomicExchange(reinterpret_cast<volatile AtomicWordCastType*>(ptr), new_value);
121
}
122
123
inline AtomicWord Acquire_AtomicExchange(volatile AtomicWord* ptr, AtomicWord new_value) {
124
    return Acquire_AtomicExchange(reinterpret_cast<volatile AtomicWordCastType*>(ptr), new_value);
125
}
126
127
inline AtomicWord Release_AtomicExchange(volatile AtomicWord* ptr, AtomicWord new_value) {
128
    return Release_AtomicExchange(reinterpret_cast<volatile AtomicWordCastType*>(ptr), new_value);
129
}
130
131
// Atomically increment *ptr by "increment".  Returns the new value of
132
// *ptr with the increment applied.  This routine implies no memory
133
// barriers.
134
inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr, AtomicWord increment) {
135
    return NoBarrier_AtomicIncrement(reinterpret_cast<volatile AtomicWordCastType*>(ptr),
136
                                     increment);
137
}
138
139
inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr, AtomicWord increment) {
140
    return Barrier_AtomicIncrement(reinterpret_cast<volatile AtomicWordCastType*>(ptr), increment);
141
}
142
143
inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr, AtomicWord old_value,
144
                                         AtomicWord new_value) {
145
    return base::subtle::Acquire_CompareAndSwap(reinterpret_cast<volatile AtomicWordCastType*>(ptr),
146
                                                old_value, new_value);
147
}
148
149
inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr, AtomicWord old_value,
150
                                         AtomicWord new_value) {
151
    return base::subtle::Release_CompareAndSwap(reinterpret_cast<volatile AtomicWordCastType*>(ptr),
152
                                                old_value, new_value);
153
}
154
155
inline void NoBarrier_Store(volatile AtomicWord* ptr, AtomicWord value) {
156
    NoBarrier_Store(reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
157
}
158
159
inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
160
    return base::subtle::Acquire_Store(reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
161
}
162
163
inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) {
164
    return base::subtle::Release_Store(reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
165
}
166
167
inline AtomicWord NoBarrier_Load(volatile const AtomicWord* ptr) {
168
    return NoBarrier_Load(reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
169
}
170
171
inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) {
172
    return base::subtle::Acquire_Load(reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
173
}
174
175
inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
176
    return base::subtle::Release_Load(reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
177
}
178
179
} // namespace subtle
180
} // namespace base
181
#endif // AtomicWordCastType
182
183
// ------------------------------------------------------------------------
184
// Commented out type definitions and method declarations for documentation
185
// of the interface provided by this module.
186
// ------------------------------------------------------------------------
187
188
// ------------------------------------------------------------------------
189
// The following are to be deprecated when all uses have been changed to
190
// use the base::subtle namespace.
191
// ------------------------------------------------------------------------
192
193
#ifdef AtomicWordCastType
194
// AtomicWord versions to be deprecated
195
inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr, AtomicWord old_value,
196
                                         AtomicWord new_value) {
197
    return base::subtle::Acquire_CompareAndSwap(ptr, old_value, new_value);
198
}
199
200
inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr, AtomicWord old_value,
201
                                         AtomicWord new_value) {
202
    return base::subtle::Release_CompareAndSwap(ptr, old_value, new_value);
203
}
204
205
inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
206
    return base::subtle::Acquire_Store(ptr, value);
207
}
208
209
inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) {
210
    return base::subtle::Release_Store(ptr, value);
211
}
212
213
inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) {
214
    return base::subtle::Acquire_Load(ptr);
215
}
216
217
inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
218
    return base::subtle::Release_Load(ptr);
219
}
220
#endif // AtomicWordCastType
221
222
// 32-bit Acquire/Release operations to be deprecated.
223
224
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, Atomic32 old_value,
225
0
                                       Atomic32 new_value) {
226
0
    return base::subtle::Acquire_CompareAndSwap(ptr, old_value, new_value);
227
0
}
228
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, Atomic32 old_value,
229
0
                                       Atomic32 new_value) {
230
0
    return base::subtle::Release_CompareAndSwap(ptr, old_value, new_value);
231
0
}
232
0
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
233
0
    base::subtle::Acquire_Store(ptr, value);
234
0
}
235
0
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
236
0
    return base::subtle::Release_Store(ptr, value);
237
0
}
238
0
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
239
0
    return base::subtle::Acquire_Load(ptr);
240
0
}
241
0
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
242
0
    return base::subtle::Release_Load(ptr);
243
0
}
244
245
// 64-bit Acquire/Release operations to be deprecated.
246
247
inline base::subtle::Atomic64 Acquire_CompareAndSwap(volatile base::subtle::Atomic64* ptr,
248
                                                     base::subtle::Atomic64 old_value,
249
0
                                                     base::subtle::Atomic64 new_value) {
250
0
    return base::subtle::Acquire_CompareAndSwap(ptr, old_value, new_value);
251
0
}
252
inline base::subtle::Atomic64 Release_CompareAndSwap(volatile base::subtle::Atomic64* ptr,
253
                                                     base::subtle::Atomic64 old_value,
254
0
                                                     base::subtle::Atomic64 new_value) {
255
0
    return base::subtle::Release_CompareAndSwap(ptr, old_value, new_value);
256
0
}
257
0
inline void Acquire_Store(volatile base::subtle::Atomic64* ptr, base::subtle::Atomic64 value) {
258
0
    base::subtle::Acquire_Store(ptr, value);
259
0
}
260
2.43k
inline void Release_Store(volatile base::subtle::Atomic64* ptr, base::subtle::Atomic64 value) {
261
2.43k
    return base::subtle::Release_Store(ptr, value);
262
2.43k
}
263
44
inline base::subtle::Atomic64 Acquire_Load(volatile const base::subtle::Atomic64* ptr) {
264
44
    return base::subtle::Acquire_Load(ptr);
265
44
}
266
0
inline base::subtle::Atomic64 Release_Load(volatile const base::subtle::Atomic64* ptr) {
267
0
    return base::subtle::Release_Load(ptr);
268
0
}