michael@0: // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: // This file is an internal atomic implementation, use base/atomicops.h instead. michael@0: michael@0: #ifndef BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_ michael@0: #define BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_ michael@0: michael@0: #include michael@0: michael@0: namespace base { michael@0: namespace subtle { michael@0: michael@0: inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, michael@0: Atomic32 old_value, michael@0: Atomic32 new_value) { michael@0: LONG result = InterlockedCompareExchange( michael@0: reinterpret_cast(ptr), michael@0: static_cast(new_value), michael@0: static_cast(old_value)); michael@0: return static_cast(result); michael@0: } michael@0: michael@0: inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, michael@0: Atomic32 new_value) { michael@0: LONG result = InterlockedExchange( michael@0: reinterpret_cast(ptr), michael@0: static_cast(new_value)); michael@0: return static_cast(result); michael@0: } michael@0: michael@0: inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, michael@0: Atomic32 increment) { michael@0: return InterlockedExchangeAdd( michael@0: reinterpret_cast(ptr), michael@0: static_cast(increment)) + increment; michael@0: } michael@0: michael@0: inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, michael@0: Atomic32 increment) { michael@0: return Barrier_AtomicIncrement(ptr, increment); michael@0: } michael@0: michael@0: #if defined(_MSC_VER) && (_MSC_VER < 1400) michael@0: #error "We require at least vs2005 for MemoryBarrier" michael@0: #endif michael@0: inline void MemoryBarrier() { michael@0: // We use MemoryBarrier from WinNT.h michael@0: ::MemoryBarrier(); michael@0: } michael@0: michael@0: inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, michael@0: Atomic32 old_value, michael@0: Atomic32 new_value) { michael@0: return NoBarrier_CompareAndSwap(ptr, old_value, new_value); michael@0: } michael@0: michael@0: inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, michael@0: Atomic32 old_value, michael@0: Atomic32 new_value) { michael@0: return NoBarrier_CompareAndSwap(ptr, old_value, new_value); michael@0: } michael@0: michael@0: inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { michael@0: *ptr = value; michael@0: } michael@0: michael@0: inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { michael@0: NoBarrier_AtomicExchange(ptr, value); michael@0: // acts as a barrier in this implementation michael@0: } michael@0: michael@0: inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { michael@0: *ptr = value; // works w/o barrier for current Intel chips as of June 2005 michael@0: // See comments in Atomic64 version of Release_Store() below. michael@0: } michael@0: michael@0: inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { michael@0: return *ptr; michael@0: } michael@0: michael@0: inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { michael@0: Atomic32 value = *ptr; michael@0: return value; michael@0: } michael@0: michael@0: inline Atomic32 Release_Load(volatile const Atomic32* ptr) { michael@0: MemoryBarrier(); michael@0: return *ptr; michael@0: } michael@0: michael@0: #if defined(_WIN64) michael@0: michael@0: // 64-bit low-level operations on 64-bit platform. michael@0: michael@0: COMPILE_ASSERT(sizeof(Atomic64) == sizeof(PVOID), atomic_word_is_atomic); michael@0: michael@0: inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, michael@0: Atomic64 old_value, michael@0: Atomic64 new_value) { michael@0: PVOID result = InterlockedCompareExchangePointer( michael@0: reinterpret_cast(ptr), michael@0: reinterpret_cast(new_value), reinterpret_cast(old_value)); michael@0: return reinterpret_cast(result); michael@0: } michael@0: michael@0: inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, michael@0: Atomic64 new_value) { michael@0: PVOID result = InterlockedExchangePointer( michael@0: reinterpret_cast(ptr), michael@0: reinterpret_cast(new_value)); michael@0: return reinterpret_cast(result); michael@0: } michael@0: michael@0: inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, michael@0: Atomic64 increment) { michael@0: return InterlockedExchangeAdd64( michael@0: reinterpret_cast(ptr), michael@0: static_cast(increment)) + increment; michael@0: } michael@0: michael@0: inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, michael@0: Atomic64 increment) { michael@0: return Barrier_AtomicIncrement(ptr, increment); michael@0: } michael@0: michael@0: inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, michael@0: Atomic64 old_value, michael@0: Atomic64 new_value) { michael@0: return NoBarrier_CompareAndSwap(ptr, old_value, new_value); michael@0: } michael@0: michael@0: inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, michael@0: Atomic64 old_value, michael@0: Atomic64 new_value) { michael@0: return NoBarrier_CompareAndSwap(ptr, old_value, new_value); michael@0: } michael@0: michael@0: inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { michael@0: *ptr = value; michael@0: } michael@0: michael@0: inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { michael@0: NoBarrier_AtomicExchange(ptr, value); michael@0: // acts as a barrier in this implementation michael@0: } michael@0: michael@0: inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { michael@0: *ptr = value; // works w/o barrier for current Intel chips as of June 2005 michael@0: michael@0: // When new chips come out, check: michael@0: // IA-32 Intel Architecture Software Developer's Manual, Volume 3: michael@0: // System Programming Guide, Chatper 7: Multiple-processor management, michael@0: // Section 7.2, Memory Ordering. michael@0: // Last seen at: michael@0: // http://developer.intel.com/design/pentium4/manuals/index_new.htm michael@0: } michael@0: michael@0: inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { michael@0: return *ptr; michael@0: } michael@0: michael@0: inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { michael@0: Atomic64 value = *ptr; michael@0: return value; michael@0: } michael@0: michael@0: inline Atomic64 Release_Load(volatile const Atomic64* ptr) { michael@0: MemoryBarrier(); michael@0: return *ptr; michael@0: } michael@0: michael@0: #endif // defined(_WIN64) michael@0: michael@0: } // namespace base::subtle michael@0: } // namespace base michael@0: michael@0: #endif // BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_