1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker // This file is an internal atomic implementation, use base/atomicops.h instead.
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #ifndef BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
8*635a8641SAndroid Build Coastguard Worker #define BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
9*635a8641SAndroid Build Coastguard Worker
10*635a8641SAndroid Build Coastguard Worker #include "base/win/windows_types.h"
11*635a8641SAndroid Build Coastguard Worker
12*635a8641SAndroid Build Coastguard Worker #include <intrin.h>
13*635a8641SAndroid Build Coastguard Worker
14*635a8641SAndroid Build Coastguard Worker #include "base/macros.h"
15*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
16*635a8641SAndroid Build Coastguard Worker
17*635a8641SAndroid Build Coastguard Worker #if defined(ARCH_CPU_64_BITS)
18*635a8641SAndroid Build Coastguard Worker // windows.h #defines this (only on x64). This causes problems because the
19*635a8641SAndroid Build Coastguard Worker // public API also uses MemoryBarrier at the public name for this fence. So, on
20*635a8641SAndroid Build Coastguard Worker // X64, undef it, and call its documented
21*635a8641SAndroid Build Coastguard Worker // (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx)
22*635a8641SAndroid Build Coastguard Worker // implementation directly.
23*635a8641SAndroid Build Coastguard Worker #undef MemoryBarrier
24*635a8641SAndroid Build Coastguard Worker #endif
25*635a8641SAndroid Build Coastguard Worker
26*635a8641SAndroid Build Coastguard Worker namespace base {
27*635a8641SAndroid Build Coastguard Worker namespace subtle {
28*635a8641SAndroid Build Coastguard Worker
NoBarrier_CompareAndSwap(volatile Atomic32 * ptr,Atomic32 old_value,Atomic32 new_value)29*635a8641SAndroid Build Coastguard Worker inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
30*635a8641SAndroid Build Coastguard Worker Atomic32 old_value,
31*635a8641SAndroid Build Coastguard Worker Atomic32 new_value) {
32*635a8641SAndroid Build Coastguard Worker LONG result = _InterlockedCompareExchange(
33*635a8641SAndroid Build Coastguard Worker reinterpret_cast<volatile LONG*>(ptr),
34*635a8641SAndroid Build Coastguard Worker static_cast<LONG>(new_value),
35*635a8641SAndroid Build Coastguard Worker static_cast<LONG>(old_value));
36*635a8641SAndroid Build Coastguard Worker return static_cast<Atomic32>(result);
37*635a8641SAndroid Build Coastguard Worker }
38*635a8641SAndroid Build Coastguard Worker
NoBarrier_AtomicExchange(volatile Atomic32 * ptr,Atomic32 new_value)39*635a8641SAndroid Build Coastguard Worker inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
40*635a8641SAndroid Build Coastguard Worker Atomic32 new_value) {
41*635a8641SAndroid Build Coastguard Worker LONG result = _InterlockedExchange(
42*635a8641SAndroid Build Coastguard Worker reinterpret_cast<volatile LONG*>(ptr),
43*635a8641SAndroid Build Coastguard Worker static_cast<LONG>(new_value));
44*635a8641SAndroid Build Coastguard Worker return static_cast<Atomic32>(result);
45*635a8641SAndroid Build Coastguard Worker }
46*635a8641SAndroid Build Coastguard Worker
Barrier_AtomicIncrement(volatile Atomic32 * ptr,Atomic32 increment)47*635a8641SAndroid Build Coastguard Worker inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
48*635a8641SAndroid Build Coastguard Worker Atomic32 increment) {
49*635a8641SAndroid Build Coastguard Worker return _InterlockedExchangeAdd(
50*635a8641SAndroid Build Coastguard Worker reinterpret_cast<volatile LONG*>(ptr),
51*635a8641SAndroid Build Coastguard Worker static_cast<LONG>(increment)) + increment;
52*635a8641SAndroid Build Coastguard Worker }
53*635a8641SAndroid Build Coastguard Worker
NoBarrier_AtomicIncrement(volatile Atomic32 * ptr,Atomic32 increment)54*635a8641SAndroid Build Coastguard Worker inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
55*635a8641SAndroid Build Coastguard Worker Atomic32 increment) {
56*635a8641SAndroid Build Coastguard Worker return Barrier_AtomicIncrement(ptr, increment);
57*635a8641SAndroid Build Coastguard Worker }
58*635a8641SAndroid Build Coastguard Worker
MemoryBarrier()59*635a8641SAndroid Build Coastguard Worker inline void MemoryBarrier() {
60*635a8641SAndroid Build Coastguard Worker #if defined(ARCH_CPU_64_BITS)
61*635a8641SAndroid Build Coastguard Worker // See #undef and note at the top of this file.
62*635a8641SAndroid Build Coastguard Worker __faststorefence();
63*635a8641SAndroid Build Coastguard Worker #else
64*635a8641SAndroid Build Coastguard Worker // We use the implementation of MemoryBarrier from WinNT.h
65*635a8641SAndroid Build Coastguard Worker LONG barrier;
66*635a8641SAndroid Build Coastguard Worker
67*635a8641SAndroid Build Coastguard Worker _InterlockedOr(&barrier, 0);
68*635a8641SAndroid Build Coastguard Worker #endif
69*635a8641SAndroid Build Coastguard Worker }
70*635a8641SAndroid Build Coastguard Worker
Acquire_CompareAndSwap(volatile Atomic32 * ptr,Atomic32 old_value,Atomic32 new_value)71*635a8641SAndroid Build Coastguard Worker inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
72*635a8641SAndroid Build Coastguard Worker Atomic32 old_value,
73*635a8641SAndroid Build Coastguard Worker Atomic32 new_value) {
74*635a8641SAndroid Build Coastguard Worker return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
75*635a8641SAndroid Build Coastguard Worker }
76*635a8641SAndroid Build Coastguard Worker
Release_CompareAndSwap(volatile Atomic32 * ptr,Atomic32 old_value,Atomic32 new_value)77*635a8641SAndroid Build Coastguard Worker inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
78*635a8641SAndroid Build Coastguard Worker Atomic32 old_value,
79*635a8641SAndroid Build Coastguard Worker Atomic32 new_value) {
80*635a8641SAndroid Build Coastguard Worker return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
81*635a8641SAndroid Build Coastguard Worker }
82*635a8641SAndroid Build Coastguard Worker
NoBarrier_Store(volatile Atomic32 * ptr,Atomic32 value)83*635a8641SAndroid Build Coastguard Worker inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
84*635a8641SAndroid Build Coastguard Worker *ptr = value;
85*635a8641SAndroid Build Coastguard Worker }
86*635a8641SAndroid Build Coastguard Worker
Acquire_Store(volatile Atomic32 * ptr,Atomic32 value)87*635a8641SAndroid Build Coastguard Worker inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
88*635a8641SAndroid Build Coastguard Worker NoBarrier_AtomicExchange(ptr, value);
89*635a8641SAndroid Build Coastguard Worker // acts as a barrier in this implementation
90*635a8641SAndroid Build Coastguard Worker }
91*635a8641SAndroid Build Coastguard Worker
Release_Store(volatile Atomic32 * ptr,Atomic32 value)92*635a8641SAndroid Build Coastguard Worker inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
93*635a8641SAndroid Build Coastguard Worker *ptr = value; // works w/o barrier for current Intel chips as of June 2005
94*635a8641SAndroid Build Coastguard Worker // See comments in Atomic64 version of Release_Store() below.
95*635a8641SAndroid Build Coastguard Worker }
96*635a8641SAndroid Build Coastguard Worker
NoBarrier_Load(volatile const Atomic32 * ptr)97*635a8641SAndroid Build Coastguard Worker inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
98*635a8641SAndroid Build Coastguard Worker return *ptr;
99*635a8641SAndroid Build Coastguard Worker }
100*635a8641SAndroid Build Coastguard Worker
Acquire_Load(volatile const Atomic32 * ptr)101*635a8641SAndroid Build Coastguard Worker inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
102*635a8641SAndroid Build Coastguard Worker Atomic32 value = *ptr;
103*635a8641SAndroid Build Coastguard Worker return value;
104*635a8641SAndroid Build Coastguard Worker }
105*635a8641SAndroid Build Coastguard Worker
Release_Load(volatile const Atomic32 * ptr)106*635a8641SAndroid Build Coastguard Worker inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
107*635a8641SAndroid Build Coastguard Worker MemoryBarrier();
108*635a8641SAndroid Build Coastguard Worker return *ptr;
109*635a8641SAndroid Build Coastguard Worker }
110*635a8641SAndroid Build Coastguard Worker
111*635a8641SAndroid Build Coastguard Worker #if defined(_WIN64)
112*635a8641SAndroid Build Coastguard Worker
113*635a8641SAndroid Build Coastguard Worker // 64-bit low-level operations on 64-bit platform.
114*635a8641SAndroid Build Coastguard Worker
115*635a8641SAndroid Build Coastguard Worker static_assert(sizeof(Atomic64) == sizeof(PVOID), "atomic word is atomic");
116*635a8641SAndroid Build Coastguard Worker
NoBarrier_CompareAndSwap(volatile Atomic64 * ptr,Atomic64 old_value,Atomic64 new_value)117*635a8641SAndroid Build Coastguard Worker inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
118*635a8641SAndroid Build Coastguard Worker Atomic64 old_value,
119*635a8641SAndroid Build Coastguard Worker Atomic64 new_value) {
120*635a8641SAndroid Build Coastguard Worker PVOID result = _InterlockedCompareExchangePointer(
121*635a8641SAndroid Build Coastguard Worker reinterpret_cast<volatile PVOID*>(ptr),
122*635a8641SAndroid Build Coastguard Worker reinterpret_cast<PVOID>(new_value), reinterpret_cast<PVOID>(old_value));
123*635a8641SAndroid Build Coastguard Worker return reinterpret_cast<Atomic64>(result);
124*635a8641SAndroid Build Coastguard Worker }
125*635a8641SAndroid Build Coastguard Worker
NoBarrier_AtomicExchange(volatile Atomic64 * ptr,Atomic64 new_value)126*635a8641SAndroid Build Coastguard Worker inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
127*635a8641SAndroid Build Coastguard Worker Atomic64 new_value) {
128*635a8641SAndroid Build Coastguard Worker PVOID result =
129*635a8641SAndroid Build Coastguard Worker _InterlockedExchangePointer(reinterpret_cast<volatile PVOID*>(ptr),
130*635a8641SAndroid Build Coastguard Worker reinterpret_cast<PVOID>(new_value));
131*635a8641SAndroid Build Coastguard Worker return reinterpret_cast<Atomic64>(result);
132*635a8641SAndroid Build Coastguard Worker }
133*635a8641SAndroid Build Coastguard Worker
Barrier_AtomicIncrement(volatile Atomic64 * ptr,Atomic64 increment)134*635a8641SAndroid Build Coastguard Worker inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
135*635a8641SAndroid Build Coastguard Worker Atomic64 increment) {
136*635a8641SAndroid Build Coastguard Worker return _InterlockedExchangeAdd64(reinterpret_cast<volatile LONGLONG*>(ptr),
137*635a8641SAndroid Build Coastguard Worker static_cast<LONGLONG>(increment)) +
138*635a8641SAndroid Build Coastguard Worker increment;
139*635a8641SAndroid Build Coastguard Worker }
140*635a8641SAndroid Build Coastguard Worker
NoBarrier_AtomicIncrement(volatile Atomic64 * ptr,Atomic64 increment)141*635a8641SAndroid Build Coastguard Worker inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
142*635a8641SAndroid Build Coastguard Worker Atomic64 increment) {
143*635a8641SAndroid Build Coastguard Worker return Barrier_AtomicIncrement(ptr, increment);
144*635a8641SAndroid Build Coastguard Worker }
145*635a8641SAndroid Build Coastguard Worker
NoBarrier_Store(volatile Atomic64 * ptr,Atomic64 value)146*635a8641SAndroid Build Coastguard Worker inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
147*635a8641SAndroid Build Coastguard Worker *ptr = value;
148*635a8641SAndroid Build Coastguard Worker }
149*635a8641SAndroid Build Coastguard Worker
Acquire_Store(volatile Atomic64 * ptr,Atomic64 value)150*635a8641SAndroid Build Coastguard Worker inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
151*635a8641SAndroid Build Coastguard Worker NoBarrier_AtomicExchange(ptr, value);
152*635a8641SAndroid Build Coastguard Worker // acts as a barrier in this implementation
153*635a8641SAndroid Build Coastguard Worker }
154*635a8641SAndroid Build Coastguard Worker
Release_Store(volatile Atomic64 * ptr,Atomic64 value)155*635a8641SAndroid Build Coastguard Worker inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
156*635a8641SAndroid Build Coastguard Worker *ptr = value; // works w/o barrier for current Intel chips as of June 2005
157*635a8641SAndroid Build Coastguard Worker
158*635a8641SAndroid Build Coastguard Worker // When new chips come out, check:
159*635a8641SAndroid Build Coastguard Worker // IA-32 Intel Architecture Software Developer's Manual, Volume 3:
160*635a8641SAndroid Build Coastguard Worker // System Programming Guide, Chatper 7: Multiple-processor management,
161*635a8641SAndroid Build Coastguard Worker // Section 7.2, Memory Ordering.
162*635a8641SAndroid Build Coastguard Worker // Last seen at:
163*635a8641SAndroid Build Coastguard Worker // http://developer.intel.com/design/pentium4/manuals/index_new.htm
164*635a8641SAndroid Build Coastguard Worker }
165*635a8641SAndroid Build Coastguard Worker
NoBarrier_Load(volatile const Atomic64 * ptr)166*635a8641SAndroid Build Coastguard Worker inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
167*635a8641SAndroid Build Coastguard Worker return *ptr;
168*635a8641SAndroid Build Coastguard Worker }
169*635a8641SAndroid Build Coastguard Worker
Acquire_Load(volatile const Atomic64 * ptr)170*635a8641SAndroid Build Coastguard Worker inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
171*635a8641SAndroid Build Coastguard Worker Atomic64 value = *ptr;
172*635a8641SAndroid Build Coastguard Worker return value;
173*635a8641SAndroid Build Coastguard Worker }
174*635a8641SAndroid Build Coastguard Worker
Release_Load(volatile const Atomic64 * ptr)175*635a8641SAndroid Build Coastguard Worker inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
176*635a8641SAndroid Build Coastguard Worker MemoryBarrier();
177*635a8641SAndroid Build Coastguard Worker return *ptr;
178*635a8641SAndroid Build Coastguard Worker }
179*635a8641SAndroid Build Coastguard Worker
Acquire_CompareAndSwap(volatile Atomic64 * ptr,Atomic64 old_value,Atomic64 new_value)180*635a8641SAndroid Build Coastguard Worker inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
181*635a8641SAndroid Build Coastguard Worker Atomic64 old_value,
182*635a8641SAndroid Build Coastguard Worker Atomic64 new_value) {
183*635a8641SAndroid Build Coastguard Worker return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
184*635a8641SAndroid Build Coastguard Worker }
185*635a8641SAndroid Build Coastguard Worker
Release_CompareAndSwap(volatile Atomic64 * ptr,Atomic64 old_value,Atomic64 new_value)186*635a8641SAndroid Build Coastguard Worker inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
187*635a8641SAndroid Build Coastguard Worker Atomic64 old_value,
188*635a8641SAndroid Build Coastguard Worker Atomic64 new_value) {
189*635a8641SAndroid Build Coastguard Worker return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
190*635a8641SAndroid Build Coastguard Worker }
191*635a8641SAndroid Build Coastguard Worker
192*635a8641SAndroid Build Coastguard Worker
193*635a8641SAndroid Build Coastguard Worker #endif // defined(_WIN64)
194*635a8641SAndroid Build Coastguard Worker
195*635a8641SAndroid Build Coastguard Worker } // namespace subtle
196*635a8641SAndroid Build Coastguard Worker } // namespace base
197*635a8641SAndroid Build Coastguard Worker
198*635a8641SAndroid Build Coastguard Worker #endif // BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
199