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