xref: /llvm-project/compiler-rt/lib/scudo/standalone/tests/atomic_test.cpp (revision f668a84b58dcd816656236d7ba7e820dce52e7f8)
13fa38318SNico Weber //===-- atomic_test.cpp -----------------------------------------*- C++ -*-===//
23fa38318SNico Weber //
33fa38318SNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43fa38318SNico Weber // See https://llvm.org/LICENSE.txt for license information.
53fa38318SNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63fa38318SNico Weber //
73fa38318SNico Weber //===----------------------------------------------------------------------===//
83fa38318SNico Weber 
90d3d4d3bSKostya Kortchinsky #include "tests/scudo_unit_test.h"
100d3d4d3bSKostya Kortchinsky 
110d3d4d3bSKostya Kortchinsky #include "atomic_helpers.h"
123fa38318SNico Weber 
133fa38318SNico Weber namespace scudo {
143fa38318SNico Weber 
153fa38318SNico Weber template <typename T> struct ValAndMagic {
163fa38318SNico Weber   typename T::Type Magic0;
173fa38318SNico Weber   T A;
183fa38318SNico Weber   typename T::Type Magic1;
193fa38318SNico Weber 
203fa38318SNico Weber   static ValAndMagic<T> *Sink;
213fa38318SNico Weber };
223fa38318SNico Weber 
233fa38318SNico Weber template <typename T> ValAndMagic<T> *ValAndMagic<T>::Sink;
243fa38318SNico Weber 
253fa38318SNico Weber template <typename T, memory_order LoadMO, memory_order StoreMO>
checkStoreLoad()263fa38318SNico Weber void checkStoreLoad() {
273fa38318SNico Weber   typedef typename T::Type Type;
283fa38318SNico Weber   ValAndMagic<T> Val;
293fa38318SNico Weber   // Prevent the compiler from scalarizing the struct.
303fa38318SNico Weber   ValAndMagic<T>::Sink = &Val;
313fa38318SNico Weber   // Ensure that surrounding memory is not overwritten.
323fa38318SNico Weber   Val.Magic0 = Val.Magic1 = (Type)-3;
333fa38318SNico Weber   for (u64 I = 0; I < 100; I++) {
343fa38318SNico Weber     // Generate A value that occupies all bytes of the variable.
353fa38318SNico Weber     u64 V = I;
363fa38318SNico Weber     V |= V << 8;
373fa38318SNico Weber     V |= V << 16;
383fa38318SNico Weber     V |= V << 32;
393fa38318SNico Weber     Val.A.ValDoNotUse = (Type)V;
403fa38318SNico Weber     EXPECT_EQ(atomic_load(&Val.A, LoadMO), (Type)V);
413fa38318SNico Weber     Val.A.ValDoNotUse = (Type)-1;
423fa38318SNico Weber     atomic_store(&Val.A, (Type)V, StoreMO);
433fa38318SNico Weber     EXPECT_EQ(Val.A.ValDoNotUse, (Type)V);
443fa38318SNico Weber   }
453fa38318SNico Weber   EXPECT_EQ(Val.Magic0, (Type)-3);
463fa38318SNico Weber   EXPECT_EQ(Val.Magic1, (Type)-3);
473fa38318SNico Weber }
483fa38318SNico Weber 
TEST(ScudoAtomicTest,AtomicStoreLoad)493fa38318SNico Weber TEST(ScudoAtomicTest, AtomicStoreLoad) {
503fa38318SNico Weber   checkStoreLoad<atomic_u8, memory_order_relaxed, memory_order_relaxed>();
513fa38318SNico Weber   checkStoreLoad<atomic_u8, memory_order_consume, memory_order_relaxed>();
523fa38318SNico Weber   checkStoreLoad<atomic_u8, memory_order_acquire, memory_order_relaxed>();
533fa38318SNico Weber   checkStoreLoad<atomic_u8, memory_order_relaxed, memory_order_release>();
543fa38318SNico Weber   checkStoreLoad<atomic_u8, memory_order_seq_cst, memory_order_seq_cst>();
553fa38318SNico Weber 
563fa38318SNico Weber   checkStoreLoad<atomic_u16, memory_order_relaxed, memory_order_relaxed>();
573fa38318SNico Weber   checkStoreLoad<atomic_u16, memory_order_consume, memory_order_relaxed>();
583fa38318SNico Weber   checkStoreLoad<atomic_u16, memory_order_acquire, memory_order_relaxed>();
593fa38318SNico Weber   checkStoreLoad<atomic_u16, memory_order_relaxed, memory_order_release>();
603fa38318SNico Weber   checkStoreLoad<atomic_u16, memory_order_seq_cst, memory_order_seq_cst>();
613fa38318SNico Weber 
623fa38318SNico Weber   checkStoreLoad<atomic_u32, memory_order_relaxed, memory_order_relaxed>();
633fa38318SNico Weber   checkStoreLoad<atomic_u32, memory_order_consume, memory_order_relaxed>();
643fa38318SNico Weber   checkStoreLoad<atomic_u32, memory_order_acquire, memory_order_relaxed>();
653fa38318SNico Weber   checkStoreLoad<atomic_u32, memory_order_relaxed, memory_order_release>();
663fa38318SNico Weber   checkStoreLoad<atomic_u32, memory_order_seq_cst, memory_order_seq_cst>();
673fa38318SNico Weber 
683fa38318SNico Weber   checkStoreLoad<atomic_u64, memory_order_relaxed, memory_order_relaxed>();
693fa38318SNico Weber   checkStoreLoad<atomic_u64, memory_order_consume, memory_order_relaxed>();
703fa38318SNico Weber   checkStoreLoad<atomic_u64, memory_order_acquire, memory_order_relaxed>();
713fa38318SNico Weber   checkStoreLoad<atomic_u64, memory_order_relaxed, memory_order_release>();
723fa38318SNico Weber   checkStoreLoad<atomic_u64, memory_order_seq_cst, memory_order_seq_cst>();
733fa38318SNico Weber 
743fa38318SNico Weber   checkStoreLoad<atomic_uptr, memory_order_relaxed, memory_order_relaxed>();
753fa38318SNico Weber   checkStoreLoad<atomic_uptr, memory_order_consume, memory_order_relaxed>();
763fa38318SNico Weber   checkStoreLoad<atomic_uptr, memory_order_acquire, memory_order_relaxed>();
773fa38318SNico Weber   checkStoreLoad<atomic_uptr, memory_order_relaxed, memory_order_release>();
783fa38318SNico Weber   checkStoreLoad<atomic_uptr, memory_order_seq_cst, memory_order_seq_cst>();
793fa38318SNico Weber }
803fa38318SNico Weber 
checkAtomicCompareExchange()813fa38318SNico Weber template <typename T> void checkAtomicCompareExchange() {
823fa38318SNico Weber   typedef typename T::Type Type;
833fa38318SNico Weber   Type OldVal = 42;
843fa38318SNico Weber   Type NewVal = 24;
853fa38318SNico Weber   Type V = OldVal;
86*f668a84bSKostya Kortchinsky   EXPECT_TRUE(atomic_compare_exchange_strong(reinterpret_cast<T *>(&V), &OldVal,
87*f668a84bSKostya Kortchinsky                                              NewVal, memory_order_relaxed));
883fa38318SNico Weber   EXPECT_FALSE(atomic_compare_exchange_strong(
893fa38318SNico Weber       reinterpret_cast<T *>(&V), &OldVal, NewVal, memory_order_relaxed));
903fa38318SNico Weber   EXPECT_EQ(NewVal, OldVal);
913fa38318SNico Weber }
923fa38318SNico Weber 
TEST(ScudoAtomicTest,AtomicCompareExchangeTest)933fa38318SNico Weber TEST(ScudoAtomicTest, AtomicCompareExchangeTest) {
943fa38318SNico Weber   checkAtomicCompareExchange<atomic_u8>();
953fa38318SNico Weber   checkAtomicCompareExchange<atomic_u16>();
963fa38318SNico Weber   checkAtomicCompareExchange<atomic_u32>();
973fa38318SNico Weber   checkAtomicCompareExchange<atomic_u64>();
983fa38318SNico Weber   checkAtomicCompareExchange<atomic_uptr>();
993fa38318SNico Weber }
1003fa38318SNico Weber 
1013fa38318SNico Weber } // namespace scudo
102