• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-inl.h"
18 
19 #include "common_runtime_test.h"
20 #include "thread-current-inl.h"
21 
22 namespace art HIDDEN {
23 
24 class MutexTest : public CommonRuntimeTest {
25  protected:
MutexTest()26   MutexTest() {
27     use_boot_image_ = true;  // Make the Runtime creation cheaper.
28   }
29 };
30 
31 struct MutexTester {
AssertDepthart::MutexTester32   static void AssertDepth(Mutex& mu, uint32_t expected_depth) {
33     ASSERT_EQ(expected_depth, mu.GetDepth());
34 
35     // This test is single-threaded, so we also know _who_ should hold the lock.
36     if (expected_depth == 0) {
37       mu.AssertNotHeld(Thread::Current());
38     } else {
39       mu.AssertHeld(Thread::Current());
40     }
41   }
42 };
43 
TEST_F(MutexTest,LockUnlock)44 TEST_F(MutexTest, LockUnlock) {
45   // TODO: Remove `Mutex` dependency on `Runtime` or at least make sure it works
46   // without a `Runtime` with reasonable defaults (and without dumping stack for timeout).
47   ASSERT_TRUE(Runtime::Current() != nullptr);
48   Mutex mu("test mutex");
49   MutexTester::AssertDepth(mu, 0U);
50   mu.Lock(Thread::Current());
51   MutexTester::AssertDepth(mu, 1U);
52   mu.Unlock(Thread::Current());
53   MutexTester::AssertDepth(mu, 0U);
54 }
55 
56 // GCC has trouble with our mutex tests, so we have to turn off thread safety analysis.
TryLockUnlockTest()57 static void TryLockUnlockTest() NO_THREAD_SAFETY_ANALYSIS {
58   Mutex mu("test mutex");
59   MutexTester::AssertDepth(mu, 0U);
60   ASSERT_TRUE(mu.TryLock(Thread::Current()));
61   MutexTester::AssertDepth(mu, 1U);
62   mu.Unlock(Thread::Current());
63   MutexTester::AssertDepth(mu, 0U);
64 }
65 
TEST_F(MutexTest,TryLockUnlock)66 TEST_F(MutexTest, TryLockUnlock) {
67   TryLockUnlockTest();
68 }
69 
70 // GCC has trouble with our mutex tests, so we have to turn off thread safety analysis.
RecursiveLockUnlockTest()71 static void RecursiveLockUnlockTest() NO_THREAD_SAFETY_ANALYSIS {
72   Mutex mu("test mutex", kDefaultMutexLevel, true);
73   MutexTester::AssertDepth(mu, 0U);
74   mu.Lock(Thread::Current());
75   MutexTester::AssertDepth(mu, 1U);
76   mu.Lock(Thread::Current());
77   MutexTester::AssertDepth(mu, 2U);
78   mu.Unlock(Thread::Current());
79   MutexTester::AssertDepth(mu, 1U);
80   mu.Unlock(Thread::Current());
81   MutexTester::AssertDepth(mu, 0U);
82 }
83 
TEST_F(MutexTest,RecursiveLockUnlock)84 TEST_F(MutexTest, RecursiveLockUnlock) {
85   RecursiveLockUnlockTest();
86 }
87 
88 // GCC has trouble with our mutex tests, so we have to turn off thread safety analysis.
RecursiveTryLockUnlockTest()89 static void RecursiveTryLockUnlockTest() NO_THREAD_SAFETY_ANALYSIS {
90   Mutex mu("test mutex", kDefaultMutexLevel, true);
91   MutexTester::AssertDepth(mu, 0U);
92   ASSERT_TRUE(mu.TryLock(Thread::Current()));
93   MutexTester::AssertDepth(mu, 1U);
94   ASSERT_TRUE(mu.TryLock(Thread::Current()));
95   MutexTester::AssertDepth(mu, 2U);
96   mu.Unlock(Thread::Current());
97   MutexTester::AssertDepth(mu, 1U);
98   mu.Unlock(Thread::Current());
99   MutexTester::AssertDepth(mu, 0U);
100 }
101 
TEST_F(MutexTest,RecursiveTryLockUnlock)102 TEST_F(MutexTest, RecursiveTryLockUnlock) {
103   RecursiveTryLockUnlockTest();
104 }
105 
106 
107 struct RecursiveLockWait {
RecursiveLockWaitart::RecursiveLockWait108   RecursiveLockWait()
109       : mu("test mutex", kDefaultMutexLevel, true), cv("test condition variable", mu) {
110   }
111 
112   Mutex mu;
113   ConditionVariable cv;
114 };
115 
RecursiveLockWaitCallback(void * arg)116 static void* RecursiveLockWaitCallback(void* arg) {
117   RecursiveLockWait* state = reinterpret_cast<RecursiveLockWait*>(arg);
118   state->mu.Lock(Thread::Current());
119   state->cv.Signal(Thread::Current());
120   state->mu.Unlock(Thread::Current());
121   return nullptr;
122 }
123 
124 // GCC has trouble with our mutex tests, so we have to turn off thread safety analysis.
RecursiveLockWaitTest()125 static void RecursiveLockWaitTest() NO_THREAD_SAFETY_ANALYSIS {
126   RecursiveLockWait state;
127   state.mu.Lock(Thread::Current());
128   state.mu.Lock(Thread::Current());
129 
130   pthread_t pthread;
131   int pthread_create_result = pthread_create(&pthread, nullptr, RecursiveLockWaitCallback, &state);
132   ASSERT_EQ(0, pthread_create_result);
133 
134   state.cv.Wait(Thread::Current());
135 
136   state.mu.Unlock(Thread::Current());
137   state.mu.Unlock(Thread::Current());
138   EXPECT_EQ(pthread_join(pthread, nullptr), 0);
139 }
140 
141 // This ensures we don't hang when waiting on a recursively locked mutex,
142 // which is not supported with bare pthread_mutex_t.
TEST_F(MutexTest,RecursiveLockWait)143 TEST_F(MutexTest, RecursiveLockWait) {
144   RecursiveLockWaitTest();
145 }
146 
TEST_F(MutexTest,SharedLockUnlock)147 TEST_F(MutexTest, SharedLockUnlock) {
148   ReaderWriterMutex mu("test rwmutex");
149   mu.AssertNotHeld(Thread::Current());
150   mu.AssertNotExclusiveHeld(Thread::Current());
151   mu.SharedLock(Thread::Current());
152   mu.AssertSharedHeld(Thread::Current());
153   mu.AssertNotExclusiveHeld(Thread::Current());
154   mu.SharedUnlock(Thread::Current());
155   mu.AssertNotHeld(Thread::Current());
156 }
157 
TEST_F(MutexTest,ExclusiveLockUnlock)158 TEST_F(MutexTest, ExclusiveLockUnlock) {
159   ReaderWriterMutex mu("test rwmutex");
160   mu.AssertNotHeld(Thread::Current());
161   mu.ExclusiveLock(Thread::Current());
162   mu.AssertSharedHeld(Thread::Current());
163   mu.AssertExclusiveHeld(Thread::Current());
164   mu.ExclusiveUnlock(Thread::Current());
165   mu.AssertNotHeld(Thread::Current());
166 }
167 
168 // GCC has trouble with our mutex tests, so we have to turn off thread safety analysis.
SharedTryLockUnlockTest()169 static void SharedTryLockUnlockTest() NO_THREAD_SAFETY_ANALYSIS {
170   ReaderWriterMutex mu("test rwmutex");
171   mu.AssertNotHeld(Thread::Current());
172   ASSERT_TRUE(mu.SharedTryLock(Thread::Current()));
173   mu.AssertSharedHeld(Thread::Current());
174   mu.SharedUnlock(Thread::Current());
175   mu.AssertNotHeld(Thread::Current());
176 }
177 
TEST_F(MutexTest,SharedTryLockUnlock)178 TEST_F(MutexTest, SharedTryLockUnlock) {
179   SharedTryLockUnlockTest();
180 }
181 
182 }  // namespace art
183