brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.6 KiB · a3e309f Raw
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