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