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_MACOSX_H_ michael@0: #define BASE_ATOMICOPS_INTERNALS_X86_MACOSX_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: Atomic32 prev_value; michael@0: do { michael@0: if (OSAtomicCompareAndSwap32(old_value, new_value, michael@0: const_cast(ptr))) { michael@0: return old_value; michael@0: } michael@0: prev_value = *ptr; michael@0: } while (prev_value == old_value); michael@0: return prev_value; michael@0: } michael@0: michael@0: inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr, michael@0: Atomic32 new_value) { michael@0: Atomic32 old_value; michael@0: do { michael@0: old_value = *ptr; michael@0: } while (!OSAtomicCompareAndSwap32(old_value, new_value, michael@0: const_cast(ptr))); michael@0: return old_value; michael@0: } michael@0: michael@0: inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr, michael@0: Atomic32 increment) { michael@0: return OSAtomicAdd32(increment, const_cast(ptr)); michael@0: } michael@0: michael@0: inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr, michael@0: Atomic32 increment) { michael@0: return OSAtomicAdd32Barrier(increment, const_cast(ptr)); michael@0: } michael@0: michael@0: inline void MemoryBarrier() { michael@0: OSMemoryBarrier(); 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: Atomic32 prev_value; michael@0: do { michael@0: if (OSAtomicCompareAndSwap32Barrier(old_value, new_value, michael@0: const_cast(ptr))) { michael@0: return old_value; michael@0: } michael@0: prev_value = *ptr; michael@0: } while (prev_value == old_value); michael@0: return prev_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 Acquire_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: *ptr = value; michael@0: MemoryBarrier(); michael@0: } michael@0: michael@0: inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) { michael@0: MemoryBarrier(); michael@0: *ptr = value; 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: MemoryBarrier(); 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: #ifdef __LP64__ michael@0: michael@0: // 64-bit implementation on 64-bit platform michael@0: michael@0: inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64 *ptr, michael@0: Atomic64 old_value, michael@0: Atomic64 new_value) { michael@0: Atomic64 prev_value; michael@0: do { michael@0: if (OSAtomicCompareAndSwap64(old_value, new_value, michael@0: const_cast(ptr))) { michael@0: return old_value; michael@0: } michael@0: prev_value = *ptr; michael@0: } while (prev_value == old_value); michael@0: return prev_value; michael@0: } michael@0: michael@0: inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64 *ptr, michael@0: Atomic64 new_value) { michael@0: Atomic64 old_value; michael@0: do { michael@0: old_value = *ptr; michael@0: } while (!OSAtomicCompareAndSwap64(old_value, new_value, michael@0: const_cast(ptr))); michael@0: return old_value; michael@0: } michael@0: michael@0: inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr, michael@0: Atomic64 increment) { michael@0: return OSAtomicAdd64(increment, const_cast(ptr)); michael@0: } michael@0: michael@0: inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr, michael@0: Atomic64 increment) { michael@0: return OSAtomicAdd64Barrier(increment, const_cast(ptr)); 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: Atomic64 prev_value; michael@0: do { michael@0: if (OSAtomicCompareAndSwap64Barrier(old_value, new_value, michael@0: const_cast(ptr))) { michael@0: return old_value; michael@0: } michael@0: prev_value = *ptr; michael@0: } while (prev_value == old_value); michael@0: return prev_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: // The lib kern interface does not distinguish between michael@0: // Acquire and Release memory barriers; they are equivalent. michael@0: return Acquire_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: *ptr = value; michael@0: MemoryBarrier(); michael@0: } michael@0: michael@0: inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) { michael@0: MemoryBarrier(); michael@0: *ptr = value; 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: MemoryBarrier(); 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(__LP64__) michael@0: michael@0: // MacOS uses long for intptr_t, AtomicWord and Atomic32 are always different michael@0: // on the Mac, even when they are the same size. We need to explicitly cast michael@0: // from AtomicWord to Atomic32/64 to implement the AtomicWord interface. michael@0: #ifdef __LP64__ michael@0: #define AtomicWordCastType Atomic64 michael@0: #else michael@0: #define AtomicWordCastType Atomic32 michael@0: #endif michael@0: michael@0: inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr, michael@0: AtomicWord old_value, michael@0: AtomicWord new_value) { michael@0: return NoBarrier_CompareAndSwap( michael@0: reinterpret_cast(ptr), michael@0: old_value, new_value); michael@0: } michael@0: michael@0: inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr, michael@0: AtomicWord new_value) { michael@0: return NoBarrier_AtomicExchange( michael@0: reinterpret_cast(ptr), new_value); michael@0: } michael@0: michael@0: inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr, michael@0: AtomicWord increment) { michael@0: return NoBarrier_AtomicIncrement( michael@0: reinterpret_cast(ptr), increment); michael@0: } michael@0: michael@0: inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr, michael@0: AtomicWord increment) { michael@0: return Barrier_AtomicIncrement( michael@0: reinterpret_cast(ptr), increment); michael@0: } michael@0: michael@0: inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr, michael@0: AtomicWord old_value, michael@0: AtomicWord new_value) { michael@0: return base::subtle::Acquire_CompareAndSwap( michael@0: reinterpret_cast(ptr), michael@0: old_value, new_value); michael@0: } michael@0: michael@0: inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr, michael@0: AtomicWord old_value, michael@0: AtomicWord new_value) { michael@0: return base::subtle::Release_CompareAndSwap( michael@0: reinterpret_cast(ptr), michael@0: old_value, new_value); michael@0: } michael@0: michael@0: inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) { michael@0: NoBarrier_Store( michael@0: reinterpret_cast(ptr), value); michael@0: } michael@0: michael@0: inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) { michael@0: return base::subtle::Acquire_Store( michael@0: reinterpret_cast(ptr), value); michael@0: } michael@0: michael@0: inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) { michael@0: return base::subtle::Release_Store( michael@0: reinterpret_cast(ptr), value); michael@0: } michael@0: michael@0: inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) { michael@0: return NoBarrier_Load( michael@0: reinterpret_cast(ptr)); michael@0: } michael@0: michael@0: inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) { michael@0: return base::subtle::Acquire_Load( michael@0: reinterpret_cast(ptr)); michael@0: } michael@0: michael@0: inline AtomicWord Release_Load(volatile const AtomicWord* ptr) { michael@0: return base::subtle::Release_Load( michael@0: reinterpret_cast(ptr)); michael@0: } michael@0: michael@0: #undef AtomicWordCastType michael@0: michael@0: } // namespace base::subtle michael@0: } // namespace base michael@0: michael@0: #endif // BASE_ATOMICOPS_INTERNALS_X86_MACOSX_H_