1*76559068SAndroid Build Coastguard Worker //===-- atomic_helpers.h ----------------------------------------*- C++ -*-===//
2*76559068SAndroid Build Coastguard Worker //
3*76559068SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*76559068SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information.
5*76559068SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*76559068SAndroid Build Coastguard Worker //
7*76559068SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
8*76559068SAndroid Build Coastguard Worker
9*76559068SAndroid Build Coastguard Worker #ifndef SCUDO_ATOMIC_H_
10*76559068SAndroid Build Coastguard Worker #define SCUDO_ATOMIC_H_
11*76559068SAndroid Build Coastguard Worker
12*76559068SAndroid Build Coastguard Worker #include "internal_defs.h"
13*76559068SAndroid Build Coastguard Worker
14*76559068SAndroid Build Coastguard Worker namespace scudo {
15*76559068SAndroid Build Coastguard Worker
16*76559068SAndroid Build Coastguard Worker enum memory_order {
17*76559068SAndroid Build Coastguard Worker memory_order_relaxed = 0,
18*76559068SAndroid Build Coastguard Worker memory_order_consume = 1,
19*76559068SAndroid Build Coastguard Worker memory_order_acquire = 2,
20*76559068SAndroid Build Coastguard Worker memory_order_release = 3,
21*76559068SAndroid Build Coastguard Worker memory_order_acq_rel = 4,
22*76559068SAndroid Build Coastguard Worker memory_order_seq_cst = 5
23*76559068SAndroid Build Coastguard Worker };
24*76559068SAndroid Build Coastguard Worker static_assert(memory_order_relaxed == __ATOMIC_RELAXED, "");
25*76559068SAndroid Build Coastguard Worker static_assert(memory_order_consume == __ATOMIC_CONSUME, "");
26*76559068SAndroid Build Coastguard Worker static_assert(memory_order_acquire == __ATOMIC_ACQUIRE, "");
27*76559068SAndroid Build Coastguard Worker static_assert(memory_order_release == __ATOMIC_RELEASE, "");
28*76559068SAndroid Build Coastguard Worker static_assert(memory_order_acq_rel == __ATOMIC_ACQ_REL, "");
29*76559068SAndroid Build Coastguard Worker static_assert(memory_order_seq_cst == __ATOMIC_SEQ_CST, "");
30*76559068SAndroid Build Coastguard Worker
31*76559068SAndroid Build Coastguard Worker struct atomic_u8 {
32*76559068SAndroid Build Coastguard Worker typedef u8 Type;
33*76559068SAndroid Build Coastguard Worker volatile Type ValDoNotUse;
34*76559068SAndroid Build Coastguard Worker };
35*76559068SAndroid Build Coastguard Worker
36*76559068SAndroid Build Coastguard Worker struct atomic_u16 {
37*76559068SAndroid Build Coastguard Worker typedef u16 Type;
38*76559068SAndroid Build Coastguard Worker volatile Type ValDoNotUse;
39*76559068SAndroid Build Coastguard Worker };
40*76559068SAndroid Build Coastguard Worker
41*76559068SAndroid Build Coastguard Worker struct atomic_s32 {
42*76559068SAndroid Build Coastguard Worker typedef s32 Type;
43*76559068SAndroid Build Coastguard Worker volatile Type ValDoNotUse;
44*76559068SAndroid Build Coastguard Worker };
45*76559068SAndroid Build Coastguard Worker
46*76559068SAndroid Build Coastguard Worker struct atomic_u32 {
47*76559068SAndroid Build Coastguard Worker typedef u32 Type;
48*76559068SAndroid Build Coastguard Worker volatile Type ValDoNotUse;
49*76559068SAndroid Build Coastguard Worker };
50*76559068SAndroid Build Coastguard Worker
51*76559068SAndroid Build Coastguard Worker struct atomic_u64 {
52*76559068SAndroid Build Coastguard Worker typedef u64 Type;
53*76559068SAndroid Build Coastguard Worker // On 32-bit platforms u64 is not necessarily aligned on 8 bytes.
54*76559068SAndroid Build Coastguard Worker alignas(8) volatile Type ValDoNotUse;
55*76559068SAndroid Build Coastguard Worker };
56*76559068SAndroid Build Coastguard Worker
57*76559068SAndroid Build Coastguard Worker struct atomic_uptr {
58*76559068SAndroid Build Coastguard Worker typedef uptr Type;
59*76559068SAndroid Build Coastguard Worker volatile Type ValDoNotUse;
60*76559068SAndroid Build Coastguard Worker };
61*76559068SAndroid Build Coastguard Worker
62*76559068SAndroid Build Coastguard Worker template <typename T>
atomic_load(const volatile T * A,memory_order MO)63*76559068SAndroid Build Coastguard Worker inline typename T::Type atomic_load(const volatile T *A, memory_order MO) {
64*76559068SAndroid Build Coastguard Worker DCHECK(!(reinterpret_cast<uptr>(A) % sizeof(*A)));
65*76559068SAndroid Build Coastguard Worker typename T::Type V;
66*76559068SAndroid Build Coastguard Worker __atomic_load(&A->ValDoNotUse, &V, MO);
67*76559068SAndroid Build Coastguard Worker return V;
68*76559068SAndroid Build Coastguard Worker }
69*76559068SAndroid Build Coastguard Worker
70*76559068SAndroid Build Coastguard Worker template <typename T>
atomic_store(volatile T * A,typename T::Type V,memory_order MO)71*76559068SAndroid Build Coastguard Worker inline void atomic_store(volatile T *A, typename T::Type V, memory_order MO) {
72*76559068SAndroid Build Coastguard Worker DCHECK(!(reinterpret_cast<uptr>(A) % sizeof(*A)));
73*76559068SAndroid Build Coastguard Worker __atomic_store(&A->ValDoNotUse, &V, MO);
74*76559068SAndroid Build Coastguard Worker }
75*76559068SAndroid Build Coastguard Worker
atomic_thread_fence(memory_order)76*76559068SAndroid Build Coastguard Worker inline void atomic_thread_fence(memory_order) { __sync_synchronize(); }
77*76559068SAndroid Build Coastguard Worker
78*76559068SAndroid Build Coastguard Worker template <typename T>
atomic_fetch_add(volatile T * A,typename T::Type V,memory_order MO)79*76559068SAndroid Build Coastguard Worker inline typename T::Type atomic_fetch_add(volatile T *A, typename T::Type V,
80*76559068SAndroid Build Coastguard Worker memory_order MO) {
81*76559068SAndroid Build Coastguard Worker DCHECK(!(reinterpret_cast<uptr>(A) % sizeof(*A)));
82*76559068SAndroid Build Coastguard Worker return __atomic_fetch_add(&A->ValDoNotUse, V, MO);
83*76559068SAndroid Build Coastguard Worker }
84*76559068SAndroid Build Coastguard Worker
85*76559068SAndroid Build Coastguard Worker template <typename T>
atomic_fetch_sub(volatile T * A,typename T::Type V,memory_order MO)86*76559068SAndroid Build Coastguard Worker inline typename T::Type atomic_fetch_sub(volatile T *A, typename T::Type V,
87*76559068SAndroid Build Coastguard Worker memory_order MO) {
88*76559068SAndroid Build Coastguard Worker DCHECK(!(reinterpret_cast<uptr>(A) % sizeof(*A)));
89*76559068SAndroid Build Coastguard Worker return __atomic_fetch_sub(&A->ValDoNotUse, V, MO);
90*76559068SAndroid Build Coastguard Worker }
91*76559068SAndroid Build Coastguard Worker
92*76559068SAndroid Build Coastguard Worker template <typename T>
atomic_fetch_and(volatile T * A,typename T::Type V,memory_order MO)93*76559068SAndroid Build Coastguard Worker inline typename T::Type atomic_fetch_and(volatile T *A, typename T::Type V,
94*76559068SAndroid Build Coastguard Worker memory_order MO) {
95*76559068SAndroid Build Coastguard Worker DCHECK(!(reinterpret_cast<uptr>(A) % sizeof(*A)));
96*76559068SAndroid Build Coastguard Worker return __atomic_fetch_and(&A->ValDoNotUse, V, MO);
97*76559068SAndroid Build Coastguard Worker }
98*76559068SAndroid Build Coastguard Worker
99*76559068SAndroid Build Coastguard Worker template <typename T>
atomic_fetch_or(volatile T * A,typename T::Type V,memory_order MO)100*76559068SAndroid Build Coastguard Worker inline typename T::Type atomic_fetch_or(volatile T *A, typename T::Type V,
101*76559068SAndroid Build Coastguard Worker memory_order MO) {
102*76559068SAndroid Build Coastguard Worker DCHECK(!(reinterpret_cast<uptr>(A) % sizeof(*A)));
103*76559068SAndroid Build Coastguard Worker return __atomic_fetch_or(&A->ValDoNotUse, V, MO);
104*76559068SAndroid Build Coastguard Worker }
105*76559068SAndroid Build Coastguard Worker
106*76559068SAndroid Build Coastguard Worker template <typename T>
atomic_exchange(volatile T * A,typename T::Type V,memory_order MO)107*76559068SAndroid Build Coastguard Worker inline typename T::Type atomic_exchange(volatile T *A, typename T::Type V,
108*76559068SAndroid Build Coastguard Worker memory_order MO) {
109*76559068SAndroid Build Coastguard Worker DCHECK(!(reinterpret_cast<uptr>(A) % sizeof(*A)));
110*76559068SAndroid Build Coastguard Worker typename T::Type R;
111*76559068SAndroid Build Coastguard Worker __atomic_exchange(&A->ValDoNotUse, &V, &R, MO);
112*76559068SAndroid Build Coastguard Worker return R;
113*76559068SAndroid Build Coastguard Worker }
114*76559068SAndroid Build Coastguard Worker
115*76559068SAndroid Build Coastguard Worker template <typename T>
atomic_compare_exchange_strong(volatile T * A,typename T::Type * Cmp,typename T::Type Xchg,memory_order MO)116*76559068SAndroid Build Coastguard Worker inline bool atomic_compare_exchange_strong(volatile T *A, typename T::Type *Cmp,
117*76559068SAndroid Build Coastguard Worker typename T::Type Xchg,
118*76559068SAndroid Build Coastguard Worker memory_order MO) {
119*76559068SAndroid Build Coastguard Worker return __atomic_compare_exchange(&A->ValDoNotUse, Cmp, &Xchg, false, MO,
120*76559068SAndroid Build Coastguard Worker __ATOMIC_RELAXED);
121*76559068SAndroid Build Coastguard Worker }
122*76559068SAndroid Build Coastguard Worker
123*76559068SAndroid Build Coastguard Worker // Clutter-reducing helpers.
124*76559068SAndroid Build Coastguard Worker
125*76559068SAndroid Build Coastguard Worker template <typename T>
atomic_load_relaxed(const volatile T * A)126*76559068SAndroid Build Coastguard Worker inline typename T::Type atomic_load_relaxed(const volatile T *A) {
127*76559068SAndroid Build Coastguard Worker return atomic_load(A, memory_order_relaxed);
128*76559068SAndroid Build Coastguard Worker }
129*76559068SAndroid Build Coastguard Worker
130*76559068SAndroid Build Coastguard Worker template <typename T>
atomic_store_relaxed(volatile T * A,typename T::Type V)131*76559068SAndroid Build Coastguard Worker inline void atomic_store_relaxed(volatile T *A, typename T::Type V) {
132*76559068SAndroid Build Coastguard Worker atomic_store(A, V, memory_order_relaxed);
133*76559068SAndroid Build Coastguard Worker }
134*76559068SAndroid Build Coastguard Worker
135*76559068SAndroid Build Coastguard Worker template <typename T>
136*76559068SAndroid Build Coastguard Worker inline typename T::Type
atomic_compare_exchange_strong(volatile T * A,typename T::Type Cmp,typename T::Type Xchg,memory_order MO)137*76559068SAndroid Build Coastguard Worker atomic_compare_exchange_strong(volatile T *A, typename T::Type Cmp,
138*76559068SAndroid Build Coastguard Worker typename T::Type Xchg, memory_order MO) {
139*76559068SAndroid Build Coastguard Worker atomic_compare_exchange_strong(A, &Cmp, Xchg, MO);
140*76559068SAndroid Build Coastguard Worker return Cmp;
141*76559068SAndroid Build Coastguard Worker }
142*76559068SAndroid Build Coastguard Worker
143*76559068SAndroid Build Coastguard Worker } // namespace scudo
144*76559068SAndroid Build Coastguard Worker
145*76559068SAndroid Build Coastguard Worker #endif // SCUDO_ATOMIC_H_
146