mutex.h revision ab47016374d340011680e9cd970ee7d6225d6704
18daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes/*
28daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Copyright (C) 2011 The Android Open Source Project
38daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *
48daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
58daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * you may not use this file except in compliance with the License.
68daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * You may obtain a copy of the License at
78daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *
88daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
98daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *
108daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Unless required by applicable law or agreed to in writing, software
118daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
128daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * See the License for the specific language governing permissions and
148daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * limitations under the License.
158daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes */
168daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
178daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#ifndef ART_SRC_MUTEX_H_
188daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#define ART_SRC_MUTEX_H_
198daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
208daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include <pthread.h>
21cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom#include <stdint.h>
22ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes
23ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes#include <iosfwd>
248daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include <string>
258daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
2600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "globals.h"
2781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#include "locks.h"
288daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include "macros.h"
2981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#include "thread.h"
3081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
31ab47016374d340011680e9cd970ee7d6225d6704Ian Rogers#if defined(__APPLE__)
3281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#define ART_USE_FUTEXES 0
33ab47016374d340011680e9cd970ee7d6225d6704Ian Rogers#else
34ab47016374d340011680e9cd970ee7d6225d6704Ian Rogers#define ART_USE_FUTEXES 1
35ab47016374d340011680e9cd970ee7d6225d6704Ian Rogers#endif
368daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
3766aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers// Currently Darwin doesn't support locks with timeouts.
3866aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#if !defined(__APPLE__)
3966aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#define HAVE_TIMED_RWLOCK 1
4066aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#else
4166aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#define HAVE_TIMED_RWLOCK 0
4266aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#endif
4366aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers
448daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesnamespace art {
458daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
4625fd14b87cced64a179dee885573113be5e11944Ian Rogersconst bool kDebugLocking = kIsDebugBuild;
4725fd14b87cced64a179dee885573113be5e11944Ian Rogers
4800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Base class for all Mutex implementations
4900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass BaseMutex {
5000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
5100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  const std::string& GetName() const {
5200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return name_;
5300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
5400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
5500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsMutex() const { return false; }
5600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsReaderWriterMutex() const { return false; }
5700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
5800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers protected:
5900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  friend class ConditionVariable;
6000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
6181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  BaseMutex(const char* name, LockLevel level);
6200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual ~BaseMutex() {}
6381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void RegisterAsLocked(Thread* self);
6481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void RegisterAsUnlocked(Thread* self);
6581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void CheckSafeToWait(Thread* self);
6600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
6781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  const LockLevel level_;  // Support for lock hierarchy.
680a1038b0a30a52dff1a449a989825e808a83df80Elliott Hughes  const std::string name_;
6900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
7000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
7100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// A Mutex is used to achieve mutual exclusion between threads. A Mutex can be used to gain
7200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// exclusive access to what it guards. A Mutex can be in one of two states:
7300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Free - not owned by any thread,
7400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Exclusive - owned by a single thread.
7500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
7600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// The effect of locking and unlocking operations on the state is:
7700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// State     | ExclusiveLock | ExclusiveUnlock
7800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// -------------------------------------------
7900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Free      | Exclusive     | error
8000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Exclusive | Block*        | Free
8100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// * Mutex is not reentrant and so an attempt to ExclusiveLock on the same thread will result in
8200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//   an error. Being non-reentrant simplifies Waiting on ConditionVariables.
8301ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogersstd::ostream& operator<<(std::ostream& os, const Mutex& mu);
8400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE Mutex : public BaseMutex {
8500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
8681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit Mutex(const char* name, LockLevel level = kDefaultMutexLevel, bool recursive = false);
8700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~Mutex();
8800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
8900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsMutex() const { return true; }
9000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
9100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until mutex is free then acquire exclusive access.
9281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ExclusiveLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION();
9381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void Lock(Thread* self) EXCLUSIVE_LOCK_FUNCTION() {  ExclusiveLock(self); }
9400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
9500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Returns true if acquires exclusive access, false otherwise.
9681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool ExclusiveTryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true);
9781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool TryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true) { return ExclusiveTryLock(self); }
9800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
9900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release exclusive access.
10081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ExclusiveUnlock(Thread* self) UNLOCK_FUNCTION();
10181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void Unlock(Thread* self) UNLOCK_FUNCTION() {  ExclusiveUnlock(self); }
10200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
10300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Is the current thread the exclusive holder of the Mutex.
10481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool IsExclusiveHeld(const Thread* self) const;
1058daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
10600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert that the Mutex is exclusively held by the current thread.
10781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertExclusiveHeld(const Thread* self) {
10825fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
10901ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(IsExclusiveHeld(self)) << *this;
11000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
11100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
11281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertHeld(const Thread* self) { AssertExclusiveHeld(self); }
11381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertHeld() { AssertExclusiveHeld(Thread::Current()); }
11400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
11500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert that the Mutex is not held by the current thread.
11681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotHeldExclusive(const Thread* self) {
11725fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
11801ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(!IsExclusiveHeld(self)) << *this;
11900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
12000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
12181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotHeld(const Thread* self) { AssertNotHeldExclusive(self); }
12200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
12300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Id associated with exclusive owner.
12400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  uint64_t GetExclusiveOwnerTid() const;
12500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
12600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Returns how many times this Mutex has been locked, it is better to use AssertHeld/NotHeld.
12700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  unsigned int GetDepth() const {
12800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return recursion_count_;
12900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
13000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
13101ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers  std::string Dump() const;
13201ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers
13300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
13400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  pthread_mutex_t mutex_;
13500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  const bool recursive_;  // Can the lock be recursively held?
13600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  unsigned int recursion_count_;
137f1498437b0d6beb9f4f91980b98cbeb0b5c773ceElliott Hughes  friend class ConditionVariable;
1383efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes  friend class MutexTester;
1398daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  DISALLOW_COPY_AND_ASSIGN(Mutex);
1408daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes};
1418daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
14200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// A ReaderWriterMutex is used to achieve mutual exclusion between threads, similar to a Mutex.
14300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Unlike a Mutex a ReaderWriterMutex can be used to gain exclusive (writer) or shared (reader)
14400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// access to what it guards. A flaw in relation to a Mutex is that it cannot be used with a
14500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// condition variable. A ReaderWriterMutex can be in one of three states:
14600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Free - not owned by any thread,
14700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Exclusive - owned by a single thread,
14800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Shared(n) - shared amongst n threads.
14900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
15000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// The effect of locking and unlocking operations on the state is:
15100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
15200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// State     | ExclusiveLock | ExclusiveUnlock | SharedLock       | SharedUnlock
15300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// ----------------------------------------------------------------------------
15400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Free      | Exclusive     | error           | SharedLock(1)    | error
15500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Exclusive | Block         | Free            | Block            | error
15600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Shared(n) | Block         | error           | SharedLock(n+1)* | Shared(n-1) or Free
15700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// * for large values of n the SharedLock may block.
15801ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogersstd::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu);
15900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE ReaderWriterMutex : public BaseMutex {
1608daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes public:
16181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit ReaderWriterMutex(const char* name, LockLevel level = kDefaultMutexLevel);
16200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~ReaderWriterMutex();
16300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
16400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsReaderWriterMutex() const { return true; }
16500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
16600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until ReaderWriterMutex is free then acquire exclusive access.
16781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ExclusiveLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION();
16881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void WriterLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION() {  ExclusiveLock(self); }
16900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
17000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release exclusive access.
17181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ExclusiveUnlock(Thread* self) UNLOCK_FUNCTION();
17281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void WriterUnlock(Thread* self) UNLOCK_FUNCTION() {  ExclusiveUnlock(self); }
17300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
17400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until ReaderWriterMutex is free and acquire exclusive access. Returns true on success
17500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // or false if timeout is reached.
17666aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#if HAVE_TIMED_RWLOCK
17781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool ExclusiveLockWithTimeout(Thread* self, const timespec& abs_timeout)
17881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      EXCLUSIVE_TRYLOCK_FUNCTION(true);
17966aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#endif
18000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
18100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until ReaderWriterMutex is shared or free then acquire a share on the access.
18281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void SharedLock(Thread* self) SHARED_LOCK_FUNCTION();
18381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ReaderLock(Thread* self) SHARED_LOCK_FUNCTION() { SharedLock(self); }
18400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
18500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Try to acquire share of ReaderWriterMutex.
18681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool SharedTryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true);
18700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
18800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release a share of the access.
18981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void SharedUnlock(Thread* self) UNLOCK_FUNCTION();
19081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ReaderUnlock(Thread* self) UNLOCK_FUNCTION() { SharedUnlock(self); }
19100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
19200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Is the current thread the exclusive holder of the ReaderWriterMutex.
19381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool IsExclusiveHeld(const Thread* self) const;
19400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
19500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread has exclusive access to the ReaderWriterMutex.
19681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertExclusiveHeld(const Thread* self) {
19725fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
19801ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(IsExclusiveHeld(self)) << *this;
19900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
2008daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  }
20181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertWriterHeld(const Thread* self) { AssertExclusiveHeld(self); }
2028daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
20300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread doesn't have exclusive access to the ReaderWriterMutex.
20481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotExclusiveHeld(const Thread* self) {
20525fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
20681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      CHECK(!IsExclusiveHeld(self));
20700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
20800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
20981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotWriterHeld(const Thread* self) { AssertNotExclusiveHeld(self); }
21000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
21100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Is the current thread a shared holder of the ReaderWriterMutex.
21281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool IsSharedHeld(const Thread* self) const;
21300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
21400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread has shared access to the ReaderWriterMutex.
21581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertSharedHeld(const Thread* self) {
21625fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
21701ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(IsSharedHeld(self)) << *this;
21800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
2198daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  }
22081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertReaderHeld(const Thread* self) { AssertSharedHeld(self); }
2218daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
22200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread doesn't hold this ReaderWriterMutex either in shared or exclusive
22300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // mode.
22481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotHeld(const Thread* self) {
22525fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
22601ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(!IsSharedHeld(self)) << *this;
22700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
22800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
22900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
23000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Id associated with exclusive owner.
23100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  uint64_t GetExclusiveOwnerTid() const;
23281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
23301ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers  std::string Dump() const;
23401ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers
2358daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes private:
23681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#if ART_USE_FUTEXES
23781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  // -1 implies held exclusive, +ve shared held by state_ many owners.
23881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  volatile int32_t state_;
23981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  // Exclusive owner.
24081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  volatile uint64_t exclusive_owner_;
24181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  // Pending readers.
24281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  volatile int32_t num_pending_readers_;
24381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  // Pending writers.
24481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  volatile int32_t num_pending_writers_;
24581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#else
24600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  pthread_rwlock_t rwlock_;
24781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#endif
24800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  friend class MutexTester;
24900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(ReaderWriterMutex);
2508daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes};
2518daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
25200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// ConditionVariables allow threads to queue and sleep. Threads may then be resumed individually
25300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// (Signal) or all at once (Broadcast).
2545f79133a435ebcb20000370d56046fe01201dd80Elliott Hughesclass ConditionVariable {
2555f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes public:
256a51a3dd5603daf3d368b7735067e1d9eb54c4c40Elliott Hughes  explicit ConditionVariable(const std::string& name);
2575f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  ~ConditionVariable();
2585f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
2595f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  void Broadcast();
2605f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  void Signal();
26181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void Wait(Thread* self, Mutex& mutex);
26281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void TimedWait(Thread* self, Mutex& mutex, const timespec& ts);
2635f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
2645f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes private:
2655f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  pthread_cond_t cond_;
2665f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  std::string name_;
2675f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
2685f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes};
2695f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
27000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a regular Mutex that acquires mu upon construction and releases it
27100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// upon destruction.
27200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE MutexLock {
27300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
27481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit MutexLock(Thread* self, Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : self_(self), mu_(mu) {
27581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveLock(self_);
27681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  }
27781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
27881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit MutexLock(Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : self_(Thread::Current()), mu_(mu) {
27981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveLock(self_);
28000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
28100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
28200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~MutexLock() UNLOCK_FUNCTION() {
28381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveUnlock(self_);
28400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
28500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
28600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
28781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  Thread* const self_;
28800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Mutex& mu_;
28900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(MutexLock);
29000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
29100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "MutexLock (lock);" instead of "MutexLock mu(lock)".
29200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_declaration_missing_variable_name)
29300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
29400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a ReaderWriterMutex that acquires read access to mu upon
29500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and releases it upon destruction.
29600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE ReaderMutexLock {
29700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
29881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit ReaderMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
29981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      self_(self), mu_(mu) {
30081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.SharedLock(self_);
30181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  }
30281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
30381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit ReaderMutexLock(ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
30481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      self_(Thread::Current()), mu_(mu) {
30581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.SharedLock(self_);
30600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
30700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
30800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~ReaderMutexLock() UNLOCK_FUNCTION() {
30981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.SharedUnlock(self_);
31000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
31100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
31200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
31381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  Thread* const self_;
31400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ReaderWriterMutex& mu_;
31500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(ReaderMutexLock);
31600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
31700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "ReaderMutexLock (lock);" instead of
31800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "ReaderMutexLock mu(lock)".
31900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define ReaderMutexLock(x) COMPILE_ASSERT(0, reader_mutex_lock_declaration_missing_variable_name)
32000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
32100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a ReaderWriterMutex that acquires write access to mu upon
32200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and releases it upon destruction.
32300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE WriterMutexLock {
32400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
32581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit WriterMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
32681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      self_(self), mu_(mu) {
32781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveLock(self_);
32881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  }
32981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
33081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit WriterMutexLock(ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
33181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      self_(Thread::Current()), mu_(mu) {
33281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveLock(self_);
33300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
33400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
33500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~WriterMutexLock() UNLOCK_FUNCTION() {
33681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveUnlock(self_);
33700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
33800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
33900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
34081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  Thread* self_;
34100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ReaderWriterMutex& mu_;
34200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(WriterMutexLock);
34300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
34400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "WriterMutexLock (lock);" instead of
34500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "WriterMutexLock mu(lock)".
34600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define WriterMutexLock(x) COMPILE_ASSERT(0, writer_mutex_lock_declaration_missing_variable_name)
34700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
3488daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}  // namespace art
3498daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
3508daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#endif  // ART_SRC_MUTEX_H_
351