12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/* 22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2012 The Android Open Source Project 32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License. 62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at 72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software 112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and 142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License. 152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */ 16cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom 17cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom#include "mutex.h" 18cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom 19a1ce1fef2d49d1d537776a5308ace7102a815fe5Brian Carlstrom#include "common_runtime_test.h" 20e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "thread-inl.h" 21cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom 22cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstromnamespace art { 23cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom 24a1ce1fef2d49d1d537776a5308ace7102a815fe5Brian Carlstromclass MutexTest : public CommonRuntimeTest {}; 2592c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom 263efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughesstruct MutexTester { 273efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes static void AssertDepth(Mutex& mu, uint32_t expected_depth) { 283efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes ASSERT_EQ(expected_depth, mu.GetDepth()); 29f1498437b0d6beb9f4f91980b98cbeb0b5c773ceElliott Hughes 30f1498437b0d6beb9f4f91980b98cbeb0b5c773ceElliott Hughes // This test is single-threaded, so we also know _who_ should hold the lock. 31f1498437b0d6beb9f4f91980b98cbeb0b5c773ceElliott Hughes if (expected_depth == 0) { 3281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.AssertNotHeld(Thread::Current()); 33f1498437b0d6beb9f4f91980b98cbeb0b5c773ceElliott Hughes } else { 3481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.AssertHeld(Thread::Current()); 35f1498437b0d6beb9f4f91980b98cbeb0b5c773ceElliott Hughes } 363efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes } 373efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes}; 383efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes 3992c9a352f7b52abbb2c75c63301e3552b3d30b75Brian CarlstromTEST_F(MutexTest, LockUnlock) { 40cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom Mutex mu("test mutex"); 413efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes MutexTester::AssertDepth(mu, 0U); 4281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.Lock(Thread::Current()); 433efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes MutexTester::AssertDepth(mu, 1U); 4481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.Unlock(Thread::Current()); 453efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes MutexTester::AssertDepth(mu, 0U); 46cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom} 47cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom 4872d63d4bc4387bd636315f16dc81cf4874905569Elliott Hughes// GCC has trouble with our mutex tests, so we have to turn off thread safety analysis. 49814140550e9dee025b0007293d1763518fdd5ef3Elliott Hughesstatic void TryLockUnlockTest() NO_THREAD_SAFETY_ANALYSIS { 50cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom Mutex mu("test mutex"); 513efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes MutexTester::AssertDepth(mu, 0U); 5281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers ASSERT_TRUE(mu.TryLock(Thread::Current())); 53814140550e9dee025b0007293d1763518fdd5ef3Elliott Hughes MutexTester::AssertDepth(mu, 1U); 5481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.Unlock(Thread::Current()); 55814140550e9dee025b0007293d1763518fdd5ef3Elliott Hughes MutexTester::AssertDepth(mu, 0U); 56814140550e9dee025b0007293d1763518fdd5ef3Elliott Hughes} 57814140550e9dee025b0007293d1763518fdd5ef3Elliott Hughes 5892c9a352f7b52abbb2c75c63301e3552b3d30b75Brian CarlstromTEST_F(MutexTest, TryLockUnlock) { 59814140550e9dee025b0007293d1763518fdd5ef3Elliott Hughes TryLockUnlockTest(); 60cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom} 61cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom 6272d63d4bc4387bd636315f16dc81cf4874905569Elliott Hughes// GCC has trouble with our mutex tests, so we have to turn off thread safety analysis. 63f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughesstatic void RecursiveLockUnlockTest() NO_THREAD_SAFETY_ANALYSIS { 6400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers Mutex mu("test mutex", kDefaultMutexLevel, true); 653efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes MutexTester::AssertDepth(mu, 0U); 6681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.Lock(Thread::Current()); 673efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes MutexTester::AssertDepth(mu, 1U); 6881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.Lock(Thread::Current()); 693efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes MutexTester::AssertDepth(mu, 2U); 7081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.Unlock(Thread::Current()); 713efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes MutexTester::AssertDepth(mu, 1U); 7281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.Unlock(Thread::Current()); 733efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes MutexTester::AssertDepth(mu, 0U); 74cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom} 75cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom 7692c9a352f7b52abbb2c75c63301e3552b3d30b75Brian CarlstromTEST_F(MutexTest, RecursiveLockUnlock) { 77f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes RecursiveLockUnlockTest(); 78f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes} 79f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes 8072d63d4bc4387bd636315f16dc81cf4874905569Elliott Hughes// GCC has trouble with our mutex tests, so we have to turn off thread safety analysis. 81f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughesstatic void RecursiveTryLockUnlockTest() NO_THREAD_SAFETY_ANALYSIS { 8200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers Mutex mu("test mutex", kDefaultMutexLevel, true); 833efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes MutexTester::AssertDepth(mu, 0U); 8481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers ASSERT_TRUE(mu.TryLock(Thread::Current())); 853efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes MutexTester::AssertDepth(mu, 1U); 8681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers ASSERT_TRUE(mu.TryLock(Thread::Current())); 873efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes MutexTester::AssertDepth(mu, 2U); 8881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.Unlock(Thread::Current()); 893efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes MutexTester::AssertDepth(mu, 1U); 9081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.Unlock(Thread::Current()); 913efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes MutexTester::AssertDepth(mu, 0U); 92cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom} 93cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom 9492c9a352f7b52abbb2c75c63301e3552b3d30b75Brian CarlstromTEST_F(MutexTest, RecursiveTryLockUnlock) { 95f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes RecursiveTryLockUnlockTest(); 96f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes} 97f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes 9892c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom 9992c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstromstruct RecursiveLockWait { 10000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers explicit RecursiveLockWait() 101c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers : mu("test mutex", kDefaultMutexLevel, true), cv("test condition variable", mu) { 10200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 10392c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom 10492c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom Mutex mu; 10592c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom ConditionVariable cv; 10692c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom}; 10792c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom 10890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartierstatic void* RecursiveLockWaitCallback(void* arg) { 10990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier RecursiveLockWait* state = reinterpret_cast<RecursiveLockWait*>(arg); 11090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier state->mu.Lock(Thread::Current()); 11190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier state->cv.Signal(Thread::Current()); 11290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier state->mu.Unlock(Thread::Current()); 11390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier return nullptr; 11490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier} 11590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier 11692c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom// GCC has trouble with our mutex tests, so we have to turn off thread safety analysis. 11792c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstromstatic void RecursiveLockWaitTest() NO_THREAD_SAFETY_ANALYSIS { 11892c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom RecursiveLockWait state; 11981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers state.mu.Lock(Thread::Current()); 12081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers state.mu.Lock(Thread::Current()); 12192c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom 12292c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom pthread_t pthread; 12390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier int pthread_create_result = pthread_create(&pthread, nullptr, RecursiveLockWaitCallback, &state); 12492c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom ASSERT_EQ(0, pthread_create_result); 12592c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom 126c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers state.cv.Wait(Thread::Current()); 12792c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom 12881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers state.mu.Unlock(Thread::Current()); 12981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers state.mu.Unlock(Thread::Current()); 1302cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier EXPECT_EQ(pthread_join(pthread, nullptr), 0); 13192c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom} 13292c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom 13392c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom// This ensures we don't hang when waiting on a recursively locked mutex, 13492c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom// which is not supported with bare pthread_mutex_t. 13592c9a352f7b52abbb2c75c63301e3552b3d30b75Brian CarlstromTEST_F(MutexTest, RecursiveLockWait) { 13692c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom RecursiveLockWaitTest(); 13792c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom} 13892c9a352f7b52abbb2c75c63301e3552b3d30b75Brian Carlstrom 13900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan RogersTEST_F(MutexTest, SharedLockUnlock) { 14000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ReaderWriterMutex mu("test rwmutex"); 14181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.AssertNotHeld(Thread::Current()); 14281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.AssertNotExclusiveHeld(Thread::Current()); 14381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.SharedLock(Thread::Current()); 14481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.AssertSharedHeld(Thread::Current()); 14581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.AssertNotExclusiveHeld(Thread::Current()); 14681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.SharedUnlock(Thread::Current()); 14781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.AssertNotHeld(Thread::Current()); 14800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers} 14900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 15000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan RogersTEST_F(MutexTest, ExclusiveLockUnlock) { 15100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ReaderWriterMutex mu("test rwmutex"); 15281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.AssertNotHeld(Thread::Current()); 15381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.ExclusiveLock(Thread::Current()); 15481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.AssertSharedHeld(Thread::Current()); 15581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.AssertExclusiveHeld(Thread::Current()); 15681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.ExclusiveUnlock(Thread::Current()); 15781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.AssertNotHeld(Thread::Current()); 15800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers} 15900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 16000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// GCC has trouble with our mutex tests, so we have to turn off thread safety analysis. 16100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic void SharedTryLockUnlockTest() NO_THREAD_SAFETY_ANALYSIS { 16200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ReaderWriterMutex mu("test rwmutex"); 16381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.AssertNotHeld(Thread::Current()); 16481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers ASSERT_TRUE(mu.SharedTryLock(Thread::Current())); 16581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.AssertSharedHeld(Thread::Current()); 16681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.SharedUnlock(Thread::Current()); 16781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers mu.AssertNotHeld(Thread::Current()); 16800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers} 16900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 17000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan RogersTEST_F(MutexTest, SharedTryLockUnlock) { 17100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers SharedTryLockUnlockTest(); 17200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers} 17300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 174cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom} // namespace art 175