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