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