atomicops_internals_portable.h revision b8cf94937c52feb53b55c39e3f82094d27de464c
1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2014 The Chromium Authors. All rights reserved.
2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be
3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file.
4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This file is an internal atomic implementation, use atomicops.h instead.
6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//
7b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This implementation uses C++11 atomics' member functions. The code base is
8b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// currently written assuming atomicity revolves around accesses instead of
9b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// C++11's memory locations. The burden is on the programmer to ensure that all
10b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// memory locations accessed atomically are never accessed non-atomically (tsan
11b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// should help with this).
12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//
13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// TODO(jfb) Modify the atomicops.h API and user code to declare atomic
14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//           locations as truly atomic. See the static_assert below.
15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//
16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Of note in this implementation:
17b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//  * All NoBarrier variants are implemented as relaxed.
18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//  * All Barrier variants are implemented as sequentially-consistent.
19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//  * Compare exchange's failure ordering is always the same as the success one
20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//    (except for release, which fails as relaxed): using a weaker ordering is
21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//    only valid under certain uses of compare exchange.
22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//  * Acquire store doesn't exist in the C11 memory model, it is instead
23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//    implemented as a relaxed store followed by a sequentially consistent
24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//    fence.
25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//  * Release load doesn't exist in the C11 memory model, it is instead
26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//    implemented as sequentially consistent fence followed by a relaxed load.
27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//  * Atomic increment is expected to return the post-incremented value, whereas
28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//    C11 fetch add returns the previous value. The implementation therefore
29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//    needs to increment twice (which the compiler should be able to detect and
30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//    optimize).
31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#ifndef BASE_ATOMICOPS_INTERNALS_PORTABLE_H_
33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#define BASE_ATOMICOPS_INTERNALS_PORTABLE_H_
34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <atomic>
36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
37b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base {
38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace subtle {
39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This implementation is transitional and maintains the original API for
41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// atomicops.h. This requires casting memory locations to the atomic types, and
42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// assumes that the API and the C++11 implementation are layout-compatible,
43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// which isn't true for all implementations or hardware platforms. The static
44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// assertion should detect this issue, were it to fire then this header
45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// shouldn't be used.
46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//
47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// TODO(jfb) If this header manages to stay committed then the API should be
48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//           modified, and all call sites updated.
49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erattypedef volatile std::atomic<Atomic32>* AtomicLocation32;
50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstatic_assert(sizeof(*(AtomicLocation32) nullptr) == sizeof(Atomic32),
51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat              "incompatible 32-bit atomic layout");
52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline void MemoryBarrier() {
54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(__GLIBCXX__)
55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Work around libstdc++ bug 51038 where atomic_thread_fence was declared but
56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // not defined, leading to the linker complaining about undefined references.
57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  __atomic_thread_fence(std::memory_order_seq_cst);
58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#else
59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  std::atomic_thread_fence(std::memory_order_seq_cst);
60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif
61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                         Atomic32 old_value,
65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                         Atomic32 new_value) {
66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation32)ptr)
67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      ->compare_exchange_strong(old_value,
68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                new_value,
69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_relaxed,
70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_relaxed);
71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return old_value;
72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                         Atomic32 new_value) {
76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return ((AtomicLocation32)ptr)
77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      ->exchange(new_value, std::memory_order_relaxed);
78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                          Atomic32 increment) {
82b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return increment +
83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat         ((AtomicLocation32)ptr)
84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat             ->fetch_add(increment, std::memory_order_relaxed);
85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                        Atomic32 increment) {
89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return increment + ((AtomicLocation32)ptr)->fetch_add(increment);
90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
91b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                       Atomic32 old_value,
94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                       Atomic32 new_value) {
95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation32)ptr)
96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      ->compare_exchange_strong(old_value,
97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                new_value,
98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_acquire,
99b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_acquire);
100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return old_value;
101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                       Atomic32 old_value,
105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                       Atomic32 new_value) {
106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation32)ptr)
107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      ->compare_exchange_strong(old_value,
108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                new_value,
109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_release,
110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_relaxed);
111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return old_value;
112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed);
116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
117b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed);
120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  MemoryBarrier();
121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation32)ptr)->store(value, std::memory_order_release);
125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
126b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
127b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
128b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed);
129b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
130b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
131b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return ((AtomicLocation32)ptr)->load(std::memory_order_acquire);
133b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic32 Release_Load(volatile const Atomic32* ptr) {
136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  MemoryBarrier();
137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed);
138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(ARCH_CPU_64_BITS)
141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erattypedef volatile std::atomic<Atomic64>* AtomicLocation64;
143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstatic_assert(sizeof(*(AtomicLocation64) nullptr) == sizeof(Atomic64),
144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat              "incompatible 64-bit atomic layout");
145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                         Atomic64 old_value,
148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                         Atomic64 new_value) {
149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation64)ptr)
150b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      ->compare_exchange_strong(old_value,
151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                new_value,
152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_relaxed,
153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_relaxed);
154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return old_value;
155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                         Atomic64 new_value) {
159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return ((AtomicLocation64)ptr)
160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      ->exchange(new_value, std::memory_order_relaxed);
161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
162b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                          Atomic64 increment) {
165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return increment +
166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat         ((AtomicLocation64)ptr)
167b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat             ->fetch_add(increment, std::memory_order_relaxed);
168b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
169b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
170b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
171b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                        Atomic64 increment) {
172b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return increment + ((AtomicLocation64)ptr)->fetch_add(increment);
173b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
174b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
175b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
176b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                       Atomic64 old_value,
177b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                       Atomic64 new_value) {
178b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation64)ptr)
179b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      ->compare_exchange_strong(old_value,
180b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                new_value,
181b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_acquire,
182b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_acquire);
183b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return old_value;
184b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
185b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
186b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
187b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                       Atomic64 old_value,
188b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                       Atomic64 new_value) {
189b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation64)ptr)
190b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      ->compare_exchange_strong(old_value,
191b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                new_value,
192b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_release,
193b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_relaxed);
194b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return old_value;
195b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
196b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
197b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
198b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed);
199b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
200b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
201b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
202b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed);
203b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  MemoryBarrier();
204b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
205b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
206b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
207b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation64)ptr)->store(value, std::memory_order_release);
208b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
209b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
210b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
211b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed);
212b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
213b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
214b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
215b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return ((AtomicLocation64)ptr)->load(std::memory_order_acquire);
216b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
217b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
218b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic64 Release_Load(volatile const Atomic64* ptr) {
219b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  MemoryBarrier();
220b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed);
221b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
222b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
223b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif  // defined(ARCH_CPU_64_BITS)
224b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace subtle
225b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace base
226b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
227b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif  // BASE_ATOMICOPS_INTERNALS_PORTABLE_H_
228