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