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