148 lines · cpp
1//===-- sanitizer_atomic_test.cpp -----------------------------------------===//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// This file is a part of ThreadSanitizer/AddressSanitizer runtime.10//11//===----------------------------------------------------------------------===//12#include "sanitizer_common/sanitizer_atomic.h"13#include "gtest/gtest.h"14 15#ifndef __has_extension16#define __has_extension(x) 017#endif18 19#ifndef ATOMIC_LLONG_LOCK_FREE20# if __has_extension(c_atomic) || __has_extension(cxx_atomic)21# define ATOMIC_LLONG_LOCK_FREE __CLANG_ATOMIC_LLONG_LOCK_FREE22# elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)23# define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE24# else25# error Unsupported compiler.26# endif27#endif28 29namespace __sanitizer {30 31template<typename T>32struct ValAndMagic {33 typename T::Type magic0;34 T a;35 typename T::Type magic1;36 37 static ValAndMagic<T> *sink;38};39 40template<typename T>41ValAndMagic<T> *ValAndMagic<T>::sink;42 43template<typename T, memory_order load_mo, memory_order store_mo>44void CheckStoreLoad() {45 typedef typename T::Type Type;46 ValAndMagic<T> val;47 // Prevent the compiler from scalarizing the struct.48 ValAndMagic<T>::sink = &val;49 // Ensure that surrounding memory is not overwritten.50 val.magic0 = val.magic1 = (Type)-3;51 for (u64 i = 0; i < 100; i++) {52 // Generate a value that occupies all bytes of the variable.53 u64 v = i;54 v |= v << 8;55 v |= v << 16;56 v |= v << 32;57 val.a.val_dont_use = (Type)v;58 EXPECT_EQ(atomic_load(&val.a, load_mo), (Type)v);59 val.a.val_dont_use = (Type)-1;60 atomic_store(&val.a, (Type)v, store_mo);61 EXPECT_EQ(val.a.val_dont_use, (Type)v);62 }63 EXPECT_EQ(val.magic0, (Type)-3);64 EXPECT_EQ(val.magic1, (Type)-3);65}66 67TEST(SanitizerCommon, AtomicStoreLoad) {68 CheckStoreLoad<atomic_uint8_t, memory_order_relaxed, memory_order_relaxed>();69 CheckStoreLoad<atomic_uint8_t, memory_order_consume, memory_order_relaxed>();70 CheckStoreLoad<atomic_uint8_t, memory_order_acquire, memory_order_relaxed>();71 CheckStoreLoad<atomic_uint8_t, memory_order_relaxed, memory_order_release>();72 CheckStoreLoad<atomic_uint8_t, memory_order_seq_cst, memory_order_seq_cst>();73 74 CheckStoreLoad<atomic_uint16_t, memory_order_relaxed, memory_order_relaxed>();75 CheckStoreLoad<atomic_uint16_t, memory_order_consume, memory_order_relaxed>();76 CheckStoreLoad<atomic_uint16_t, memory_order_acquire, memory_order_relaxed>();77 CheckStoreLoad<atomic_uint16_t, memory_order_relaxed, memory_order_release>();78 CheckStoreLoad<atomic_uint16_t, memory_order_seq_cst, memory_order_seq_cst>();79 80 CheckStoreLoad<atomic_uint32_t, memory_order_relaxed, memory_order_relaxed>();81 CheckStoreLoad<atomic_uint32_t, memory_order_consume, memory_order_relaxed>();82 CheckStoreLoad<atomic_uint32_t, memory_order_acquire, memory_order_relaxed>();83 CheckStoreLoad<atomic_uint32_t, memory_order_relaxed, memory_order_release>();84 CheckStoreLoad<atomic_uint32_t, memory_order_seq_cst, memory_order_seq_cst>();85 86 // Avoid fallbacking to software emulated compiler atomics, that are usually87 // provided by libatomic, which is not always present.88#if ATOMIC_LLONG_LOCK_FREE == 289 CheckStoreLoad<atomic_uint64_t, memory_order_relaxed, memory_order_relaxed>();90 CheckStoreLoad<atomic_uint64_t, memory_order_consume, memory_order_relaxed>();91 CheckStoreLoad<atomic_uint64_t, memory_order_acquire, memory_order_relaxed>();92 CheckStoreLoad<atomic_uint64_t, memory_order_relaxed, memory_order_release>();93 CheckStoreLoad<atomic_uint64_t, memory_order_seq_cst, memory_order_seq_cst>();94#endif95 96 CheckStoreLoad<atomic_uintptr_t, memory_order_relaxed, memory_order_relaxed>97 ();98 CheckStoreLoad<atomic_uintptr_t, memory_order_consume, memory_order_relaxed>99 ();100 CheckStoreLoad<atomic_uintptr_t, memory_order_acquire, memory_order_relaxed>101 ();102 CheckStoreLoad<atomic_uintptr_t, memory_order_relaxed, memory_order_release>103 ();104 CheckStoreLoad<atomic_uintptr_t, memory_order_seq_cst, memory_order_seq_cst>105 ();106}107 108// Clang crashes while compiling this test for Android:109// http://llvm.org/bugs/show_bug.cgi?id=15587110#if !SANITIZER_ANDROID111template<typename T>112void CheckAtomicCompareExchange() {113 typedef typename T::Type Type;114 {115 Type old_val = 42;116 Type new_val = 24;117 Type var = old_val;118 EXPECT_TRUE(atomic_compare_exchange_strong((T*)&var, &old_val, new_val,119 memory_order_relaxed));120 EXPECT_FALSE(atomic_compare_exchange_strong((T*)&var, &old_val, new_val,121 memory_order_relaxed));122 EXPECT_EQ(new_val, old_val);123 }124 {125 Type old_val = 42;126 Type new_val = 24;127 Type var = old_val;128 EXPECT_TRUE(atomic_compare_exchange_weak((T*)&var, &old_val, new_val,129 memory_order_relaxed));130 EXPECT_FALSE(atomic_compare_exchange_weak((T*)&var, &old_val, new_val,131 memory_order_relaxed));132 EXPECT_EQ(new_val, old_val);133 }134}135 136TEST(SanitizerCommon, AtomicCompareExchangeTest) {137 CheckAtomicCompareExchange<atomic_uint8_t>();138 CheckAtomicCompareExchange<atomic_uint16_t>();139 CheckAtomicCompareExchange<atomic_uint32_t>();140#if ATOMIC_LLONG_LOCK_FREE == 2141 CheckAtomicCompareExchange<atomic_uint64_t>();142#endif143 CheckAtomicCompareExchange<atomic_uintptr_t>();144}145#endif //!SANITIZER_ANDROID146 147} // namespace __sanitizer148