1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// This file is an internal atomic implementation, use base/atomicops.h instead. 6 7#ifndef BASE_ATOMICOPS_INTERNALS_MAC_H_ 8#define BASE_ATOMICOPS_INTERNALS_MAC_H_ 9 10#include <libkern/OSAtomic.h> 11 12namespace base { 13namespace subtle { 14 15inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, 16 Atomic32 old_value, 17 Atomic32 new_value) { 18 Atomic32 prev_value; 19 do { 20 if (OSAtomicCompareAndSwap32(old_value, new_value, 21 const_cast<Atomic32*>(ptr))) { 22 return old_value; 23 } 24 prev_value = *ptr; 25 } while (prev_value == old_value); 26 return prev_value; 27} 28 29inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, 30 Atomic32 new_value) { 31 Atomic32 old_value; 32 do { 33 old_value = *ptr; 34 } while (!OSAtomicCompareAndSwap32(old_value, new_value, 35 const_cast<Atomic32*>(ptr))); 36 return old_value; 37} 38 39inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, 40 Atomic32 increment) { 41 return OSAtomicAdd32(increment, const_cast<Atomic32*>(ptr)); 42} 43 44inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, 45 Atomic32 increment) { 46 return OSAtomicAdd32Barrier(increment, const_cast<Atomic32*>(ptr)); 47} 48 49inline void MemoryBarrier() { 50 OSMemoryBarrier(); 51} 52 53inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, 54 Atomic32 old_value, 55 Atomic32 new_value) { 56 Atomic32 prev_value; 57 do { 58 if (OSAtomicCompareAndSwap32Barrier(old_value, new_value, 59 const_cast<Atomic32*>(ptr))) { 60 return old_value; 61 } 62 prev_value = *ptr; 63 } while (prev_value == old_value); 64 return prev_value; 65} 66 67inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, 68 Atomic32 old_value, 69 Atomic32 new_value) { 70 return Acquire_CompareAndSwap(ptr, old_value, new_value); 71} 72 73inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { 74 *ptr = value; 75} 76 77inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { 78 *ptr = value; 79 MemoryBarrier(); 80} 81 82inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { 83 MemoryBarrier(); 84 *ptr = value; 85} 86 87inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { 88 return *ptr; 89} 90 91inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { 92 Atomic32 value = *ptr; 93 MemoryBarrier(); 94 return value; 95} 96 97inline Atomic32 Release_Load(volatile const Atomic32* ptr) { 98 MemoryBarrier(); 99 return *ptr; 100} 101 102#ifdef __LP64__ 103 104// 64-bit implementation on 64-bit platform 105 106inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, 107 Atomic64 old_value, 108 Atomic64 new_value) { 109 Atomic64 prev_value; 110 do { 111 if (OSAtomicCompareAndSwap64(old_value, new_value, 112 reinterpret_cast<volatile int64_t*>(ptr))) { 113 return old_value; 114 } 115 prev_value = *ptr; 116 } while (prev_value == old_value); 117 return prev_value; 118} 119 120inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, 121 Atomic64 new_value) { 122 Atomic64 old_value; 123 do { 124 old_value = *ptr; 125 } while (!OSAtomicCompareAndSwap64(old_value, new_value, 126 reinterpret_cast<volatile int64_t*>(ptr))); 127 return old_value; 128} 129 130inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, 131 Atomic64 increment) { 132 return OSAtomicAdd64(increment, reinterpret_cast<volatile int64_t*>(ptr)); 133} 134 135inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, 136 Atomic64 increment) { 137 return OSAtomicAdd64Barrier(increment, 138 reinterpret_cast<volatile int64_t*>(ptr)); 139} 140 141inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, 142 Atomic64 old_value, 143 Atomic64 new_value) { 144 Atomic64 prev_value; 145 do { 146 if (OSAtomicCompareAndSwap64Barrier( 147 old_value, new_value, reinterpret_cast<volatile int64_t*>(ptr))) { 148 return old_value; 149 } 150 prev_value = *ptr; 151 } while (prev_value == old_value); 152 return prev_value; 153} 154 155inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, 156 Atomic64 old_value, 157 Atomic64 new_value) { 158 // The lib kern interface does not distinguish between 159 // Acquire and Release memory barriers; they are equivalent. 160 return Acquire_CompareAndSwap(ptr, old_value, new_value); 161} 162 163inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { 164 *ptr = value; 165} 166 167inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { 168 *ptr = value; 169 MemoryBarrier(); 170} 171 172inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { 173 MemoryBarrier(); 174 *ptr = value; 175} 176 177inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { 178 return *ptr; 179} 180 181inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { 182 Atomic64 value = *ptr; 183 MemoryBarrier(); 184 return value; 185} 186 187inline Atomic64 Release_Load(volatile const Atomic64* ptr) { 188 MemoryBarrier(); 189 return *ptr; 190} 191 192#endif // defined(__LP64__) 193 194} // namespace base::subtle 195} // namespace base 196 197#endif // BASE_ATOMICOPS_INTERNALS_MAC_H_ 198