1
// Protocol Buffers - Google's data interchange format
2
// Copyright 2012 Google Inc. All rights reserved.
3
// http://code.google.com/p/protobuf/
5
// Redistribution and use in source and binary forms, with or without
6
// modification, are permitted provided that the following conditions are
9
// * Redistributions of source code must retain the above copyright
10
// notice, this list of conditions and the following disclaimer.
11
// * Redistributions in binary form must reproduce the above
12
// copyright notice, this list of conditions and the following disclaimer
13
// in the documentation and/or other materials provided with the
15
// * Neither the name of Google Inc. nor the names of its
16
// contributors may be used to endorse or promote products derived from
17
// this software without specific prior written permission.
19
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
// The routines exported by this module are subtle. If you use them, even if
32
// you get the code right, it will depend on careful reasoning about atomicity
33
// and memory ordering; it will be less readable, and harder to maintain. If
34
// you plan to use these routines, you should have a good reason, such as solid
35
// evidence that performance would otherwise suffer, or there being no
36
// alternative. You should assume only properties explicitly guaranteed by the
37
// specifications in this file. You are almost certainly _not_ writing code
38
// just for the x86; if you assume x86 semantics, x86 hardware bugs and
39
// implementations on other archtectures will cause your code to break. If you
40
// do not know what you are doing, avoid these routines, and use a Mutex.
42
// It is incorrect to make direct assignments to/from an atomic variable.
43
// You should use one of the Load or Store routines. The NoBarrier
44
// versions are provided when no barriers are needed:
47
// Although there are currently no compiler enforcement, you are encouraged
50
// This header and the implementations for each platform (located in
51
// atomicops_internals_*) must be kept in sync with the upstream code (V8).
53
#ifndef GOOGLE_PROTOBUF_ATOMICOPS_H_
54
#define GOOGLE_PROTOBUF_ATOMICOPS_H_
56
// Don't include this file for people not concerned about thread safety.
57
#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY
59
#include <google/protobuf/stubs/platform_macros.h>
65
typedef int32 Atomic32;
66
#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT
67
// We need to be able to go between Atomic64 and AtomicWord implicitly. This
68
// means Atomic64 and AtomicWord should be the same type on 64-bit.
69
#if defined(__ILP32__) || defined(GOOGLE_PROTOBUF_OS_NACL)
70
// NaCl's intptr_t is not actually 64-bits on 64-bit!
71
// http://code.google.com/p/nativeclient/issues/detail?id=1162
72
typedef int64 Atomic64;
74
typedef intptr_t Atomic64;
78
// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or
79
// Atomic64 routines below, depending on your architecture.
80
typedef intptr_t AtomicWord;
82
// Atomically execute:
84
// if (*ptr == old_value)
88
// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
89
// Always return the old value of "*ptr"
91
// This routine implies no memory barriers.
92
Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
96
// Atomically store new_value into *ptr, returning the previous value held in
97
// *ptr. This routine implies no memory barriers.
98
Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value);
100
// Atomically increment *ptr by "increment". Returns the new value of
101
// *ptr with the increment applied. This routine implies no memory barriers.
102
Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment);
104
Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
107
// These following lower-level operations are typically useful only to people
108
// implementing higher-level synchronization operations like spinlocks,
109
// mutexes, and condition-variables. They combine CompareAndSwap(), a load, or
110
// a store with appropriate memory-ordering instructions. "Acquire" operations
111
// ensure that no later memory access can be reordered ahead of the operation.
112
// "Release" operations ensure that no previous memory access can be reordered
113
// after the operation. "Barrier" operations have both "Acquire" and "Release"
114
// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory
116
Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
119
Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
123
void MemoryBarrier();
124
void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value);
125
void Acquire_Store(volatile Atomic32* ptr, Atomic32 value);
126
void Release_Store(volatile Atomic32* ptr, Atomic32 value);
128
Atomic32 NoBarrier_Load(volatile const Atomic32* ptr);
129
Atomic32 Acquire_Load(volatile const Atomic32* ptr);
130
Atomic32 Release_Load(volatile const Atomic32* ptr);
132
// 64-bit atomic operations (only available on 64-bit processors).
133
#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT
134
Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
137
Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value);
138
Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
139
Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
141
Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
144
Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
147
void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value);
148
void Acquire_Store(volatile Atomic64* ptr, Atomic64 value);
149
void Release_Store(volatile Atomic64* ptr, Atomic64 value);
150
Atomic64 NoBarrier_Load(volatile const Atomic64* ptr);
151
Atomic64 Acquire_Load(volatile const Atomic64* ptr);
152
Atomic64 Release_Load(volatile const Atomic64* ptr);
153
#endif // GOOGLE_PROTOBUF_ARCH_64_BIT
155
} // namespace internal
156
} // namespace protobuf
157
} // namespace google
159
// Include our platform specific implementation.
160
#define GOOGLE_PROTOBUF_ATOMICOPS_ERROR \
161
#error "Atomic operations are not supported on your platform"
163
// ThreadSanitizer, http://clang.llvm.org/docs/ThreadSanitizer.html.
164
#if defined(THREAD_SANITIZER)
165
#include <google/protobuf/stubs/atomicops_internals_tsan.h>
167
#elif defined(_MSC_VER)
168
#if defined(GOOGLE_PROTOBUF_ARCH_IA32) || defined(GOOGLE_PROTOBUF_ARCH_X64)
169
#include <google/protobuf/stubs/atomicops_internals_x86_msvc.h>
171
GOOGLE_PROTOBUF_ATOMICOPS_ERROR
175
#elif defined(GOOGLE_PROTOBUF_OS_APPLE)
176
#include <google/protobuf/stubs/atomicops_internals_macosx.h>
179
#elif defined(__GNUC__)
180
#if defined(GOOGLE_PROTOBUF_ARCH_IA32) || defined(GOOGLE_PROTOBUF_ARCH_X64)
181
#include <google/protobuf/stubs/atomicops_internals_x86_gcc.h>
182
#elif defined(GOOGLE_PROTOBUF_ARCH_ARM)
183
#include <google/protobuf/stubs/atomicops_internals_arm_gcc.h>
184
#elif defined(GOOGLE_PROTOBUF_ARCH_ARM_QNX)
185
#include <google/protobuf/stubs/atomicops_internals_arm_qnx.h>
186
#elif defined(GOOGLE_PROTOBUF_ARCH_MIPS)
187
#include <google/protobuf/stubs/atomicops_internals_mips_gcc.h>
188
#elif defined(__pnacl__)
189
#include <google/protobuf/stubs/atomicops_internals_pnacl.h>
191
GOOGLE_PROTOBUF_ATOMICOPS_ERROR
196
GOOGLE_PROTOBUF_ATOMICOPS_ERROR
199
// On some platforms we need additional declarations to make AtomicWord
200
// compatible with our other Atomic* types.
201
#if defined(GOOGLE_PROTOBUF_OS_APPLE)
202
#include <google/protobuf/stubs/atomicops_internals_atomicword_compat.h>
205
#undef GOOGLE_PROTOBUF_ATOMICOPS_ERROR
207
#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY
209
#endif // GOOGLE_PROTOBUF_ATOMICOPS_H_