atomicops_internals_x86_msvc.h revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2006-2008 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_X86_MSVC_H_
8#define BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
9#pragma once
10
11#include <windows.h>
12
13namespace base {
14namespace subtle {
15
16inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
17                                         Atomic32 old_value,
18                                         Atomic32 new_value) {
19  LONG result = InterlockedCompareExchange(
20      reinterpret_cast<volatile LONG*>(ptr),
21      static_cast<LONG>(new_value),
22      static_cast<LONG>(old_value));
23  return static_cast<Atomic32>(result);
24}
25
26inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
27                                         Atomic32 new_value) {
28  LONG result = InterlockedExchange(
29      reinterpret_cast<volatile LONG*>(ptr),
30      static_cast<LONG>(new_value));
31  return static_cast<Atomic32>(result);
32}
33
34inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
35                                        Atomic32 increment) {
36  return InterlockedExchangeAdd(
37      reinterpret_cast<volatile LONG*>(ptr),
38      static_cast<LONG>(increment)) + increment;
39}
40
41inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
42                                          Atomic32 increment) {
43  return Barrier_AtomicIncrement(ptr, increment);
44}
45
46#if !(defined(_MSC_VER) && _MSC_VER >= 1400)
47#error "We require at least vs2005 for MemoryBarrier"
48#endif
49inline void MemoryBarrier() {
50  // We use MemoryBarrier from WinNT.h
51  ::MemoryBarrier();
52}
53
54inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
55                                       Atomic32 old_value,
56                                       Atomic32 new_value) {
57  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
58}
59
60inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
61                                       Atomic32 old_value,
62                                       Atomic32 new_value) {
63  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
64}
65
66inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
67  *ptr = value;
68}
69
70inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
71  NoBarrier_AtomicExchange(ptr, value);
72              // acts as a barrier in this implementation
73}
74
75inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
76  *ptr = value; // works w/o barrier for current Intel chips as of June 2005
77  // See comments in Atomic64 version of Release_Store() below.
78}
79
80inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
81  return *ptr;
82}
83
84inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
85  Atomic32 value = *ptr;
86  return value;
87}
88
89inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
90  MemoryBarrier();
91  return *ptr;
92}
93
94#if defined(_WIN64)
95
96// 64-bit low-level operations on 64-bit platform.
97
98COMPILE_ASSERT(sizeof(Atomic64) == sizeof(PVOID), atomic_word_is_atomic);
99
100inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
101                                         Atomic64 old_value,
102                                         Atomic64 new_value) {
103  PVOID result = InterlockedCompareExchangePointer(
104    reinterpret_cast<volatile PVOID*>(ptr),
105    reinterpret_cast<PVOID>(new_value), reinterpret_cast<PVOID>(old_value));
106  return reinterpret_cast<Atomic64>(result);
107}
108
109inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
110                                         Atomic64 new_value) {
111  PVOID result = InterlockedExchangePointer(
112    reinterpret_cast<volatile PVOID*>(ptr),
113    reinterpret_cast<PVOID>(new_value));
114  return reinterpret_cast<Atomic64>(result);
115}
116
117inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
118                                        Atomic64 increment) {
119  return InterlockedExchangeAdd64(
120      reinterpret_cast<volatile LONGLONG*>(ptr),
121      static_cast<LONGLONG>(increment)) + increment;
122}
123
124inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
125                                          Atomic64 increment) {
126  return Barrier_AtomicIncrement(ptr, increment);
127}
128
129inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
130  *ptr = value;
131}
132
133inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
134  NoBarrier_AtomicExchange(ptr, value);
135              // acts as a barrier in this implementation
136}
137
138inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
139  *ptr = value; // works w/o barrier for current Intel chips as of June 2005
140
141  // When new chips come out, check:
142  //  IA-32 Intel Architecture Software Developer's Manual, Volume 3:
143  //  System Programming Guide, Chatper 7: Multiple-processor management,
144  //  Section 7.2, Memory Ordering.
145  // Last seen at:
146  //   http://developer.intel.com/design/pentium4/manuals/index_new.htm
147}
148
149inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
150  return *ptr;
151}
152
153inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
154  Atomic64 value = *ptr;
155  return value;
156}
157
158inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
159  MemoryBarrier();
160  return *ptr;
161}
162
163inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
164                                       Atomic64 old_value,
165                                       Atomic64 new_value) {
166  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
167}
168
169inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
170                                       Atomic64 old_value,
171                                       Atomic64 new_value) {
172  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
173}
174
175
176#endif  // defined(_WIN64)
177
178}  // namespace base::subtle
179}  // namespace base
180
181#endif  // BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
182