1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/base/atomicops_internals_mutex.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,252 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * vim: sw=2 ts=8 et : 1.6 + */ 1.7 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.10 + 1.11 +// This file is an internal atomic implementation, use 1.12 +// base/atomicops.h instead. 1.13 +// 1.14 +// This is a very slow fallback implementation of atomic operations 1.15 +// that uses a mutex instead of atomic instructions. 1.16 +// 1.17 +// (NB: a small "optimization" here would be using a spinlock instead 1.18 +// of a blocking mutex, but it's probably not worth the time.) 1.19 + 1.20 +#ifndef base_atomicops_internals_mutex_h 1.21 +#define base_atomicops_internals_mutex_h 1.22 + 1.23 +#include "base/lock.h" 1.24 + 1.25 +namespace base { 1.26 +namespace subtle { 1.27 + 1.28 +extern Lock gAtomicsMutex; 1.29 + 1.30 +template<typename T> 1.31 +T Locked_CAS(volatile T* ptr, T old_value, T new_value) { 1.32 + AutoLock _(gAtomicsMutex); 1.33 + 1.34 + T current_value = *ptr; 1.35 + if (current_value == old_value) 1.36 + *ptr = new_value; 1.37 + 1.38 + return current_value; 1.39 +} 1.40 + 1.41 +template<typename T> 1.42 +T Locked_AtomicExchange(volatile T* ptr, T new_value) { 1.43 + AutoLock _(gAtomicsMutex); 1.44 + 1.45 + T current_value = *ptr; 1.46 + *ptr = new_value; 1.47 + return current_value; 1.48 +} 1.49 + 1.50 +template<typename T> 1.51 +T Locked_AtomicIncrement(volatile T* ptr, T increment) { 1.52 + AutoLock _(gAtomicsMutex); 1.53 + return *ptr += increment; 1.54 +} 1.55 + 1.56 +template<typename T> 1.57 +void Locked_Store(volatile T* ptr, T value) { 1.58 + AutoLock _(gAtomicsMutex); 1.59 + *ptr = value; 1.60 +} 1.61 + 1.62 +template<typename T> 1.63 +T Locked_Load(volatile const T* ptr) { 1.64 + AutoLock _(gAtomicsMutex); 1.65 + return *ptr; 1.66 +} 1.67 + 1.68 +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, 1.69 + Atomic32 old_value, 1.70 + Atomic32 new_value) { 1.71 + return Locked_CAS(ptr, old_value, new_value); 1.72 +} 1.73 + 1.74 +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, 1.75 + Atomic32 new_value) { 1.76 + return Locked_AtomicExchange(ptr, new_value); 1.77 +} 1.78 + 1.79 +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, 1.80 + Atomic32 increment) { 1.81 + return Locked_AtomicIncrement(ptr, increment); 1.82 +} 1.83 + 1.84 +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, 1.85 + Atomic32 increment) { 1.86 + return Locked_AtomicIncrement(ptr, increment); 1.87 +} 1.88 + 1.89 +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, 1.90 + Atomic32 old_value, 1.91 + Atomic32 new_value) { 1.92 + return Locked_CAS(ptr, old_value, new_value); 1.93 +} 1.94 + 1.95 +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, 1.96 + Atomic32 old_value, 1.97 + Atomic32 new_value) { 1.98 + return Locked_CAS(ptr, old_value, new_value); 1.99 +} 1.100 + 1.101 +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { 1.102 + return Locked_Store(ptr, value); 1.103 +} 1.104 + 1.105 +inline void MemoryBarrier() { 1.106 + AutoLock _(gAtomicsMutex); 1.107 + // lock/unlock work as a barrier here 1.108 +} 1.109 + 1.110 +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { 1.111 + return Locked_Store(ptr, value); 1.112 +} 1.113 + 1.114 +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { 1.115 + return Locked_Store(ptr, value); 1.116 +} 1.117 + 1.118 +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { 1.119 + return Locked_Load(ptr); 1.120 +} 1.121 + 1.122 +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { 1.123 + return NoBarrier_Load(ptr); 1.124 +} 1.125 + 1.126 +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { 1.127 + return Locked_Load(ptr); 1.128 +} 1.129 + 1.130 +#ifdef ARCH_CPU_64_BITS 1.131 + 1.132 +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, 1.133 + Atomic64 old_value, 1.134 + Atomic64 new_value) { 1.135 + return Locked_CAS(ptr, old_value, new_value); 1.136 +} 1.137 + 1.138 +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, 1.139 + Atomic64 new_value) { 1.140 + return Locked_AtomicExchange(ptr, new_value); 1.141 +} 1.142 + 1.143 +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, 1.144 + Atomic64 increment) { 1.145 + return Locked_AtomicIncrement(ptr, increment); 1.146 +} 1.147 + 1.148 +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, 1.149 + Atomic64 increment) { 1.150 + return Locked_AtomicIncrement(ptr, increment); 1.151 +} 1.152 + 1.153 +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { 1.154 + return Locked_Store(ptr, value); 1.155 +} 1.156 + 1.157 +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, 1.158 + Atomic64 old_value, 1.159 + Atomic64 new_value) { 1.160 + return Locked_CAS(ptr, old_value, new_value); 1.161 +} 1.162 + 1.163 +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { 1.164 + return Locked_Store(ptr, value); 1.165 +} 1.166 + 1.167 +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { 1.168 + return Locked_Store(ptr, value); 1.169 +} 1.170 + 1.171 +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { 1.172 + return Locked_Load(ptr); 1.173 +} 1.174 + 1.175 +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { 1.176 + return Locked_Load(ptr); 1.177 +} 1.178 + 1.179 +inline Atomic64 Release_Load(volatile const Atomic64* ptr) { 1.180 + return Locked_Load(ptr); 1.181 +} 1.182 + 1.183 +#endif // ARCH_CPU_64_BITS 1.184 + 1.185 +#ifdef OS_MACOSX 1.186 +// From atomicops_internals_x86_macosx.h: 1.187 +// 1.188 +// MacOS uses long for intptr_t, AtomicWord and Atomic32 are always 1.189 +// different on the Mac, even when they are the same size. We need 1.190 +// to explicitly cast from AtomicWord to Atomic32/64 to implement 1.191 +// the AtomicWord interface. 1.192 + 1.193 +inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr, 1.194 + AtomicWord old_value, 1.195 + AtomicWord new_value) { 1.196 + return Locked_CAS(ptr, old_value, new_value); 1.197 +} 1.198 + 1.199 +inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr, 1.200 + AtomicWord new_value) { 1.201 + return Locked_AtomicExchange(ptr, new_value); 1.202 +} 1.203 + 1.204 +inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr, 1.205 + AtomicWord increment) { 1.206 + return Locked_AtomicIncrement(ptr, increment); 1.207 +} 1.208 + 1.209 +inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr, 1.210 + AtomicWord increment) { 1.211 + return Locked_AtomicIncrement(ptr, increment); 1.212 +} 1.213 + 1.214 +inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr, 1.215 + AtomicWord old_value, 1.216 + AtomicWord new_value) { 1.217 + return Locked_CAS(ptr, old_value, new_value); 1.218 +} 1.219 + 1.220 +inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr, 1.221 + AtomicWord old_value, 1.222 + AtomicWord new_value) { 1.223 + return Locked_CAS(ptr, old_value, new_value); 1.224 +} 1.225 + 1.226 +inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) { 1.227 + return Locked_Store(ptr, value); 1.228 +} 1.229 + 1.230 +inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) { 1.231 + return Locked_Store(ptr, value); 1.232 +} 1.233 + 1.234 +inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) { 1.235 + return Locked_Store(ptr, value); 1.236 +} 1.237 + 1.238 +inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) { 1.239 + return Locked_Load(ptr); 1.240 +} 1.241 + 1.242 +inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) { 1.243 + return Locked_Load(ptr); 1.244 +} 1.245 + 1.246 +inline AtomicWord Release_Load(volatile const AtomicWord* ptr) { 1.247 + return Locked_Load(ptr); 1.248 +} 1.249 + 1.250 +#endif // OS_MACOSX 1.251 + 1.252 +} // namespace subtle 1.253 +} // namespace base 1.254 + 1.255 +#endif // base_atomicops_internals_mutex_h