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 16class TestData { 17public: 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] = LocalData[I] + 1; 47 EXPECT_EQ(LocalData[I], 1U); 48 } 49 } 50 51private: 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 58const scudo::u32 NumberOfThreads = 8; 59#if SCUDO_DEBUG 60const scudo::u32 NumberOfIterations = 4 * 1024; 61#else 62const scudo::u32 NumberOfIterations = 16 * 1024; 63#endif 64 65static 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 74static 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 83TEST(ScudoMutexTest, Mutex) { 84 scudo::HybridMutex M; 85 TestData Data(M); 86 pthread_t Threads[NumberOfThreads]; 87 for (scudo::u32 I = 0; I < NumberOfThreads; I++) 88 pthread_create(&Threads[I], 0, lockThread, &Data); 89 for (scudo::u32 I = 0; I < NumberOfThreads; I++) 90 pthread_join(Threads[I], 0); 91} 92 93TEST(ScudoMutexTest, MutexTry) { 94 scudo::HybridMutex M; 95 TestData Data(M); 96 pthread_t Threads[NumberOfThreads]; 97 for (scudo::u32 I = 0; I < NumberOfThreads; I++) 98 pthread_create(&Threads[I], 0, tryThread, &Data); 99 for (scudo::u32 I = 0; I < NumberOfThreads; I++) 100 pthread_join(Threads[I], 0); 101} 102