• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  // Protocol Buffers - Google's data interchange format
2  // Copyright 2013 Google Inc.  All rights reserved.
3  // https://developers.google.com/protocol-buffers/
4  //
5  // Redistribution and use in source and binary forms, with or without
6  // modification, are permitted provided that the following conditions are
7  // met:
8  //
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
14  // distribution.
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.
18  //
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.
30  
31  // This file is an internal atomic implementation for compiler-based
32  // ThreadSanitizer (http://clang.llvm.org/docs/ThreadSanitizer.html).
33  // Use atomicops.h instead.
34  
35  #ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_TSAN_H_
36  #define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_TSAN_H_
37  
38  #define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
39  
40  #include <sanitizer/tsan_interface_atomic.h>
41  
42  namespace google {
43  namespace protobuf {
44  namespace internal {
45  
NoBarrier_CompareAndSwap(volatile Atomic32 * ptr,Atomic32 old_value,Atomic32 new_value)46  inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr,
47                                           Atomic32 old_value,
48                                           Atomic32 new_value) {
49    Atomic32 cmp = old_value;
50    __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value,
51        __tsan_memory_order_relaxed, __tsan_memory_order_relaxed);
52    return cmp;
53  }
54  
NoBarrier_AtomicExchange(volatile Atomic32 * ptr,Atomic32 new_value)55  inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr,
56                                           Atomic32 new_value) {
57    return __tsan_atomic32_exchange(ptr, new_value,
58        __tsan_memory_order_relaxed);
59  }
60  
Acquire_AtomicExchange(volatile Atomic32 * ptr,Atomic32 new_value)61  inline Atomic32 Acquire_AtomicExchange(volatile Atomic32 *ptr,
62                                         Atomic32 new_value) {
63    return __tsan_atomic32_exchange(ptr, new_value,
64        __tsan_memory_order_acquire);
65  }
66  
Release_AtomicExchange(volatile Atomic32 * ptr,Atomic32 new_value)67  inline Atomic32 Release_AtomicExchange(volatile Atomic32 *ptr,
68                                         Atomic32 new_value) {
69    return __tsan_atomic32_exchange(ptr, new_value,
70        __tsan_memory_order_release);
71  }
72  
NoBarrier_AtomicIncrement(volatile Atomic32 * ptr,Atomic32 increment)73  inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr,
74                                            Atomic32 increment) {
75    return increment + __tsan_atomic32_fetch_add(ptr, increment,
76        __tsan_memory_order_relaxed);
77  }
78  
Barrier_AtomicIncrement(volatile Atomic32 * ptr,Atomic32 increment)79  inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr,
80                                          Atomic32 increment) {
81    return increment + __tsan_atomic32_fetch_add(ptr, increment,
82        __tsan_memory_order_acq_rel);
83  }
84  
Acquire_CompareAndSwap(volatile Atomic32 * ptr,Atomic32 old_value,Atomic32 new_value)85  inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr,
86                                         Atomic32 old_value,
87                                         Atomic32 new_value) {
88    Atomic32 cmp = old_value;
89    __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value,
90        __tsan_memory_order_acquire, __tsan_memory_order_acquire);
91    return cmp;
92  }
93  
Release_CompareAndSwap(volatile Atomic32 * ptr,Atomic32 old_value,Atomic32 new_value)94  inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr,
95                                         Atomic32 old_value,
96                                         Atomic32 new_value) {
97    Atomic32 cmp = old_value;
98    __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value,
99        __tsan_memory_order_release, __tsan_memory_order_relaxed);
100    return cmp;
101  }
102  
NoBarrier_Store(volatile Atomic32 * ptr,Atomic32 value)103  inline void NoBarrier_Store(volatile Atomic32 *ptr, Atomic32 value) {
104    __tsan_atomic32_store(ptr, value, __tsan_memory_order_relaxed);
105  }
106  
Acquire_Store(volatile Atomic32 * ptr,Atomic32 value)107  inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
108    __tsan_atomic32_store(ptr, value, __tsan_memory_order_relaxed);
109    __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
110  }
111  
Release_Store(volatile Atomic32 * ptr,Atomic32 value)112  inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) {
113    __tsan_atomic32_store(ptr, value, __tsan_memory_order_release);
114  }
115  
NoBarrier_Load(volatile const Atomic32 * ptr)116  inline Atomic32 NoBarrier_Load(volatile const Atomic32 *ptr) {
117    return __tsan_atomic32_load(ptr, __tsan_memory_order_relaxed);
118  }
119  
Acquire_Load(volatile const Atomic32 * ptr)120  inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) {
121    return __tsan_atomic32_load(ptr, __tsan_memory_order_acquire);
122  }
123  
Release_Load(volatile const Atomic32 * ptr)124  inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
125    __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
126    return __tsan_atomic32_load(ptr, __tsan_memory_order_relaxed);
127  }
128  
NoBarrier_CompareAndSwap(volatile Atomic64 * ptr,Atomic64 old_value,Atomic64 new_value)129  inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64 *ptr,
130                                           Atomic64 old_value,
131                                           Atomic64 new_value) {
132    Atomic64 cmp = old_value;
133    __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value,
134        __tsan_memory_order_relaxed, __tsan_memory_order_relaxed);
135    return cmp;
136  }
137  
NoBarrier_AtomicExchange(volatile Atomic64 * ptr,Atomic64 new_value)138  inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64 *ptr,
139                                           Atomic64 new_value) {
140    return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_relaxed);
141  }
142  
Acquire_AtomicExchange(volatile Atomic64 * ptr,Atomic64 new_value)143  inline Atomic64 Acquire_AtomicExchange(volatile Atomic64 *ptr,
144                                         Atomic64 new_value) {
145    return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_acquire);
146  }
147  
Release_AtomicExchange(volatile Atomic64 * ptr,Atomic64 new_value)148  inline Atomic64 Release_AtomicExchange(volatile Atomic64 *ptr,
149                                         Atomic64 new_value) {
150    return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_release);
151  }
152  
NoBarrier_AtomicIncrement(volatile Atomic64 * ptr,Atomic64 increment)153  inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr,
154                                            Atomic64 increment) {
155    return increment + __tsan_atomic64_fetch_add(ptr, increment,
156        __tsan_memory_order_relaxed);
157  }
158  
Barrier_AtomicIncrement(volatile Atomic64 * ptr,Atomic64 increment)159  inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr,
160                                          Atomic64 increment) {
161    return increment + __tsan_atomic64_fetch_add(ptr, increment,
162        __tsan_memory_order_acq_rel);
163  }
164  
NoBarrier_Store(volatile Atomic64 * ptr,Atomic64 value)165  inline void NoBarrier_Store(volatile Atomic64 *ptr, Atomic64 value) {
166    __tsan_atomic64_store(ptr, value, __tsan_memory_order_relaxed);
167  }
168  
Acquire_Store(volatile Atomic64 * ptr,Atomic64 value)169  inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
170    __tsan_atomic64_store(ptr, value, __tsan_memory_order_relaxed);
171    __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
172  }
173  
Release_Store(volatile Atomic64 * ptr,Atomic64 value)174  inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) {
175    __tsan_atomic64_store(ptr, value, __tsan_memory_order_release);
176  }
177  
NoBarrier_Load(volatile const Atomic64 * ptr)178  inline Atomic64 NoBarrier_Load(volatile const Atomic64 *ptr) {
179    return __tsan_atomic64_load(ptr, __tsan_memory_order_relaxed);
180  }
181  
Acquire_Load(volatile const Atomic64 * ptr)182  inline Atomic64 Acquire_Load(volatile const Atomic64 *ptr) {
183    return __tsan_atomic64_load(ptr, __tsan_memory_order_acquire);
184  }
185  
Release_Load(volatile const Atomic64 * ptr)186  inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
187    __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
188    return __tsan_atomic64_load(ptr, __tsan_memory_order_relaxed);
189  }
190  
Acquire_CompareAndSwap(volatile Atomic64 * ptr,Atomic64 old_value,Atomic64 new_value)191  inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr,
192                                         Atomic64 old_value,
193                                         Atomic64 new_value) {
194    Atomic64 cmp = old_value;
195    __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value,
196        __tsan_memory_order_acquire, __tsan_memory_order_acquire);
197    return cmp;
198  }
199  
Release_CompareAndSwap(volatile Atomic64 * ptr,Atomic64 old_value,Atomic64 new_value)200  inline Atomic64 Release_CompareAndSwap(volatile Atomic64 *ptr,
201                                         Atomic64 old_value,
202                                         Atomic64 new_value) {
203    Atomic64 cmp = old_value;
204    __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value,
205        __tsan_memory_order_release, __tsan_memory_order_relaxed);
206    return cmp;
207  }
208  
MemoryBarrier()209  inline void MemoryBarrier() {
210    __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
211  }
212  
213  }  // namespace internal
214  }  // namespace protobuf
215  }  // namespace google
216  
217  #undef ATOMICOPS_COMPILER_BARRIER
218  
219  #endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_TSAN_H_
220