Home | History | Annotate | Download | only in base
      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 
     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   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 nullptr;
    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.
    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, RecursiveLockWait::Callback,
    124                                              &state);
    125   ASSERT_EQ(0, pthread_create_result);
    126 
    127   state.cv.Wait(Thread::Current());
    128 
    129   state.mu.Unlock(Thread::Current());
    130   state.mu.Unlock(Thread::Current());
    131   EXPECT_EQ(pthread_join(pthread, nullptr), 0);
    132 }
    133 
    134 // This ensures we don't hang when waiting on a recursively locked mutex,
    135 // which is not supported with bare pthread_mutex_t.
    136 TEST_F(MutexTest, RecursiveLockWait) {
    137   RecursiveLockWaitTest();
    138 }
    139 
    140 TEST_F(MutexTest, SharedLockUnlock) {
    141   ReaderWriterMutex mu("test rwmutex");
    142   mu.AssertNotHeld(Thread::Current());
    143   mu.AssertNotExclusiveHeld(Thread::Current());
    144   mu.SharedLock(Thread::Current());
    145   mu.AssertSharedHeld(Thread::Current());
    146   mu.AssertNotExclusiveHeld(Thread::Current());
    147   mu.SharedUnlock(Thread::Current());
    148   mu.AssertNotHeld(Thread::Current());
    149 }
    150 
    151 TEST_F(MutexTest, ExclusiveLockUnlock) {
    152   ReaderWriterMutex mu("test rwmutex");
    153   mu.AssertNotHeld(Thread::Current());
    154   mu.ExclusiveLock(Thread::Current());
    155   mu.AssertSharedHeld(Thread::Current());
    156   mu.AssertExclusiveHeld(Thread::Current());
    157   mu.ExclusiveUnlock(Thread::Current());
    158   mu.AssertNotHeld(Thread::Current());
    159 }
    160 
    161 // GCC has trouble with our mutex tests, so we have to turn off thread safety analysis.
    162 static void SharedTryLockUnlockTest() NO_THREAD_SAFETY_ANALYSIS {
    163   ReaderWriterMutex mu("test rwmutex");
    164   mu.AssertNotHeld(Thread::Current());
    165   ASSERT_TRUE(mu.SharedTryLock(Thread::Current()));
    166   mu.AssertSharedHeld(Thread::Current());
    167   mu.SharedUnlock(Thread::Current());
    168   mu.AssertNotHeld(Thread::Current());
    169 }
    170 
    171 TEST_F(MutexTest, SharedTryLockUnlock) {
    172   SharedTryLockUnlockTest();
    173 }
    174 
    175 }  // namespace art
    176