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