mutex.h revision 01ae5808367e641a983e3f8bb82b3e0d364cd03e
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
3181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#define ART_USE_FUTEXES 0
328daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
3366aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers// Currently Darwin doesn't support locks with timeouts.
3466aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#if !defined(__APPLE__)
3566aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#define HAVE_TIMED_RWLOCK 1
3666aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#else
3766aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#define HAVE_TIMED_RWLOCK 0
3866aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#endif
3966aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers
408daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesnamespace art {
418daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
4225fd14b87cced64a179dee885573113be5e11944Ian Rogersconst bool kDebugLocking = kIsDebugBuild;
4325fd14b87cced64a179dee885573113be5e11944Ian Rogers
4400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Base class for all Mutex implementations
4500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass BaseMutex {
4600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
4700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  const std::string& GetName() const {
4800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return name_;
4900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
5000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
5100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsMutex() const { return false; }
5200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsReaderWriterMutex() const { return false; }
5300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
5400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers protected:
5500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  friend class ConditionVariable;
5600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
5781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  BaseMutex(const char* name, LockLevel level);
5800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual ~BaseMutex() {}
5981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void RegisterAsLocked(Thread* self);
6081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void RegisterAsUnlocked(Thread* self);
6181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void CheckSafeToWait(Thread* self);
6200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
6381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  const LockLevel level_;  // Support for lock hierarchy.
640a1038b0a30a52dff1a449a989825e808a83df80Elliott Hughes  const std::string name_;
6500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
6600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
6700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// A Mutex is used to achieve mutual exclusion between threads. A Mutex can be used to gain
6800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// exclusive access to what it guards. A Mutex can be in one of two states:
6900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Free - not owned by any thread,
7000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Exclusive - owned by a single thread.
7100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
7200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// The effect of locking and unlocking operations on the state is:
7300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// State     | ExclusiveLock | ExclusiveUnlock
7400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// -------------------------------------------
7500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Free      | Exclusive     | error
7600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Exclusive | Block*        | Free
7700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// * Mutex is not reentrant and so an attempt to ExclusiveLock on the same thread will result in
7800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//   an error. Being non-reentrant simplifies Waiting on ConditionVariables.
7901ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogersstd::ostream& operator<<(std::ostream& os, const Mutex& mu);
8000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE Mutex : public BaseMutex {
8100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
8281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit Mutex(const char* name, LockLevel level = kDefaultMutexLevel, bool recursive = false);
8300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~Mutex();
8400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
8500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsMutex() const { return true; }
8600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
8700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until mutex is free then acquire exclusive access.
8881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ExclusiveLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION();
8981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void Lock(Thread* self) EXCLUSIVE_LOCK_FUNCTION() {  ExclusiveLock(self); }
9000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
9100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Returns true if acquires exclusive access, false otherwise.
9281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool ExclusiveTryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true);
9381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool TryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true) { return ExclusiveTryLock(self); }
9400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
9500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release exclusive access.
9681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ExclusiveUnlock(Thread* self) UNLOCK_FUNCTION();
9781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void Unlock(Thread* self) UNLOCK_FUNCTION() {  ExclusiveUnlock(self); }
9800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
9900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Is the current thread the exclusive holder of the Mutex.
10081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool IsExclusiveHeld(const Thread* self) const;
1018daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
10200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert that the Mutex is exclusively held by the current thread.
10381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertExclusiveHeld(const Thread* self) {
10425fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
10501ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(IsExclusiveHeld(self)) << *this;
10600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
10700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
10881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertHeld(const Thread* self) { AssertExclusiveHeld(self); }
10981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertHeld() { AssertExclusiveHeld(Thread::Current()); }
11000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
11100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert that the Mutex is not held by the current thread.
11281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotHeldExclusive(const Thread* self) {
11325fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
11401ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(!IsExclusiveHeld(self)) << *this;
11500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
11600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
11781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotHeld(const Thread* self) { AssertNotHeldExclusive(self); }
11800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
11900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Id associated with exclusive owner.
12000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  uint64_t GetExclusiveOwnerTid() const;
12100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
12200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Returns how many times this Mutex has been locked, it is better to use AssertHeld/NotHeld.
12300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  unsigned int GetDepth() const {
12400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return recursion_count_;
12500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
12600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
12701ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers  std::string Dump() const;
12801ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers
12900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
13000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  pthread_mutex_t mutex_;
13100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  const bool recursive_;  // Can the lock be recursively held?
13200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  unsigned int recursion_count_;
133f1498437b0d6beb9f4f91980b98cbeb0b5c773ceElliott Hughes  friend class ConditionVariable;
1343efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes  friend class MutexTester;
1358daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  DISALLOW_COPY_AND_ASSIGN(Mutex);
1368daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes};
1378daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
13800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// A ReaderWriterMutex is used to achieve mutual exclusion between threads, similar to a Mutex.
13900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Unlike a Mutex a ReaderWriterMutex can be used to gain exclusive (writer) or shared (reader)
14000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// access to what it guards. A flaw in relation to a Mutex is that it cannot be used with a
14100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// condition variable. A ReaderWriterMutex can be in one of three states:
14200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Free - not owned by any thread,
14300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Exclusive - owned by a single thread,
14400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Shared(n) - shared amongst n threads.
14500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
14600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// The effect of locking and unlocking operations on the state is:
14700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
14800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// State     | ExclusiveLock | ExclusiveUnlock | SharedLock       | SharedUnlock
14900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// ----------------------------------------------------------------------------
15000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Free      | Exclusive     | error           | SharedLock(1)    | error
15100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Exclusive | Block         | Free            | Block            | error
15200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Shared(n) | Block         | error           | SharedLock(n+1)* | Shared(n-1) or Free
15300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// * for large values of n the SharedLock may block.
15401ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogersstd::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu);
15500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE ReaderWriterMutex : public BaseMutex {
1568daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes public:
15781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit ReaderWriterMutex(const char* name, LockLevel level = kDefaultMutexLevel);
15800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~ReaderWriterMutex();
15900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
16000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsReaderWriterMutex() const { return true; }
16100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
16200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until ReaderWriterMutex is free then acquire exclusive access.
16381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ExclusiveLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION();
16481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void WriterLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION() {  ExclusiveLock(self); }
16500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
16600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release exclusive access.
16781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ExclusiveUnlock(Thread* self) UNLOCK_FUNCTION();
16881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void WriterUnlock(Thread* self) UNLOCK_FUNCTION() {  ExclusiveUnlock(self); }
16900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
17000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until ReaderWriterMutex is free and acquire exclusive access. Returns true on success
17100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // or false if timeout is reached.
17266aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#if HAVE_TIMED_RWLOCK
17381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool ExclusiveLockWithTimeout(Thread* self, const timespec& abs_timeout)
17481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      EXCLUSIVE_TRYLOCK_FUNCTION(true);
17566aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#endif
17600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
17700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until ReaderWriterMutex is shared or free then acquire a share on the access.
17881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void SharedLock(Thread* self) SHARED_LOCK_FUNCTION();
17981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ReaderLock(Thread* self) SHARED_LOCK_FUNCTION() { SharedLock(self); }
18000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
18100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Try to acquire share of ReaderWriterMutex.
18281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool SharedTryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true);
18300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
18400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release a share of the access.
18581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void SharedUnlock(Thread* self) UNLOCK_FUNCTION();
18681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ReaderUnlock(Thread* self) UNLOCK_FUNCTION() { SharedUnlock(self); }
18700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
18800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Is the current thread the exclusive holder of the ReaderWriterMutex.
18981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool IsExclusiveHeld(const Thread* self) const;
19000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
19100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread has exclusive access to the ReaderWriterMutex.
19281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertExclusiveHeld(const Thread* self) {
19325fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
19401ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(IsExclusiveHeld(self)) << *this;
19500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
1968daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  }
19781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertWriterHeld(const Thread* self) { AssertExclusiveHeld(self); }
1988daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
19900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread doesn't have exclusive access to the ReaderWriterMutex.
20081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotExclusiveHeld(const Thread* self) {
20125fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
20281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      CHECK(!IsExclusiveHeld(self));
20300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
20400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
20581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotWriterHeld(const Thread* self) { AssertNotExclusiveHeld(self); }
20600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
20700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Is the current thread a shared holder of the ReaderWriterMutex.
20881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool IsSharedHeld(const Thread* self) const;
20900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
21000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread has shared access to the ReaderWriterMutex.
21181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertSharedHeld(const Thread* self) {
21225fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
21301ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(IsSharedHeld(self)) << *this;
21400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
2158daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  }
21681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertReaderHeld(const Thread* self) { AssertSharedHeld(self); }
2178daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
21800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread doesn't hold this ReaderWriterMutex either in shared or exclusive
21900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // mode.
22081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotHeld(const Thread* self) {
22125fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
22201ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(!IsSharedHeld(self)) << *this;
22300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
22400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
22500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
22600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Id associated with exclusive owner.
22700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  uint64_t GetExclusiveOwnerTid() const;
22881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
22901ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers  std::string Dump() const;
23001ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers
2318daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes private:
23281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#if ART_USE_FUTEXES
23381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  // -1 implies held exclusive, +ve shared held by state_ many owners.
23481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  volatile int32_t state_;
23581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  // Exclusive owner.
23681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  volatile uint64_t exclusive_owner_;
23781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  // Pending readers.
23881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  volatile int32_t num_pending_readers_;
23981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  // Pending writers.
24081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  volatile int32_t num_pending_writers_;
24181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#else
24200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  pthread_rwlock_t rwlock_;
24381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#endif
24400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  friend class MutexTester;
24500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(ReaderWriterMutex);
2468daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes};
2478daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
24800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// ConditionVariables allow threads to queue and sleep. Threads may then be resumed individually
24900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// (Signal) or all at once (Broadcast).
2505f79133a435ebcb20000370d56046fe01201dd80Elliott Hughesclass ConditionVariable {
2515f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes public:
252a51a3dd5603daf3d368b7735067e1d9eb54c4c40Elliott Hughes  explicit ConditionVariable(const std::string& name);
2535f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  ~ConditionVariable();
2545f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
2555f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  void Broadcast();
2565f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  void Signal();
25781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void Wait(Thread* self, Mutex& mutex);
25881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void TimedWait(Thread* self, Mutex& mutex, const timespec& ts);
2595f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
2605f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes private:
2615f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  pthread_cond_t cond_;
2625f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  std::string name_;
2635f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
2645f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes};
2655f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
26600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a regular Mutex that acquires mu upon construction and releases it
26700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// upon destruction.
26800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE MutexLock {
26900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
27081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit MutexLock(Thread* self, Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : self_(self), mu_(mu) {
27181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveLock(self_);
27281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  }
27381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
27481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit MutexLock(Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : self_(Thread::Current()), mu_(mu) {
27581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveLock(self_);
27600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
27700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
27800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~MutexLock() UNLOCK_FUNCTION() {
27981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveUnlock(self_);
28000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
28100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
28200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
28381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  Thread* const self_;
28400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Mutex& mu_;
28500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(MutexLock);
28600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
28700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "MutexLock (lock);" instead of "MutexLock mu(lock)".
28800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_declaration_missing_variable_name)
28900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
29000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a ReaderWriterMutex that acquires read access to mu upon
29100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and releases it upon destruction.
29200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE ReaderMutexLock {
29300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
29481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit ReaderMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
29581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      self_(self), mu_(mu) {
29681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.SharedLock(self_);
29781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  }
29881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
29981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit ReaderMutexLock(ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
30081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      self_(Thread::Current()), mu_(mu) {
30181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.SharedLock(self_);
30200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
30300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
30400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~ReaderMutexLock() UNLOCK_FUNCTION() {
30581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.SharedUnlock(self_);
30600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
30700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
30800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
30981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  Thread* const self_;
31000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ReaderWriterMutex& mu_;
31100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(ReaderMutexLock);
31200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
31300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "ReaderMutexLock (lock);" instead of
31400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "ReaderMutexLock mu(lock)".
31500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define ReaderMutexLock(x) COMPILE_ASSERT(0, reader_mutex_lock_declaration_missing_variable_name)
31600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
31700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a ReaderWriterMutex that acquires write access to mu upon
31800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and releases it upon destruction.
31900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE WriterMutexLock {
32000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
32181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit WriterMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
32281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      self_(self), mu_(mu) {
32381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveLock(self_);
32481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  }
32581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
32681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit WriterMutexLock(ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
32781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      self_(Thread::Current()), mu_(mu) {
32881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveLock(self_);
32900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
33000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
33100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~WriterMutexLock() UNLOCK_FUNCTION() {
33281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveUnlock(self_);
33300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
33400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
33500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
33681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  Thread* self_;
33700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ReaderWriterMutex& mu_;
33800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(WriterMutexLock);
33900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
34000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "WriterMutexLock (lock);" instead of
34100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "WriterMutexLock mu(lock)".
34200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define WriterMutexLock(x) COMPILE_ASSERT(0, writer_mutex_lock_declaration_missing_variable_name)
34300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
3448daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}  // namespace art
3458daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
3468daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#endif  // ART_SRC_MUTEX_H_
347