Path: blob/main/contrib/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_atomic_msvc.h
35233 views
//===-- sanitizer_atomic_msvc.h ---------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file is a part of ThreadSanitizer/AddressSanitizer runtime.9// Not intended for direct inclusion. Include sanitizer_atomic.h.10//11//===----------------------------------------------------------------------===//1213#ifndef SANITIZER_ATOMIC_MSVC_H14#define SANITIZER_ATOMIC_MSVC_H1516extern "C" void _ReadWriteBarrier();17#pragma intrinsic(_ReadWriteBarrier)18extern "C" void _mm_mfence();19#pragma intrinsic(_mm_mfence)20extern "C" void _mm_pause();21#pragma intrinsic(_mm_pause)22extern "C" char _InterlockedExchange8(char volatile *Addend, char Value);23#pragma intrinsic(_InterlockedExchange8)24extern "C" short _InterlockedExchange16(short volatile *Addend, short Value);25#pragma intrinsic(_InterlockedExchange16)26extern "C" long _InterlockedExchange(long volatile *Addend, long Value);27#pragma intrinsic(_InterlockedExchange)28extern "C" long _InterlockedExchangeAdd(long volatile *Addend, long Value);29#pragma intrinsic(_InterlockedExchangeAdd)30extern "C" char _InterlockedCompareExchange8(char volatile *Destination,31char Exchange, char Comparand);32#pragma intrinsic(_InterlockedCompareExchange8)33extern "C" short _InterlockedCompareExchange16(short volatile *Destination,34short Exchange, short Comparand);35#pragma intrinsic(_InterlockedCompareExchange16)36extern "C" long long _InterlockedCompareExchange64(37long long volatile *Destination, long long Exchange, long long Comparand);38#pragma intrinsic(_InterlockedCompareExchange64)39extern "C" void *_InterlockedCompareExchangePointer(40void *volatile *Destination,41void *Exchange, void *Comparand);42#pragma intrinsic(_InterlockedCompareExchangePointer)43extern "C" long __cdecl _InterlockedCompareExchange(long volatile *Destination,44long Exchange,45long Comparand);46#pragma intrinsic(_InterlockedCompareExchange)4748#ifdef _WIN6449extern "C" long long _InterlockedExchangeAdd64(long long volatile *Addend,50long long Value);51#pragma intrinsic(_InterlockedExchangeAdd64)52#endif5354namespace __sanitizer {5556inline void atomic_signal_fence(memory_order) {57_ReadWriteBarrier();58}5960inline void atomic_thread_fence(memory_order) {61_mm_mfence();62}6364inline void proc_yield(int cnt) {65for (int i = 0; i < cnt; i++)66_mm_pause();67}6869template<typename T>70inline typename T::Type atomic_load(71const volatile T *a, memory_order mo) {72DCHECK(mo == memory_order_relaxed || mo == memory_order_consume ||73mo == memory_order_acquire || mo == memory_order_seq_cst);74DCHECK(!((uptr)a % sizeof(*a)));75typename T::Type v;76// FIXME(dvyukov): 64-bit load is not atomic on 32-bits.77if (mo == memory_order_relaxed) {78v = a->val_dont_use;79} else {80atomic_signal_fence(memory_order_seq_cst);81v = a->val_dont_use;82atomic_signal_fence(memory_order_seq_cst);83}84return v;85}8687template<typename T>88inline void atomic_store(volatile T *a, typename T::Type v, memory_order mo) {89DCHECK(mo == memory_order_relaxed || mo == memory_order_release ||90mo == memory_order_seq_cst);91DCHECK(!((uptr)a % sizeof(*a)));92// FIXME(dvyukov): 64-bit store is not atomic on 32-bits.93if (mo == memory_order_relaxed) {94a->val_dont_use = v;95} else {96atomic_signal_fence(memory_order_seq_cst);97a->val_dont_use = v;98atomic_signal_fence(memory_order_seq_cst);99}100if (mo == memory_order_seq_cst)101atomic_thread_fence(memory_order_seq_cst);102}103104inline u32 atomic_fetch_add(volatile atomic_uint32_t *a,105u32 v, memory_order mo) {106(void)mo;107DCHECK(!((uptr)a % sizeof(*a)));108return (u32)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,109(long)v);110}111112inline uptr atomic_fetch_add(volatile atomic_uintptr_t *a,113uptr v, memory_order mo) {114(void)mo;115DCHECK(!((uptr)a % sizeof(*a)));116#ifdef _WIN64117return (uptr)_InterlockedExchangeAdd64((volatile long long *)&a->val_dont_use,118(long long)v);119#else120return (uptr)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,121(long)v);122#endif123}124125inline u32 atomic_fetch_sub(volatile atomic_uint32_t *a,126u32 v, memory_order mo) {127(void)mo;128DCHECK(!((uptr)a % sizeof(*a)));129return (u32)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,130-(long)v);131}132133inline uptr atomic_fetch_sub(volatile atomic_uintptr_t *a,134uptr v, memory_order mo) {135(void)mo;136DCHECK(!((uptr)a % sizeof(*a)));137#ifdef _WIN64138return (uptr)_InterlockedExchangeAdd64((volatile long long *)&a->val_dont_use,139-(long long)v);140#else141return (uptr)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,142-(long)v);143#endif144}145146inline u8 atomic_exchange(volatile atomic_uint8_t *a,147u8 v, memory_order mo) {148(void)mo;149DCHECK(!((uptr)a % sizeof(*a)));150return (u8)_InterlockedExchange8((volatile char*)&a->val_dont_use, v);151}152153inline u16 atomic_exchange(volatile atomic_uint16_t *a,154u16 v, memory_order mo) {155(void)mo;156DCHECK(!((uptr)a % sizeof(*a)));157return (u16)_InterlockedExchange16((volatile short*)&a->val_dont_use, v);158}159160inline u32 atomic_exchange(volatile atomic_uint32_t *a,161u32 v, memory_order mo) {162(void)mo;163DCHECK(!((uptr)a % sizeof(*a)));164return (u32)_InterlockedExchange((volatile long*)&a->val_dont_use, v);165}166167inline bool atomic_compare_exchange_strong(volatile atomic_uint8_t *a,168u8 *cmp,169u8 xchgv,170memory_order mo) {171(void)mo;172DCHECK(!((uptr)a % sizeof(*a)));173u8 cmpv = *cmp;174#ifdef _WIN64175u8 prev = (u8)_InterlockedCompareExchange8(176(volatile char*)&a->val_dont_use, (char)xchgv, (char)cmpv);177#else178u8 prev;179__asm {180mov al, cmpv181mov ecx, a182mov dl, xchgv183lock cmpxchg [ecx], dl184mov prev, al185}186#endif187if (prev == cmpv)188return true;189*cmp = prev;190return false;191}192193inline bool atomic_compare_exchange_strong(volatile atomic_uintptr_t *a,194uptr *cmp,195uptr xchg,196memory_order mo) {197uptr cmpv = *cmp;198uptr prev = (uptr)_InterlockedCompareExchangePointer(199(void*volatile*)&a->val_dont_use, (void*)xchg, (void*)cmpv);200if (prev == cmpv)201return true;202*cmp = prev;203return false;204}205206inline bool atomic_compare_exchange_strong(volatile atomic_uint16_t *a,207u16 *cmp,208u16 xchg,209memory_order mo) {210u16 cmpv = *cmp;211u16 prev = (u16)_InterlockedCompareExchange16(212(volatile short*)&a->val_dont_use, (short)xchg, (short)cmpv);213if (prev == cmpv)214return true;215*cmp = prev;216return false;217}218219inline bool atomic_compare_exchange_strong(volatile atomic_uint32_t *a,220u32 *cmp,221u32 xchg,222memory_order mo) {223u32 cmpv = *cmp;224u32 prev = (u32)_InterlockedCompareExchange(225(volatile long*)&a->val_dont_use, (long)xchg, (long)cmpv);226if (prev == cmpv)227return true;228*cmp = prev;229return false;230}231232inline bool atomic_compare_exchange_strong(volatile atomic_uint64_t *a,233u64 *cmp,234u64 xchg,235memory_order mo) {236u64 cmpv = *cmp;237u64 prev = (u64)_InterlockedCompareExchange64(238(volatile long long*)&a->val_dont_use, (long long)xchg, (long long)cmpv);239if (prev == cmpv)240return true;241*cmp = prev;242return false;243}244245template<typename T>246inline bool atomic_compare_exchange_weak(volatile T *a,247typename T::Type *cmp,248typename T::Type xchg,249memory_order mo) {250return atomic_compare_exchange_strong(a, cmp, xchg, mo);251}252253} // namespace __sanitizer254255#endif // SANITIZER_ATOMIC_CLANG_H256257258