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_runtime_test.h" 20#include "thread-inl.h" 21 22namespace art { 23 24class MutexTest : public CommonRuntimeTest {}; 25 26struct 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 39TEST_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. 49static 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 58TEST_F(MutexTest, TryLockUnlock) { 59 TryLockUnlockTest(); 60} 61 62// GCC has trouble with our mutex tests, so we have to turn off thread safety analysis. 63static 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 76TEST_F(MutexTest, RecursiveLockUnlock) { 77 RecursiveLockUnlockTest(); 78} 79 80// GCC has trouble with our mutex tests, so we have to turn off thread safety analysis. 81static 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 94TEST_F(MutexTest, RecursiveTryLockUnlock) { 95 RecursiveTryLockUnlockTest(); 96} 97 98 99struct RecursiveLockWait { 100 explicit RecursiveLockWait() 101 : mu("test mutex", kDefaultMutexLevel, true), cv("test condition variable", mu) { 102 } 103 104 static void* Callback(void* arg) { 105 RecursiveLockWait* state = reinterpret_cast<RecursiveLockWait*>(arg); 106 state->mu.Lock(Thread::Current()); 107 state->cv.Signal(Thread::Current()); 108 state->mu.Unlock(Thread::Current()); 109 return NULL; 110 } 111 112 Mutex mu; 113 ConditionVariable cv; 114}; 115 116// GCC has trouble with our mutex tests, so we have to turn off thread safety analysis. 117static 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, NULL, RecursiveLockWait::Callback, &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, NULL), 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. 135TEST_F(MutexTest, RecursiveLockWait) { 136 RecursiveLockWaitTest(); 137} 138 139TEST_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 150TEST_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. 161static 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 170TEST_F(MutexTest, SharedTryLockUnlock) { 171 SharedTryLockUnlockTest(); 172} 173 174} // namespace art 175