129 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			129 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- sanitizer_atomic_test.cc ------------------------------------------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| #include "sanitizer_common/sanitizer_atomic.h"
 | |
| #include "gtest/gtest.h"
 | |
| 
 | |
| namespace __sanitizer {
 | |
| 
 | |
| template<typename T>
 | |
| struct ValAndMagic {
 | |
|   typename T::Type magic0;
 | |
|   T a;
 | |
|   typename T::Type magic1;
 | |
| 
 | |
|   static ValAndMagic<T> *sink;
 | |
| };
 | |
| 
 | |
| template<typename T>
 | |
| ValAndMagic<T> *ValAndMagic<T>::sink;
 | |
| 
 | |
| template<typename T, memory_order load_mo, memory_order store_mo>
 | |
| void CheckStoreLoad() {
 | |
|   typedef typename T::Type Type;
 | |
|   ValAndMagic<T> val;
 | |
|   // Prevent the compiler from scalarizing the struct.
 | |
|   ValAndMagic<T>::sink = &val;
 | |
|   // Ensure that surrounding memory is not overwritten.
 | |
|   val.magic0 = val.magic1 = (Type)-3;
 | |
|   for (u64 i = 0; i < 100; i++) {
 | |
|     // Generate a value that occupies all bytes of the variable.
 | |
|     u64 v = i;
 | |
|     v |= v << 8;
 | |
|     v |= v << 16;
 | |
|     v |= v << 32;
 | |
|     val.a.val_dont_use = (Type)v;
 | |
|     EXPECT_EQ(atomic_load(&val.a, load_mo), (Type)v);
 | |
|     val.a.val_dont_use = (Type)-1;
 | |
|     atomic_store(&val.a, (Type)v, store_mo);
 | |
|     EXPECT_EQ(val.a.val_dont_use, (Type)v);
 | |
|   }
 | |
|   EXPECT_EQ(val.magic0, (Type)-3);
 | |
|   EXPECT_EQ(val.magic1, (Type)-3);
 | |
| }
 | |
| 
 | |
| TEST(SanitizerCommon, AtomicStoreLoad) {
 | |
|   CheckStoreLoad<atomic_uint8_t, memory_order_relaxed, memory_order_relaxed>();
 | |
|   CheckStoreLoad<atomic_uint8_t, memory_order_consume, memory_order_relaxed>();
 | |
|   CheckStoreLoad<atomic_uint8_t, memory_order_acquire, memory_order_relaxed>();
 | |
|   CheckStoreLoad<atomic_uint8_t, memory_order_relaxed, memory_order_release>();
 | |
|   CheckStoreLoad<atomic_uint8_t, memory_order_seq_cst, memory_order_seq_cst>();
 | |
| 
 | |
|   CheckStoreLoad<atomic_uint16_t, memory_order_relaxed, memory_order_relaxed>();
 | |
|   CheckStoreLoad<atomic_uint16_t, memory_order_consume, memory_order_relaxed>();
 | |
|   CheckStoreLoad<atomic_uint16_t, memory_order_acquire, memory_order_relaxed>();
 | |
|   CheckStoreLoad<atomic_uint16_t, memory_order_relaxed, memory_order_release>();
 | |
|   CheckStoreLoad<atomic_uint16_t, memory_order_seq_cst, memory_order_seq_cst>();
 | |
| 
 | |
|   CheckStoreLoad<atomic_uint32_t, memory_order_relaxed, memory_order_relaxed>();
 | |
|   CheckStoreLoad<atomic_uint32_t, memory_order_consume, memory_order_relaxed>();
 | |
|   CheckStoreLoad<atomic_uint32_t, memory_order_acquire, memory_order_relaxed>();
 | |
|   CheckStoreLoad<atomic_uint32_t, memory_order_relaxed, memory_order_release>();
 | |
|   CheckStoreLoad<atomic_uint32_t, memory_order_seq_cst, memory_order_seq_cst>();
 | |
| 
 | |
|   CheckStoreLoad<atomic_uint64_t, memory_order_relaxed, memory_order_relaxed>();
 | |
|   CheckStoreLoad<atomic_uint64_t, memory_order_consume, memory_order_relaxed>();
 | |
|   CheckStoreLoad<atomic_uint64_t, memory_order_acquire, memory_order_relaxed>();
 | |
|   CheckStoreLoad<atomic_uint64_t, memory_order_relaxed, memory_order_release>();
 | |
|   CheckStoreLoad<atomic_uint64_t, memory_order_seq_cst, memory_order_seq_cst>();
 | |
| 
 | |
|   CheckStoreLoad<atomic_uintptr_t, memory_order_relaxed, memory_order_relaxed>
 | |
|       ();
 | |
|   CheckStoreLoad<atomic_uintptr_t, memory_order_consume, memory_order_relaxed>
 | |
|       ();
 | |
|   CheckStoreLoad<atomic_uintptr_t, memory_order_acquire, memory_order_relaxed>
 | |
|       ();
 | |
|   CheckStoreLoad<atomic_uintptr_t, memory_order_relaxed, memory_order_release>
 | |
|       ();
 | |
|   CheckStoreLoad<atomic_uintptr_t, memory_order_seq_cst, memory_order_seq_cst>
 | |
|       ();
 | |
| }
 | |
| 
 | |
| // Clang crashes while compiling this test for Android:
 | |
| // http://llvm.org/bugs/show_bug.cgi?id=15587
 | |
| #if !SANITIZER_ANDROID
 | |
| template<typename T>
 | |
| void CheckAtomicCompareExchange() {
 | |
|   typedef typename T::Type Type;
 | |
|   {
 | |
|     Type old_val = 42;
 | |
|     Type new_val = 24;
 | |
|     Type var = old_val;
 | |
|     EXPECT_TRUE(atomic_compare_exchange_strong((T*)&var, &old_val, new_val,
 | |
|                                                memory_order_relaxed));
 | |
|     EXPECT_FALSE(atomic_compare_exchange_strong((T*)&var, &old_val, new_val,
 | |
|                                                 memory_order_relaxed));
 | |
|     EXPECT_EQ(new_val, old_val);
 | |
|   }
 | |
|   {
 | |
|     Type old_val = 42;
 | |
|     Type new_val = 24;
 | |
|     Type var = old_val;
 | |
|     EXPECT_TRUE(atomic_compare_exchange_weak((T*)&var, &old_val, new_val,
 | |
|                                              memory_order_relaxed));
 | |
|     EXPECT_FALSE(atomic_compare_exchange_weak((T*)&var, &old_val, new_val,
 | |
|                                               memory_order_relaxed));
 | |
|     EXPECT_EQ(new_val, old_val);
 | |
|   }
 | |
| }
 | |
| 
 | |
| TEST(SanitizerCommon, AtomicCompareExchangeTest) {
 | |
|   CheckAtomicCompareExchange<atomic_uint8_t>();
 | |
|   CheckAtomicCompareExchange<atomic_uint16_t>();
 | |
|   CheckAtomicCompareExchange<atomic_uint32_t>();
 | |
|   CheckAtomicCompareExchange<atomic_uint64_t>();
 | |
|   CheckAtomicCompareExchange<atomic_uintptr_t>();
 | |
| }
 | |
| #endif  //!SANITIZER_ANDROID
 | |
| 
 | |
| }  // namespace __sanitizer
 |