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