• 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.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