[go: nahoru, domu]

blob: 47a10e65e7ac708fc679213f266e0110a694104a [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2012 The Chromium Authors
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
deanm@google.com611dbe02008-08-05 09:57:364
Benoit Lize79cf0592023-01-27 10:01:575// IMPORTANT NOTE: deprecated. Use std::atomic instead.
6//
7// Rationale:
8// - Uniformity: most of the code uses std::atomic, and the underlying
9// implementation is the same. Use the STL one.
10// - Clearer code: return values from some operations (e.g. CompareAndSwap)
11// differ from the equivalent ones in std::atomic, leading to confusion.
12// - Richer semantics: can use actual types, rather than e.g. Atomic32 for a
13// boolean flag, or AtomicWord for T*. Bitwise operations (e.g. fetch_or())
14// are only in std::atomic.
15// - Harder to misuse: base::subtle::Atomic32 is just an int, making it possible
16// to accidentally manipulate, not realizing that there are no atomic
17// semantics attached to it. For instance, "Atomic32 a; a++;" is almost
18// certainly incorrect.
19
deanm@google.com611dbe02008-08-05 09:57:3620// For atomic operations on reference counts, see atomic_refcount.h.
21// For atomic operations on sequence numbers, see atomic_sequence_num.h.
22
23// The routines exported by this module are subtle. If you use them, even if
24// you get the code right, it will depend on careful reasoning about atomicity
25// and memory ordering; it will be less readable, and harder to maintain. If
26// you plan to use these routines, you should have a good reason, such as solid
27// evidence that performance would otherwise suffer, or there being no
28// alternative. You should assume only properties explicitly guaranteed by the
29// specifications in this file. You are almost certainly _not_ writing code
30// just for the x86; if you assume x86 semantics, x86 hardware bugs and
31// implementations on other archtectures will cause your code to break. If you
32// do not know what you are doing, avoid these routines, and use a Mutex.
33//
34// It is incorrect to make direct assignments to/from an atomic variable.
35// You should use one of the Load or Store routines. The NoBarrier
36// versions are provided when no barriers are needed:
37// NoBarrier_Store()
38// NoBarrier_Load()
39// Although there are currently no compiler enforcement, you are encouraged
40// to use these.
41//
42
43#ifndef BASE_ATOMICOPS_H_
44#define BASE_ATOMICOPS_H_
45
ctruta@blackberry.com92677102014-02-08 04:59:5546#include <stdint.h>
47
thestig29356662015-01-21 11:06:0248// Small C++ header which defines implementation specific macros used to
49// identify the STL implementation.
50// - libc++: captures __config for _LIBCPP_VERSION
51// - libstdc++: captures bits/c++config.h for __GLIBCXX__
52#include <cstddef>
53
jhawkins@chromium.org2edc2862011-04-04 18:04:3754#include "build/build_config.h"
deanm@google.com611dbe02008-08-05 09:57:3655
56namespace base {
57namespace subtle {
58
ctruta@blackberry.com92677102014-02-08 04:59:5559typedef int32_t Atomic32;
deanm@chromium.org616f9a12009-07-27 21:17:2360#ifdef ARCH_CPU_64_BITS
61// We need to be able to go between Atomic64 and AtomicWord implicitly. This
62// means Atomic64 and AtomicWord should be the same type on 64-bit.
Xiaohan Wang38e4ebb2022-01-19 06:57:4363#if defined(__ILP32__) || BUILDFLAG(IS_NACL)
abarth@chromium.orgbd254b42010-12-01 07:34:5864// NaCl's intptr_t is not actually 64-bits on 64-bit!
65// http://code.google.com/p/nativeclient/issues/detail?id=1162
66typedef int64_t Atomic64;
67#else
deanm@chromium.org616f9a12009-07-27 21:17:2368typedef intptr_t Atomic64;
deanm@google.com611dbe02008-08-05 09:57:3669#endif
abarth@chromium.orgbd254b42010-12-01 07:34:5870#endif
deanm@google.com611dbe02008-08-05 09:57:3671
72// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or
73// Atomic64 routines below, depending on your architecture.
74typedef intptr_t AtomicWord;
75
76// Atomically execute:
77// result = *ptr;
78// if (*ptr == old_value)
79// *ptr = new_value;
80// return result;
81//
82// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
83// Always return the old value of "*ptr"
84//
85// This routine implies no memory barriers.
86Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
87 Atomic32 old_value,
88 Atomic32 new_value);
89
90// Atomically store new_value into *ptr, returning the previous value held in
91// *ptr. This routine implies no memory barriers.
92Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value);
93
94// Atomically increment *ptr by "increment". Returns the new value of
95// *ptr with the increment applied. This routine implies no memory barriers.
96Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment);
97
98Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
99 Atomic32 increment);
100
101// These following lower-level operations are typically useful only to people
102// implementing higher-level synchronization operations like spinlocks,
103// mutexes, and condition-variables. They combine CompareAndSwap(), a load, or
104// a store with appropriate memory-ordering instructions. "Acquire" operations
105// ensure that no later memory access can be reordered ahead of the operation.
106// "Release" operations ensure that no previous memory access can be reordered
107// after the operation. "Barrier" operations have both "Acquire" and "Release"
Tomasz Moniuszkobdbaaf42019-05-07 08:19:44108// semantics.
deanm@google.com611dbe02008-08-05 09:57:36109Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
110 Atomic32 old_value,
111 Atomic32 new_value);
112Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
113 Atomic32 old_value,
114 Atomic32 new_value);
115
deanm@google.com611dbe02008-08-05 09:57:36116void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value);
deanm@google.com611dbe02008-08-05 09:57:36117void Release_Store(volatile Atomic32* ptr, Atomic32 value);
118
119Atomic32 NoBarrier_Load(volatile const Atomic32* ptr);
120Atomic32 Acquire_Load(volatile const Atomic32* ptr);
deanm@google.com611dbe02008-08-05 09:57:36121
122// 64-bit atomic operations (only available on 64-bit processors).
deanm@chromium.org616f9a12009-07-27 21:17:23123#ifdef ARCH_CPU_64_BITS
deanm@google.com611dbe02008-08-05 09:57:36124Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
125 Atomic64 old_value,
126 Atomic64 new_value);
127Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value);
128Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
129Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
130
131Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
132 Atomic64 old_value,
133 Atomic64 new_value);
134Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
135 Atomic64 old_value,
136 Atomic64 new_value);
deanm@google.com611dbe02008-08-05 09:57:36137void Release_Store(volatile Atomic64* ptr, Atomic64 value);
138Atomic64 NoBarrier_Load(volatile const Atomic64* ptr);
139Atomic64 Acquire_Load(volatile const Atomic64* ptr);
deanm@chromium.org616f9a12009-07-27 21:17:23140#endif // ARCH_CPU_64_BITS
deanm@google.com611dbe02008-08-05 09:57:36141
byungwook.ahn@gmail.comabe936a32014-04-13 17:36:27142} // namespace subtle
deanm@google.com611dbe02008-08-05 09:57:36143} // namespace base
144
Benoit Lize163598d2021-04-01 16:46:59145#include "base/atomicops_internals_portable.h"
jfb57a4e4a2014-10-14 15:06:05146
phajdan.jr@chromium.org0c6f3b0c2011-04-15 06:15:04147// On some platforms we need additional declarations to make
148// AtomicWord compatible with our other Atomic* types.
Xiaohan Wang38e4ebb2022-01-19 06:57:43149#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_OPENBSD)
phajdan.jr@chromium.org0c6f3b0c2011-04-15 06:15:04150#include "base/atomicops_internals_atomicword_compat.h"
151#endif
152
deanm@google.com611dbe02008-08-05 09:57:36153#endif // BASE_ATOMICOPS_H_