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 { 26 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 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. 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 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. 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 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. 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 93 TEST_F(MutexTest, RecursiveTryLockUnlock) { 94 RecursiveTryLockUnlockTest(); 95 } 96 97 98 struct RecursiveLockWait { 99 explicit RecursiveLockWait() 100 : mu("test mutex", kDefaultMutexLevel, true), cv("test condition variable", mu) { 101 } 102 103 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. 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. 134 TEST_F(MutexTest, RecursiveLockWait) { 135 RecursiveLockWaitTest(); 136 } 137 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 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. 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 169 TEST_F(MutexTest, SharedTryLockUnlock) { 170 SharedTryLockUnlockTest(); 171 } 172 173 } // namespace art 174