1 //===-- mutex_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 "mutex.h" 12 13 #include <pthread.h> 14 #include <string.h> 15 16 class TestData { 17 public: 18 explicit TestData(scudo::HybridMutex &M) : Mutex(M) { 19 for (scudo::u32 I = 0; I < Size; I++) 20 Data[I] = 0; 21 } 22 23 void write() { 24 scudo::ScopedLock L(Mutex); 25 T V0 = Data[0]; 26 for (scudo::u32 I = 0; I < Size; I++) { 27 EXPECT_EQ(Data[I], V0); 28 Data[I]++; 29 } 30 } 31 32 void tryWrite() { 33 if (!Mutex.tryLock()) 34 return; 35 T V0 = Data[0]; 36 for (scudo::u32 I = 0; I < Size; I++) { 37 EXPECT_EQ(Data[I], V0); 38 Data[I]++; 39 } 40 Mutex.unlock(); 41 } 42 43 void backoff() { 44 volatile T LocalData[Size] = {}; 45 for (scudo::u32 I = 0; I < Size; I++) { 46 LocalData[I]++; 47 EXPECT_EQ(LocalData[I], 1U); 48 } 49 } 50 51 private: 52 static const scudo::u32 Size = 64U; 53 typedef scudo::u64 T; 54 scudo::HybridMutex &Mutex; 55 alignas(SCUDO_CACHE_LINE_SIZE) T Data[Size]; 56 }; 57 58 const scudo::u32 NumberOfThreads = 8; 59 #if SCUDO_DEBUG 60 const scudo::u32 NumberOfIterations = 4 * 1024; 61 #else 62 const scudo::u32 NumberOfIterations = 16 * 1024; 63 #endif 64 65 static void *lockThread(void *Param) { 66 TestData *Data = reinterpret_cast<TestData *>(Param); 67 for (scudo::u32 I = 0; I < NumberOfIterations; I++) { 68 Data->write(); 69 Data->backoff(); 70 } 71 return 0; 72 } 73 74 static void *tryThread(void *Param) { 75 TestData *Data = reinterpret_cast<TestData *>(Param); 76 for (scudo::u32 I = 0; I < NumberOfIterations; I++) { 77 Data->tryWrite(); 78 Data->backoff(); 79 } 80 return 0; 81 } 82 83 TEST(ScudoMutexTest, Mutex) { 84 scudo::HybridMutex M; 85 M.init(); 86 TestData Data(M); 87 pthread_t Threads[NumberOfThreads]; 88 for (scudo::u32 I = 0; I < NumberOfThreads; I++) 89 pthread_create(&Threads[I], 0, lockThread, &Data); 90 for (scudo::u32 I = 0; I < NumberOfThreads; I++) 91 pthread_join(Threads[I], 0); 92 } 93 94 TEST(ScudoMutexTest, MutexTry) { 95 scudo::HybridMutex M; 96 M.init(); 97 TestData Data(M); 98 pthread_t Threads[NumberOfThreads]; 99 for (scudo::u32 I = 0; I < NumberOfThreads; I++) 100 pthread_create(&Threads[I], 0, tryThread, &Data); 101 for (scudo::u32 I = 0; I < NumberOfThreads; I++) 102 pthread_join(Threads[I], 0); 103 } 104