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
37cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include "build/build_config.h"
38cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko
39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base {
40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace subtle {
41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This implementation is transitional and maintains the original API for
43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// atomicops.h. This requires casting memory locations to the atomic types, and
44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// assumes that the API and the C++11 implementation are layout-compatible,
45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// which isn't true for all implementations or hardware platforms. The static
46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// assertion should detect this issue, were it to fire then this header
47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// shouldn't be used.
48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//
49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// TODO(jfb) If this header manages to stay committed then the API should be
50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//           modified, and all call sites updated.
51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erattypedef volatile std::atomic<Atomic32>* AtomicLocation32;
52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstatic_assert(sizeof(*(AtomicLocation32) nullptr) == sizeof(Atomic32),
53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat              "incompatible 32-bit atomic layout");
54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline void MemoryBarrier() {
56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(__GLIBCXX__)
57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Work around libstdc++ bug 51038 where atomic_thread_fence was declared but
58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // not defined, leading to the linker complaining about undefined references.
59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  __atomic_thread_fence(std::memory_order_seq_cst);
60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#else
61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  std::atomic_thread_fence(std::memory_order_seq_cst);
62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif
63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                         Atomic32 old_value,
67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                         Atomic32 new_value) {
68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation32)ptr)
69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      ->compare_exchange_strong(old_value,
70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                new_value,
71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_relaxed,
72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_relaxed);
73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return old_value;
74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                         Atomic32 new_value) {
78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return ((AtomicLocation32)ptr)
79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      ->exchange(new_value, std::memory_order_relaxed);
80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
82b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                          Atomic32 increment) {
84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return increment +
85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat         ((AtomicLocation32)ptr)
86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat             ->fetch_add(increment, std::memory_order_relaxed);
87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                        Atomic32 increment) {
91b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return increment + ((AtomicLocation32)ptr)->fetch_add(increment);
92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                       Atomic32 old_value,
96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                       Atomic32 new_value) {
97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation32)ptr)
98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      ->compare_exchange_strong(old_value,
99b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                new_value,
100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_acquire,
101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_acquire);
102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return old_value;
103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                       Atomic32 old_value,
107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                       Atomic32 new_value) {
108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation32)ptr)
109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      ->compare_exchange_strong(old_value,
110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                new_value,
111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_release,
112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_relaxed);
113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return old_value;
114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
117b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed);
118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed);
122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  MemoryBarrier();
123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
126b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation32)ptr)->store(value, std::memory_order_release);
127b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
128b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
129b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
130b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed);
131b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
133b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return ((AtomicLocation32)ptr)->load(std::memory_order_acquire);
135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic32 Release_Load(volatile const Atomic32* ptr) {
138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  MemoryBarrier();
139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed);
140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(ARCH_CPU_64_BITS)
143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erattypedef volatile std::atomic<Atomic64>* AtomicLocation64;
145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstatic_assert(sizeof(*(AtomicLocation64) nullptr) == sizeof(Atomic64),
146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat              "incompatible 64-bit atomic layout");
147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                         Atomic64 old_value,
150b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                         Atomic64 new_value) {
151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation64)ptr)
152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      ->compare_exchange_strong(old_value,
153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                new_value,
154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_relaxed,
155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_relaxed);
156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return old_value;
157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                         Atomic64 new_value) {
161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return ((AtomicLocation64)ptr)
162b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      ->exchange(new_value, std::memory_order_relaxed);
163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                          Atomic64 increment) {
167b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return increment +
168b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat         ((AtomicLocation64)ptr)
169b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat             ->fetch_add(increment, std::memory_order_relaxed);
170b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
171b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
172b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
173b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                        Atomic64 increment) {
174b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return increment + ((AtomicLocation64)ptr)->fetch_add(increment);
175b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
176b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
177b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
178b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                       Atomic64 old_value,
179b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                       Atomic64 new_value) {
180b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation64)ptr)
181b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      ->compare_exchange_strong(old_value,
182b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                new_value,
183b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_acquire,
184b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_acquire);
185b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return old_value;
186b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
187b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
188b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
189b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                       Atomic64 old_value,
190b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                       Atomic64 new_value) {
191b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation64)ptr)
192b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      ->compare_exchange_strong(old_value,
193b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                new_value,
194b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_release,
195b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                std::memory_order_relaxed);
196b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return old_value;
197b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
198b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
199b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
200b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed);
201b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
202b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
203b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
204b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed);
205b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  MemoryBarrier();
206b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
207b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
208b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
209b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ((AtomicLocation64)ptr)->store(value, std::memory_order_release);
210b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
211b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
212b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
213b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed);
214b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
215b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
216b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
217b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return ((AtomicLocation64)ptr)->load(std::memory_order_acquire);
218b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
219b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
220b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratinline Atomic64 Release_Load(volatile const Atomic64* ptr) {
221b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  MemoryBarrier();
222b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed);
223b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
224b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
225b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif  // defined(ARCH_CPU_64_BITS)
226b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace subtle
227b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace base
228b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
229b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif  // BASE_ATOMICOPS_INTERNALS_PORTABLE_H_
230