xref: /aosp_15_r20/external/scudo/standalone/tests/mutex_test.cpp (revision 76559068c068bd27e82aff38fac3bfc865233bca)
1*76559068SAndroid Build Coastguard Worker //===-- mutex_test.cpp ------------------------------------------*- C++ -*-===//
2*76559068SAndroid Build Coastguard Worker //
3*76559068SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*76559068SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information.
5*76559068SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*76559068SAndroid Build Coastguard Worker //
7*76559068SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
8*76559068SAndroid Build Coastguard Worker 
9*76559068SAndroid Build Coastguard Worker #include "tests/scudo_unit_test.h"
10*76559068SAndroid Build Coastguard Worker 
11*76559068SAndroid Build Coastguard Worker #include "mutex.h"
12*76559068SAndroid Build Coastguard Worker 
13*76559068SAndroid Build Coastguard Worker #include <pthread.h>
14*76559068SAndroid Build Coastguard Worker #include <string.h>
15*76559068SAndroid Build Coastguard Worker 
16*76559068SAndroid Build Coastguard Worker class TestData {
17*76559068SAndroid Build Coastguard Worker public:
TestData(scudo::HybridMutex & M)18*76559068SAndroid Build Coastguard Worker   explicit TestData(scudo::HybridMutex &M) : Mutex(M) {
19*76559068SAndroid Build Coastguard Worker     for (scudo::u32 I = 0; I < Size; I++)
20*76559068SAndroid Build Coastguard Worker       Data[I] = 0;
21*76559068SAndroid Build Coastguard Worker   }
22*76559068SAndroid Build Coastguard Worker 
write()23*76559068SAndroid Build Coastguard Worker   void write() {
24*76559068SAndroid Build Coastguard Worker     scudo::ScopedLock L(Mutex);
25*76559068SAndroid Build Coastguard Worker     T V0 = Data[0];
26*76559068SAndroid Build Coastguard Worker     for (scudo::u32 I = 0; I < Size; I++) {
27*76559068SAndroid Build Coastguard Worker       EXPECT_EQ(Data[I], V0);
28*76559068SAndroid Build Coastguard Worker       Data[I]++;
29*76559068SAndroid Build Coastguard Worker     }
30*76559068SAndroid Build Coastguard Worker   }
31*76559068SAndroid Build Coastguard Worker 
tryWrite()32*76559068SAndroid Build Coastguard Worker   void tryWrite() {
33*76559068SAndroid Build Coastguard Worker     if (!Mutex.tryLock())
34*76559068SAndroid Build Coastguard Worker       return;
35*76559068SAndroid Build Coastguard Worker     T V0 = Data[0];
36*76559068SAndroid Build Coastguard Worker     for (scudo::u32 I = 0; I < Size; I++) {
37*76559068SAndroid Build Coastguard Worker       EXPECT_EQ(Data[I], V0);
38*76559068SAndroid Build Coastguard Worker       Data[I]++;
39*76559068SAndroid Build Coastguard Worker     }
40*76559068SAndroid Build Coastguard Worker     Mutex.unlock();
41*76559068SAndroid Build Coastguard Worker   }
42*76559068SAndroid Build Coastguard Worker 
backoff()43*76559068SAndroid Build Coastguard Worker   void backoff() {
44*76559068SAndroid Build Coastguard Worker     volatile T LocalData[Size] = {};
45*76559068SAndroid Build Coastguard Worker     for (scudo::u32 I = 0; I < Size; I++) {
46*76559068SAndroid Build Coastguard Worker       LocalData[I] = LocalData[I] + 1;
47*76559068SAndroid Build Coastguard Worker       EXPECT_EQ(LocalData[I], 1U);
48*76559068SAndroid Build Coastguard Worker     }
49*76559068SAndroid Build Coastguard Worker   }
50*76559068SAndroid Build Coastguard Worker 
51*76559068SAndroid Build Coastguard Worker private:
52*76559068SAndroid Build Coastguard Worker   static const scudo::u32 Size = 64U;
53*76559068SAndroid Build Coastguard Worker   typedef scudo::u64 T;
54*76559068SAndroid Build Coastguard Worker   scudo::HybridMutex &Mutex;
55*76559068SAndroid Build Coastguard Worker   alignas(SCUDO_CACHE_LINE_SIZE) T Data[Size];
56*76559068SAndroid Build Coastguard Worker };
57*76559068SAndroid Build Coastguard Worker 
58*76559068SAndroid Build Coastguard Worker const scudo::u32 NumberOfThreads = 8;
59*76559068SAndroid Build Coastguard Worker #if SCUDO_DEBUG
60*76559068SAndroid Build Coastguard Worker const scudo::u32 NumberOfIterations = 4 * 1024;
61*76559068SAndroid Build Coastguard Worker #else
62*76559068SAndroid Build Coastguard Worker const scudo::u32 NumberOfIterations = 16 * 1024;
63*76559068SAndroid Build Coastguard Worker #endif
64*76559068SAndroid Build Coastguard Worker 
lockThread(void * Param)65*76559068SAndroid Build Coastguard Worker static void *lockThread(void *Param) {
66*76559068SAndroid Build Coastguard Worker   TestData *Data = reinterpret_cast<TestData *>(Param);
67*76559068SAndroid Build Coastguard Worker   for (scudo::u32 I = 0; I < NumberOfIterations; I++) {
68*76559068SAndroid Build Coastguard Worker     Data->write();
69*76559068SAndroid Build Coastguard Worker     Data->backoff();
70*76559068SAndroid Build Coastguard Worker   }
71*76559068SAndroid Build Coastguard Worker   return 0;
72*76559068SAndroid Build Coastguard Worker }
73*76559068SAndroid Build Coastguard Worker 
tryThread(void * Param)74*76559068SAndroid Build Coastguard Worker static void *tryThread(void *Param) {
75*76559068SAndroid Build Coastguard Worker   TestData *Data = reinterpret_cast<TestData *>(Param);
76*76559068SAndroid Build Coastguard Worker   for (scudo::u32 I = 0; I < NumberOfIterations; I++) {
77*76559068SAndroid Build Coastguard Worker     Data->tryWrite();
78*76559068SAndroid Build Coastguard Worker     Data->backoff();
79*76559068SAndroid Build Coastguard Worker   }
80*76559068SAndroid Build Coastguard Worker   return 0;
81*76559068SAndroid Build Coastguard Worker }
82*76559068SAndroid Build Coastguard Worker 
TEST(ScudoMutexTest,Mutex)83*76559068SAndroid Build Coastguard Worker TEST(ScudoMutexTest, Mutex) {
84*76559068SAndroid Build Coastguard Worker   scudo::HybridMutex M;
85*76559068SAndroid Build Coastguard Worker   TestData Data(M);
86*76559068SAndroid Build Coastguard Worker   pthread_t Threads[NumberOfThreads];
87*76559068SAndroid Build Coastguard Worker   for (scudo::u32 I = 0; I < NumberOfThreads; I++)
88*76559068SAndroid Build Coastguard Worker     pthread_create(&Threads[I], 0, lockThread, &Data);
89*76559068SAndroid Build Coastguard Worker   for (scudo::u32 I = 0; I < NumberOfThreads; I++)
90*76559068SAndroid Build Coastguard Worker     pthread_join(Threads[I], 0);
91*76559068SAndroid Build Coastguard Worker }
92*76559068SAndroid Build Coastguard Worker 
TEST(ScudoMutexTest,MutexTry)93*76559068SAndroid Build Coastguard Worker TEST(ScudoMutexTest, MutexTry) {
94*76559068SAndroid Build Coastguard Worker   scudo::HybridMutex M;
95*76559068SAndroid Build Coastguard Worker   TestData Data(M);
96*76559068SAndroid Build Coastguard Worker   pthread_t Threads[NumberOfThreads];
97*76559068SAndroid Build Coastguard Worker   for (scudo::u32 I = 0; I < NumberOfThreads; I++)
98*76559068SAndroid Build Coastguard Worker     pthread_create(&Threads[I], 0, tryThread, &Data);
99*76559068SAndroid Build Coastguard Worker   for (scudo::u32 I = 0; I < NumberOfThreads; I++)
100*76559068SAndroid Build Coastguard Worker     pthread_join(Threads[I], 0);
101*76559068SAndroid Build Coastguard Worker }
102*76559068SAndroid Build Coastguard Worker 
TEST(ScudoMutexTest,MutexAssertHeld)103*76559068SAndroid Build Coastguard Worker TEST(ScudoMutexTest, MutexAssertHeld) {
104*76559068SAndroid Build Coastguard Worker   scudo::HybridMutex M;
105*76559068SAndroid Build Coastguard Worker   M.lock();
106*76559068SAndroid Build Coastguard Worker   M.assertHeld();
107*76559068SAndroid Build Coastguard Worker   M.unlock();
108*76559068SAndroid Build Coastguard Worker }
109