1a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// Copyright 2010 the V8 project authors. All rights reserved. 23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be 33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file. 4a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 5a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// The routines exported by this module are subtle. If you use them, even if 6a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// you get the code right, it will depend on careful reasoning about atomicity 7a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// and memory ordering; it will be less readable, and harder to maintain. If 8a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// you plan to use these routines, you should have a good reason, such as solid 9a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// evidence that performance would otherwise suffer, or there being no 10a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// alternative. You should assume only properties explicitly guaranteed by the 11a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// specifications in this file. You are almost certainly _not_ writing code 12a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// just for the x86; if you assume x86 semantics, x86 hardware bugs and 13a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// implementations on other archtectures will cause your code to break. If you 14a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// do not know what you are doing, avoid these routines, and use a Mutex. 15a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// 16a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// It is incorrect to make direct assignments to/from an atomic variable. 17a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// You should use one of the Load or Store routines. The NoBarrier 18a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// versions are provided when no barriers are needed: 19a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// NoBarrier_Store() 20a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// NoBarrier_Load() 21a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// Although there are currently no compiler enforcement, you are encouraged 22a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// to use these. 23a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// 24a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 251e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#ifndef V8_BASE_ATOMICOPS_H_ 261e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#define V8_BASE_ATOMICOPS_H_ 27a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 28d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org#include "include/v8stdint.h" 29196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/base/build_config.h" 30a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 31ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org#if defined(_WIN32) && defined(V8_HOST_ARCH_64_BIT) 32ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org// windows.h #defines this (only on x64). This causes problems because the 33ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org// public API also uses MemoryBarrier at the public name for this fence. So, on 34ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org// X64, undef it, and call its documented 35ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx) 36ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org// implementation directly. 37ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org#undef MemoryBarrier 38ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org#endif 39ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org 40a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgnamespace v8 { 411e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.orgnamespace base { 42a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 435b080567cf135f6dbaf23973ba6b6fa1d6af83b3machenbach@chromium.orgtypedef char Atomic8; 44a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgtypedef int32_t Atomic32; 45a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#ifdef V8_HOST_ARCH_64_BIT 46a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// We need to be able to go between Atomic64 and AtomicWord implicitly. This 47a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// means Atomic64 and AtomicWord should be the same type on 64-bit. 48ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org#if defined(__ILP32__) 49a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgtypedef int64_t Atomic64; 50a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#else 51a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgtypedef intptr_t Atomic64; 52a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#endif 53a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#endif 54a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 55a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or 56a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// Atomic64 routines below, depending on your architecture. 57a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgtypedef intptr_t AtomicWord; 58a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 59a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// Atomically execute: 60a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// result = *ptr; 61a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// if (*ptr == old_value) 62a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// *ptr = new_value; 63a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// return result; 64a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// 65a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value". 66a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// Always return the old value of "*ptr" 67a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// 68a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// This routine implies no memory barriers. 69a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgAtomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, 70a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Atomic32 old_value, 71a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Atomic32 new_value); 72a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 73a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// Atomically store new_value into *ptr, returning the previous value held in 74a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// *ptr. This routine implies no memory barriers. 75a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgAtomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value); 76a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 77a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// Atomically increment *ptr by "increment". Returns the new value of 78a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// *ptr with the increment applied. This routine implies no memory barriers. 79a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgAtomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment); 80a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 81a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgAtomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, 82a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Atomic32 increment); 83a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 84a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// These following lower-level operations are typically useful only to people 85a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// implementing higher-level synchronization operations like spinlocks, 86a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// mutexes, and condition-variables. They combine CompareAndSwap(), a load, or 87a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// a store with appropriate memory-ordering instructions. "Acquire" operations 88a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// ensure that no later memory access can be reordered ahead of the operation. 89a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// "Release" operations ensure that no previous memory access can be reordered 90a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// after the operation. "Barrier" operations have both "Acquire" and "Release" 91a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory 92a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// access. 93a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgAtomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, 94a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Atomic32 old_value, 95a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Atomic32 new_value); 96a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgAtomic32 Release_CompareAndSwap(volatile Atomic32* ptr, 97a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Atomic32 old_value, 98a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Atomic32 new_value); 99a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 100a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid MemoryBarrier(); 1015b080567cf135f6dbaf23973ba6b6fa1d6af83b3machenbach@chromium.orgvoid NoBarrier_Store(volatile Atomic8* ptr, Atomic8 value); 102a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value); 103a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Acquire_Store(volatile Atomic32* ptr, Atomic32 value); 104a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Release_Store(volatile Atomic32* ptr, Atomic32 value); 105a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 1065b080567cf135f6dbaf23973ba6b6fa1d6af83b3machenbach@chromium.orgAtomic8 NoBarrier_Load(volatile const Atomic8* ptr); 107a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgAtomic32 NoBarrier_Load(volatile const Atomic32* ptr); 108a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgAtomic32 Acquire_Load(volatile const Atomic32* ptr); 109a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgAtomic32 Release_Load(volatile const Atomic32* ptr); 110a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 111a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// 64-bit atomic operations (only available on 64-bit processors). 112a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#ifdef V8_HOST_ARCH_64_BIT 113a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgAtomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, 114a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Atomic64 old_value, 115a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Atomic64 new_value); 116a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgAtomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value); 117a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgAtomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment); 118a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgAtomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment); 119a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 120a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgAtomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, 121a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Atomic64 old_value, 122a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Atomic64 new_value); 123a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgAtomic64 Release_CompareAndSwap(volatile Atomic64* ptr, 124a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Atomic64 old_value, 125a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Atomic64 new_value); 126a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value); 127a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Acquire_Store(volatile Atomic64* ptr, Atomic64 value); 128a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Release_Store(volatile Atomic64* ptr, Atomic64 value); 129a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgAtomic64 NoBarrier_Load(volatile const Atomic64* ptr); 130a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgAtomic64 Acquire_Load(volatile const Atomic64* ptr); 131a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgAtomic64 Release_Load(volatile const Atomic64* ptr); 132a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#endif // V8_HOST_ARCH_64_BIT 133a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 1341e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org} } // namespace v8::base 135a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 136a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// Include our platform specific implementation. 137fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org#if defined(THREAD_SANITIZER) 1381e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#include "src/base/atomicops_internals_tsan.h" 139e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org#elif defined(_MSC_VER) && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64) 1401e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#include "src/base/atomicops_internals_x86_msvc.h" 141ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org#elif defined(__APPLE__) 1421e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#include "src/base/atomicops_internals_mac.h" 143fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org#elif defined(__GNUC__) && V8_HOST_ARCH_ARM64 1441e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#include "src/base/atomicops_internals_arm64_gcc.h" 14593a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#elif defined(__GNUC__) && V8_HOST_ARCH_ARM 1461e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#include "src/base/atomicops_internals_arm_gcc.h" 147ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org#elif defined(__GNUC__) && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64) 1481e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#include "src/base/atomicops_internals_x86_gcc.h" 14993a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#elif defined(__GNUC__) && V8_HOST_ARCH_MIPS 1501e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#include "src/base/atomicops_internals_mips_gcc.h" 15112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#elif defined(__GNUC__) && V8_HOST_ARCH_MIPS64 15212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/base/atomicops_internals_mips64_gcc.h" 153a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#else 154a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#error "Atomic operations are not supported on your platform" 155a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#endif 156a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 157ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org// On some platforms we need additional declarations to make 158ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org// AtomicWord compatible with our other Atomic* types. 159ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org#if defined(__APPLE__) || defined(__OpenBSD__) 1601e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#include "src/base/atomicops_internals_atomicword_compat.h" 161ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org#endif 162ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org 1631e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#endif // V8_BASE_ATOMICOPS_H_ 164