1 /*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "mutex.h"
18
19 #include "common_test.h"
20
21 namespace art {
22
23 class MutexTest : public CommonTest {};
24
25 struct MutexTester {
AssertDepthart::MutexTester26 static void AssertDepth(Mutex& mu, uint32_t expected_depth) {
27 ASSERT_EQ(expected_depth, mu.GetDepth());
28
29 // This test is single-threaded, so we also know _who_ should hold the lock.
30 if (expected_depth == 0) {
31 mu.AssertNotHeld(Thread::Current());
32 } else {
33 mu.AssertHeld(Thread::Current());
34 }
35 }
36 };
37
TEST_F(MutexTest,LockUnlock)38 TEST_F(MutexTest, LockUnlock) {
39 Mutex mu("test mutex");
40 MutexTester::AssertDepth(mu, 0U);
41 mu.Lock(Thread::Current());
42 MutexTester::AssertDepth(mu, 1U);
43 mu.Unlock(Thread::Current());
44 MutexTester::AssertDepth(mu, 0U);
45 }
46
47 // GCC has trouble with our mutex tests, so we have to turn off thread safety analysis.
TryLockUnlockTest()48 static void TryLockUnlockTest() NO_THREAD_SAFETY_ANALYSIS {
49 Mutex mu("test mutex");
50 MutexTester::AssertDepth(mu, 0U);
51 ASSERT_TRUE(mu.TryLock(Thread::Current()));
52 MutexTester::AssertDepth(mu, 1U);
53 mu.Unlock(Thread::Current());
54 MutexTester::AssertDepth(mu, 0U);
55 }
56
TEST_F(MutexTest,TryLockUnlock)57 TEST_F(MutexTest, TryLockUnlock) {
58 TryLockUnlockTest();
59 }
60
61 // GCC has trouble with our mutex tests, so we have to turn off thread safety analysis.
RecursiveLockUnlockTest()62 static void RecursiveLockUnlockTest() NO_THREAD_SAFETY_ANALYSIS {
63 Mutex mu("test mutex", kDefaultMutexLevel, true);
64 MutexTester::AssertDepth(mu, 0U);
65 mu.Lock(Thread::Current());
66 MutexTester::AssertDepth(mu, 1U);
67 mu.Lock(Thread::Current());
68 MutexTester::AssertDepth(mu, 2U);
69 mu.Unlock(Thread::Current());
70 MutexTester::AssertDepth(mu, 1U);
71 mu.Unlock(Thread::Current());
72 MutexTester::AssertDepth(mu, 0U);
73 }
74
TEST_F(MutexTest,RecursiveLockUnlock)75 TEST_F(MutexTest, RecursiveLockUnlock) {
76 RecursiveLockUnlockTest();
77 }
78
79 // GCC has trouble with our mutex tests, so we have to turn off thread safety analysis.
RecursiveTryLockUnlockTest()80 static void RecursiveTryLockUnlockTest() NO_THREAD_SAFETY_ANALYSIS {
81 Mutex mu("test mutex", kDefaultMutexLevel, true);
82 MutexTester::AssertDepth(mu, 0U);
83 ASSERT_TRUE(mu.TryLock(Thread::Current()));
84 MutexTester::AssertDepth(mu, 1U);
85 ASSERT_TRUE(mu.TryLock(Thread::Current()));
86 MutexTester::AssertDepth(mu, 2U);
87 mu.Unlock(Thread::Current());
88 MutexTester::AssertDepth(mu, 1U);
89 mu.Unlock(Thread::Current());
90 MutexTester::AssertDepth(mu, 0U);
91 }
92
TEST_F(MutexTest,RecursiveTryLockUnlock)93 TEST_F(MutexTest, RecursiveTryLockUnlock) {
94 RecursiveTryLockUnlockTest();
95 }
96
97
98 struct RecursiveLockWait {
RecursiveLockWaitart::RecursiveLockWait99 explicit RecursiveLockWait()
100 : mu("test mutex", kDefaultMutexLevel, true), cv("test condition variable", mu) {
101 }
102
Callbackart::RecursiveLockWait103 static void* Callback(void* arg) {
104 RecursiveLockWait* state = reinterpret_cast<RecursiveLockWait*>(arg);
105 state->mu.Lock(Thread::Current());
106 state->cv.Signal(Thread::Current());
107 state->mu.Unlock(Thread::Current());
108 return NULL;
109 }
110
111 Mutex mu;
112 ConditionVariable cv;
113 };
114
115 // GCC has trouble with our mutex tests, so we have to turn off thread safety analysis.
RecursiveLockWaitTest()116 static void RecursiveLockWaitTest() NO_THREAD_SAFETY_ANALYSIS {
117 RecursiveLockWait state;
118 state.mu.Lock(Thread::Current());
119 state.mu.Lock(Thread::Current());
120
121 pthread_t pthread;
122 int pthread_create_result = pthread_create(&pthread, NULL, RecursiveLockWait::Callback, &state);
123 ASSERT_EQ(0, pthread_create_result);
124
125 state.cv.Wait(Thread::Current());
126
127 state.mu.Unlock(Thread::Current());
128 state.mu.Unlock(Thread::Current());
129 EXPECT_EQ(pthread_join(pthread, NULL), 0);
130 }
131
132 // This ensures we don't hang when waiting on a recursively locked mutex,
133 // which is not supported with bare pthread_mutex_t.
TEST_F(MutexTest,RecursiveLockWait)134 TEST_F(MutexTest, RecursiveLockWait) {
135 RecursiveLockWaitTest();
136 }
137
TEST_F(MutexTest,SharedLockUnlock)138 TEST_F(MutexTest, SharedLockUnlock) {
139 ReaderWriterMutex mu("test rwmutex");
140 mu.AssertNotHeld(Thread::Current());
141 mu.AssertNotExclusiveHeld(Thread::Current());
142 mu.SharedLock(Thread::Current());
143 mu.AssertSharedHeld(Thread::Current());
144 mu.AssertNotExclusiveHeld(Thread::Current());
145 mu.SharedUnlock(Thread::Current());
146 mu.AssertNotHeld(Thread::Current());
147 }
148
TEST_F(MutexTest,ExclusiveLockUnlock)149 TEST_F(MutexTest, ExclusiveLockUnlock) {
150 ReaderWriterMutex mu("test rwmutex");
151 mu.AssertNotHeld(Thread::Current());
152 mu.ExclusiveLock(Thread::Current());
153 mu.AssertSharedHeld(Thread::Current());
154 mu.AssertExclusiveHeld(Thread::Current());
155 mu.ExclusiveUnlock(Thread::Current());
156 mu.AssertNotHeld(Thread::Current());
157 }
158
159 // GCC has trouble with our mutex tests, so we have to turn off thread safety analysis.
SharedTryLockUnlockTest()160 static void SharedTryLockUnlockTest() NO_THREAD_SAFETY_ANALYSIS {
161 ReaderWriterMutex mu("test rwmutex");
162 mu.AssertNotHeld(Thread::Current());
163 ASSERT_TRUE(mu.SharedTryLock(Thread::Current()));
164 mu.AssertSharedHeld(Thread::Current());
165 mu.SharedUnlock(Thread::Current());
166 mu.AssertNotHeld(Thread::Current());
167 }
168
TEST_F(MutexTest,SharedTryLockUnlock)169 TEST_F(MutexTest, SharedTryLockUnlock) {
170 SharedTryLockUnlockTest();
171 }
172
173 } // namespace art
174