xref: /aosp_15_r20/external/libchrome/base/atomicops_internals_x86_msvc.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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