//===-- mutex_test.cpp ------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "tests/scudo_unit_test.h" #include "mutex.h" #include #include class TestData { public: explicit TestData(scudo::HybridMutex &M) : Mutex(M) { for (scudo::u32 I = 0; I < Size; I++) Data[I] = 0; } void write() { scudo::ScopedLock L(Mutex); T V0 = Data[0]; for (scudo::u32 I = 0; I < Size; I++) { EXPECT_EQ(Data[I], V0); Data[I]++; } } void tryWrite() { if (!Mutex.tryLock()) return; T V0 = Data[0]; for (scudo::u32 I = 0; I < Size; I++) { EXPECT_EQ(Data[I], V0); Data[I]++; } Mutex.unlock(); } void backoff() { volatile T LocalData[Size] = {}; for (scudo::u32 I = 0; I < Size; I++) { LocalData[I]++; EXPECT_EQ(LocalData[I], 1U); } } private: static const scudo::u32 Size = 64U; typedef scudo::u64 T; scudo::HybridMutex &Mutex; alignas(SCUDO_CACHE_LINE_SIZE) T Data[Size]; }; const scudo::u32 NumberOfThreads = 8; #if SCUDO_DEBUG const scudo::u32 NumberOfIterations = 4 * 1024; #else const scudo::u32 NumberOfIterations = 16 * 1024; #endif static void *lockThread(void *Param) { TestData *Data = reinterpret_cast(Param); for (scudo::u32 I = 0; I < NumberOfIterations; I++) { Data->write(); Data->backoff(); } return 0; } static void *tryThread(void *Param) { TestData *Data = reinterpret_cast(Param); for (scudo::u32 I = 0; I < NumberOfIterations; I++) { Data->tryWrite(); Data->backoff(); } return 0; } TEST(ScudoMutexTest, Mutex) { scudo::HybridMutex M; TestData Data(M); pthread_t Threads[NumberOfThreads]; for (scudo::u32 I = 0; I < NumberOfThreads; I++) pthread_create(&Threads[I], 0, lockThread, &Data); for (scudo::u32 I = 0; I < NumberOfThreads; I++) pthread_join(Threads[I], 0); } TEST(ScudoMutexTest, MutexTry) { scudo::HybridMutex M; TestData Data(M); pthread_t Threads[NumberOfThreads]; for (scudo::u32 I = 0; I < NumberOfThreads; I++) pthread_create(&Threads[I], 0, tryThread, &Data); for (scudo::u32 I = 0; I < NumberOfThreads; I++) pthread_join(Threads[I], 0); }