1 //===-- atomic_test.cpp -----------------------------------------*- 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "tests/scudo_unit_test.h" 10 11 #include "atomic_helpers.h" 12 13 namespace scudo { 14 15 template <typename T> struct ValAndMagic { 16 typename T::Type Magic0; 17 T A; 18 typename T::Type Magic1; 19 20 static ValAndMagic<T> *Sink; 21 }; 22 23 template <typename T> ValAndMagic<T> *ValAndMagic<T>::Sink; 24 25 template <typename T, memory_order LoadMO, memory_order StoreMO> 26 void checkStoreLoad() { 27 typedef typename T::Type Type; 28 ValAndMagic<T> Val; 29 // Prevent the compiler from scalarizing the struct. 30 ValAndMagic<T>::Sink = &Val; 31 // Ensure that surrounding memory is not overwritten. 32 Val.Magic0 = Val.Magic1 = (Type)-3; 33 for (u64 I = 0; I < 100; I++) { 34 // Generate A value that occupies all bytes of the variable. 35 u64 V = I; 36 V |= V << 8; 37 V |= V << 16; 38 V |= V << 32; 39 Val.A.ValDoNotUse = (Type)V; 40 EXPECT_EQ(atomic_load(&Val.A, LoadMO), (Type)V); 41 Val.A.ValDoNotUse = (Type)-1; 42 atomic_store(&Val.A, (Type)V, StoreMO); 43 EXPECT_EQ(Val.A.ValDoNotUse, (Type)V); 44 } 45 EXPECT_EQ(Val.Magic0, (Type)-3); 46 EXPECT_EQ(Val.Magic1, (Type)-3); 47 } 48 49 TEST(ScudoAtomicTest, AtomicStoreLoad) { 50 checkStoreLoad<atomic_u8, memory_order_relaxed, memory_order_relaxed>(); 51 checkStoreLoad<atomic_u8, memory_order_consume, memory_order_relaxed>(); 52 checkStoreLoad<atomic_u8, memory_order_acquire, memory_order_relaxed>(); 53 checkStoreLoad<atomic_u8, memory_order_relaxed, memory_order_release>(); 54 checkStoreLoad<atomic_u8, memory_order_seq_cst, memory_order_seq_cst>(); 55 56 checkStoreLoad<atomic_u16, memory_order_relaxed, memory_order_relaxed>(); 57 checkStoreLoad<atomic_u16, memory_order_consume, memory_order_relaxed>(); 58 checkStoreLoad<atomic_u16, memory_order_acquire, memory_order_relaxed>(); 59 checkStoreLoad<atomic_u16, memory_order_relaxed, memory_order_release>(); 60 checkStoreLoad<atomic_u16, memory_order_seq_cst, memory_order_seq_cst>(); 61 62 checkStoreLoad<atomic_u32, memory_order_relaxed, memory_order_relaxed>(); 63 checkStoreLoad<atomic_u32, memory_order_consume, memory_order_relaxed>(); 64 checkStoreLoad<atomic_u32, memory_order_acquire, memory_order_relaxed>(); 65 checkStoreLoad<atomic_u32, memory_order_relaxed, memory_order_release>(); 66 checkStoreLoad<atomic_u32, memory_order_seq_cst, memory_order_seq_cst>(); 67 68 checkStoreLoad<atomic_u64, memory_order_relaxed, memory_order_relaxed>(); 69 checkStoreLoad<atomic_u64, memory_order_consume, memory_order_relaxed>(); 70 checkStoreLoad<atomic_u64, memory_order_acquire, memory_order_relaxed>(); 71 checkStoreLoad<atomic_u64, memory_order_relaxed, memory_order_release>(); 72 checkStoreLoad<atomic_u64, memory_order_seq_cst, memory_order_seq_cst>(); 73 74 checkStoreLoad<atomic_uptr, memory_order_relaxed, memory_order_relaxed>(); 75 checkStoreLoad<atomic_uptr, memory_order_consume, memory_order_relaxed>(); 76 checkStoreLoad<atomic_uptr, memory_order_acquire, memory_order_relaxed>(); 77 checkStoreLoad<atomic_uptr, memory_order_relaxed, memory_order_release>(); 78 checkStoreLoad<atomic_uptr, memory_order_seq_cst, memory_order_seq_cst>(); 79 } 80 81 template <typename T> void checkAtomicCompareExchange() { 82 typedef typename T::Type Type; 83 Type OldVal = 42; 84 Type NewVal = 24; 85 Type V = OldVal; 86 EXPECT_TRUE(atomic_compare_exchange_strong(reinterpret_cast<T *>(&V), &OldVal, 87 NewVal, memory_order_relaxed)); 88 EXPECT_FALSE(atomic_compare_exchange_strong( 89 reinterpret_cast<T *>(&V), &OldVal, NewVal, memory_order_relaxed)); 90 EXPECT_EQ(NewVal, OldVal); 91 } 92 93 TEST(ScudoAtomicTest, AtomicCompareExchangeTest) { 94 checkAtomicCompareExchange<atomic_u8>(); 95 checkAtomicCompareExchange<atomic_u16>(); 96 checkAtomicCompareExchange<atomic_u32>(); 97 checkAtomicCompareExchange<atomic_u64>(); 98 checkAtomicCompareExchange<atomic_uptr>(); 99 } 100 101 } // namespace scudo 102