mutex.h revision 81d425b0b232962441616f8b14f73620bffef5e5
15ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov/*
25ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov * Copyright (C) 2011 The Android Open Source Project
35ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov *
45ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov * Licensed under the Apache License, Version 2.0 (the "License");
55ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov * you may not use this file except in compliance with the License.
65ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov * You may obtain a copy of the License at
75ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov *
85ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov *      http://www.apache.org/licenses/LICENSE-2.0
95ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov *
105ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov * Unless required by applicable law or agreed to in writing, software
115ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov * distributed under the License is distributed on an "AS IS" BASIS,
125ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov * See the License for the specific language governing permissions and
145ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov * limitations under the License.
155ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov */
165ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
175ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov#ifndef ART_SRC_MUTEX_H_
185ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov#define ART_SRC_MUTEX_H_
195ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
20c6ea7d00ad069a2736f603daa3d8eaa9a1f8ea11Andreas Gampe#include <pthread.h>
215ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov#include <stdint.h>
225ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
2309659c22dc2f2c85a0ade965d1fc5160944b8692Andreas Gampe#include <iosfwd>
245ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov#include <string>
255ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
26c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe#include "globals.h"
27c6ea7d00ad069a2736f603daa3d8eaa9a1f8ea11Andreas Gampe#include "locks.h"
28c6ea7d00ad069a2736f603daa3d8eaa9a1f8ea11Andreas Gampe#include "macros.h"
29c6ea7d00ad069a2736f603daa3d8eaa9a1f8ea11Andreas Gampe#include "thread.h"
30b486a98aadc95d80548953410cf23edba62259faAndreas Gampe
315ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov#define ART_USE_FUTEXES 0
325ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
335ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// Currently Darwin doesn't support locks with timeouts.
345ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov#if !defined(__APPLE__)
355ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov#define HAVE_TIMED_RWLOCK 1
365ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov#else
375ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov#define HAVE_TIMED_RWLOCK 0
385ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov#endif
395ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
405ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilovnamespace art {
415ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
425ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilovconst bool kDebugLocking = kIsDebugBuild;
435ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
445ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// Base class for all Mutex implementations
455ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilovclass BaseMutex {
465ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov public:
475ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  const std::string& GetName() const {
485ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    return name_;
4953463ba8717fc93379ebf2b0c04a9a2c85382973xueliang.zhong  }
505ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
51c032e74b57d31861b6bb55500016ebb5476eb142xueliang.zhong  virtual bool IsMutex() const { return false; }
525ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  virtual bool IsReaderWriterMutex() const { return false; }
535ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
545ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov protected:
555ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  friend class ConditionVariable;
56c032e74b57d31861b6bb55500016ebb5476eb142xueliang.zhong
575ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  BaseMutex(const char* name, LockLevel level);
585ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  virtual ~BaseMutex() {}
595ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void RegisterAsLocked(Thread* self);
600fb3719129098110a61f320cb47edf774166b602Artem Serov  void RegisterAsUnlocked(Thread* self);
610fb3719129098110a61f320cb47edf774166b602Artem Serov  void CheckSafeToWait(Thread* self);
620fb3719129098110a61f320cb47edf774166b602Artem Serov
635ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  const LockLevel level_;  // Support for lock hierarchy.
645ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  const std::string name_;
655ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov};
665ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
675ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// A Mutex is used to achieve mutual exclusion between threads. A Mutex can be used to gain
68ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko// exclusive access to what it guards. A Mutex can be in one of two states:
695ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// - Free - not owned by any thread,
705ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// - Exclusive - owned by a single thread.
715ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov//
725ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// The effect of locking and unlocking operations on the state is:
735ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// State     | ExclusiveLock | ExclusiveUnlock
745ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// -------------------------------------------
755ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// Free      | Exclusive     | error
765ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// Exclusive | Block*        | Free
775ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// * Mutex is not reentrant and so an attempt to ExclusiveLock on the same thread will result in
785ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov//   an error. Being non-reentrant simplifies Waiting on ConditionVariables.
795ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilovclass LOCKABLE Mutex : public BaseMutex {
805ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov public:
815ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  explicit Mutex(const char* name, LockLevel level = kDefaultMutexLevel, bool recursive = false);
825ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  ~Mutex();
835ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
845ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  virtual bool IsMutex() const { return true; }
855ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
865ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Block until mutex is free then acquire exclusive access.
87d4cc5b2127894475160b5d2bba9791dd21af5953Artem Serov  void ExclusiveLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION();
885ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void Lock(Thread* self) EXCLUSIVE_LOCK_FUNCTION() {  ExclusiveLock(self); }
895ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
905ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Returns true if acquires exclusive access, false otherwise.
915ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  bool ExclusiveTryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true);
925ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  bool TryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true) { return ExclusiveTryLock(self); }
935ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
945ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Release exclusive access.
955ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void ExclusiveUnlock(Thread* self) UNLOCK_FUNCTION();
965ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void Unlock(Thread* self) UNLOCK_FUNCTION() {  ExclusiveUnlock(self); }
975ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
985ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Is the current thread the exclusive holder of the Mutex.
995ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  bool IsExclusiveHeld(const Thread* self) const;
1005ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
101e7197bf7d58c705a048e13e241d7ca320502cd40Vladimir Marko  // Assert that the Mutex is exclusively held by the current thread.
1025ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void AssertExclusiveHeld(const Thread* self) {
103e7197bf7d58c705a048e13e241d7ca320502cd40Vladimir Marko    if (kDebugLocking) {
1045ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov      CHECK(IsExclusiveHeld(self));
1055ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    }
1065ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  }
1075ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void AssertHeld(const Thread* self) { AssertExclusiveHeld(self); }
1085ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void AssertHeld() { AssertExclusiveHeld(Thread::Current()); }
1095ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
1105ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Assert that the Mutex is not held by the current thread.
1115ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void AssertNotHeldExclusive(const Thread* self) {
1125ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    if (kDebugLocking) {
1135ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov      CHECK(!IsExclusiveHeld(self));
1145ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    }
1155ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  }
1165ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void AssertNotHeld(const Thread* self) { AssertNotHeldExclusive(self); }
1175ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
1185ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Id associated with exclusive owner.
1195ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  uint64_t GetExclusiveOwnerTid() const;
1205ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
1215ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Returns how many times this Mutex has been locked, it is better to use AssertHeld/NotHeld.
1225ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  unsigned int GetDepth() const {
1235ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    return recursion_count_;
1245ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  }
1255ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
1265ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov private:
1279cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain  pthread_mutex_t mutex_;
1289cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain  const bool recursive_;  // Can the lock be recursively held?
1290ebe0d83138bba1996e9c8007969b5381d972b32Vladimir Marko  unsigned int recursion_count_;
1309cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain  friend class ConditionVariable;
1319cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain  friend class MutexTester;
1329cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain  DISALLOW_COPY_AND_ASSIGN(Mutex);
1339cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain};
1340ebe0d83138bba1996e9c8007969b5381d972b32Vladimir Marko
1359cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain// A ReaderWriterMutex is used to achieve mutual exclusion between threads, similar to a Mutex.
1360ebe0d83138bba1996e9c8007969b5381d972b32Vladimir Marko// Unlike a Mutex a ReaderWriterMutex can be used to gain exclusive (writer) or shared (reader)
1370ebe0d83138bba1996e9c8007969b5381d972b32Vladimir Marko// access to what it guards. A flaw in relation to a Mutex is that it cannot be used with a
1380ebe0d83138bba1996e9c8007969b5381d972b32Vladimir Marko// condition variable. A ReaderWriterMutex can be in one of three states:
1399cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain// - Free - not owned by any thread,
1409cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain// - Exclusive - owned by a single thread,
1419cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain// - Shared(n) - shared amongst n threads.
1429cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain//
1439cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain// The effect of locking and unlocking operations on the state is:
1449cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain//
1459cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain// State     | ExclusiveLock | ExclusiveUnlock | SharedLock       | SharedUnlock
1469cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain// ----------------------------------------------------------------------------
1479cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain// Free      | Exclusive     | error           | SharedLock(1)    | error
1489cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain// Exclusive | Block         | Free            | Block            | error
1499cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain// Shared(n) | Block         | error           | SharedLock(n+1)* | Shared(n-1) or Free
1509cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain// * for large values of n the SharedLock may block.
1519cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillainclass LOCKABLE ReaderWriterMutex : public BaseMutex {
1520ebe0d83138bba1996e9c8007969b5381d972b32Vladimir Marko public:
1539cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain  explicit ReaderWriterMutex(const char* name, LockLevel level = kDefaultMutexLevel);
1549cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain  ~ReaderWriterMutex();
1559cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain
1569cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain  virtual bool IsReaderWriterMutex() const { return true; }
1570ebe0d83138bba1996e9c8007969b5381d972b32Vladimir Marko
1589cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain  // Block until ReaderWriterMutex is free then acquire exclusive access.
1590ebe0d83138bba1996e9c8007969b5381d972b32Vladimir Marko  void ExclusiveLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION();
1600ebe0d83138bba1996e9c8007969b5381d972b32Vladimir Marko  void WriterLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION() {  ExclusiveLock(self); }
1610ebe0d83138bba1996e9c8007969b5381d972b32Vladimir Marko
1629cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain  // Release exclusive access.
1639cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain  void ExclusiveUnlock(Thread* self) UNLOCK_FUNCTION();
1649cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain  void WriterUnlock(Thread* self) UNLOCK_FUNCTION() {  ExclusiveUnlock(self); }
1659cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain
1669cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain  // Block until ReaderWriterMutex is free and acquire exclusive access. Returns true on success
1679cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain  // or false if timeout is reached.
1689cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain#if HAVE_TIMED_RWLOCK
1699cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain  bool ExclusiveLockWithTimeout(Thread* self, const timespec& abs_timeout)
1709cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain      EXCLUSIVE_TRYLOCK_FUNCTION(true);
1715ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov#endif
1725ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
1735ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Block until ReaderWriterMutex is shared or free then acquire a share on the access.
1745ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void SharedLock(Thread* self) SHARED_LOCK_FUNCTION();
1755ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void ReaderLock(Thread* self) SHARED_LOCK_FUNCTION() { SharedLock(self); }
1765ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
1775ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Try to acquire share of ReaderWriterMutex.
1785ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  bool SharedTryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true);
1795ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
1805ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Release a share of the access.
1815ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void SharedUnlock(Thread* self) UNLOCK_FUNCTION();
1825ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void ReaderUnlock(Thread* self) UNLOCK_FUNCTION() { SharedUnlock(self); }
1835ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
1845ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Is the current thread the exclusive holder of the ReaderWriterMutex.
1855ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  bool IsExclusiveHeld(const Thread* self) const;
1865ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
1875ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Assert the current thread has exclusive access to the ReaderWriterMutex.
1885ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void AssertExclusiveHeld(const Thread* self) {
1895ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    if (kDebugLocking) {
1905ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov      CHECK(IsExclusiveHeld(self));
1910ebe0d83138bba1996e9c8007969b5381d972b32Vladimir Marko    }
1920ebe0d83138bba1996e9c8007969b5381d972b32Vladimir Marko  }
1935ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void AssertWriterHeld(const Thread* self) { AssertExclusiveHeld(self); }
1945ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
1955ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Assert the current thread doesn't have exclusive access to the ReaderWriterMutex.
1965ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void AssertNotExclusiveHeld(const Thread* self) {
1975ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    if (kDebugLocking) {
1985ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov      CHECK(!IsExclusiveHeld(self));
1995ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    }
2005ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  }
2015ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void AssertNotWriterHeld(const Thread* self) { AssertNotExclusiveHeld(self); }
2025ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
2039cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain  // Is the current thread a shared holder of the ReaderWriterMutex.
2045ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  bool IsSharedHeld(const Thread* self) const;
2055ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
2065ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Assert the current thread has shared access to the ReaderWriterMutex.
2075ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void AssertSharedHeld(const Thread* self) {
2085ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    if (kDebugLocking) {
2095ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov      CHECK(IsSharedHeld(self));
2105ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    }
2115ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  }
2125ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void AssertReaderHeld(const Thread* self) { AssertSharedHeld(self); }
2135ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
2145ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Assert the current thread doesn't hold this ReaderWriterMutex either in shared or exclusive
2155ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // mode.
2165ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void AssertNotHeld(const Thread* self) {
2175ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    if (kDebugLocking) {
2185ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov      CHECK(!IsSharedHeld(self));
2195ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    }
2205ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  }
2215ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
2225ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Id associated with exclusive owner.
2235ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  uint64_t GetExclusiveOwnerTid() const;
2245ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
2255ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov private:
2265ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov#if ART_USE_FUTEXES
2279cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain  // -1 implies held exclusive, +ve shared held by state_ many owners.
2289cc0ea8140e0106e132efc3c1c5c458fa196ae41Roland Levillain  volatile int32_t state_;
2295ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Exclusive owner.
23097c46466aea25ab63a99b3d1afc558f0d9f55abbRoland Levillain  volatile uint64_t exclusive_owner_;
2315ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Pending readers.
2325ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  volatile int32_t num_pending_readers_;
2335ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  // Pending writers.
2345ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  volatile int32_t num_pending_writers_;
2355ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov#else
236517d9f6678c5d577f25777bc000a83afd5503874Artem Serov  pthread_rwlock_t rwlock_;
2375ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov#endif
2385ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  friend class MutexTester;
2395ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  DISALLOW_COPY_AND_ASSIGN(ReaderWriterMutex);
2405ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov};
2415ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
2425ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// ConditionVariables allow threads to queue and sleep. Threads may then be resumed individually
2435ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// (Signal) or all at once (Broadcast).
2445ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilovclass ConditionVariable {
2455ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov public:
2465ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  explicit ConditionVariable(const std::string& name);
2475ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  ~ConditionVariable();
2485ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
249ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  void Broadcast();
250331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray  void Signal();
2515ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void Wait(Thread* self, Mutex& mutex);
2525ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  void TimedWait(Thread* self, Mutex& mutex, const timespec& ts);
2535ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
2545ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov private:
2555ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  pthread_cond_t cond_;
2565ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  std::string name_;
2575ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
2585ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov};
2595ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
2605ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// Scoped locker/unlocker for a regular Mutex that acquires mu upon construction and releases it
2615ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// upon destruction.
2625ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilovclass SCOPED_LOCKABLE MutexLock {
263ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko public:
264ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  explicit MutexLock(Thread* self, Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : self_(self), mu_(mu) {
265ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko    mu_.ExclusiveLock(self_);
2665ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  }
2675ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
2685ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  explicit MutexLock(Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : self_(Thread::Current()), mu_(mu) {
2695ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    mu_.ExclusiveLock(self_);
270ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  }
271ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko
272ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  ~MutexLock() UNLOCK_FUNCTION() {
2735ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    mu_.ExclusiveUnlock(self_);
2745ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  }
2755ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
2765ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov private:
2775ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  Thread* const self_;
2785ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  Mutex& mu_;
2795ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  DISALLOW_COPY_AND_ASSIGN(MutexLock);
2805ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov};
2815ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// Catch bug where variable name is omitted. "MutexLock (lock);" instead of "MutexLock mu(lock)".
2825ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_declaration_missing_variable_name)
2835ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
2845ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// Scoped locker/unlocker for a ReaderWriterMutex that acquires read access to mu upon
2855ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// construction and releases it upon destruction.
2865ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilovclass SCOPED_LOCKABLE ReaderMutexLock {
2875ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov public:
2885ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  explicit ReaderMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
2895ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov      self_(self), mu_(mu) {
2905ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    mu_.SharedLock(self_);
2915ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  }
2925ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
2935ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  explicit ReaderMutexLock(ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
2945ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov      self_(Thread::Current()), mu_(mu) {
2955ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    mu_.SharedLock(self_);
2965ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  }
2975ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
298ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  ~ReaderMutexLock() UNLOCK_FUNCTION() {
2995ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    mu_.SharedUnlock(self_);
3005ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  }
301ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko
3025ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov private:
3035ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  Thread* const self_;
3045ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  ReaderWriterMutex& mu_;
3055ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  DISALLOW_COPY_AND_ASSIGN(ReaderMutexLock);
3065ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov};
3075ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// Catch bug where variable name is omitted. "ReaderMutexLock (lock);" instead of
3085ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// "ReaderMutexLock mu(lock)".
3095ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov#define ReaderMutexLock(x) COMPILE_ASSERT(0, reader_mutex_lock_declaration_missing_variable_name)
3105ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
3115ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov// Scoped locker/unlocker for a ReaderWriterMutex that acquires write access to mu upon
312ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko// construction and releases it upon destruction.
3135ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilovclass SCOPED_LOCKABLE WriterMutexLock {
3145ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov public:
315ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  explicit WriterMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
3165ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov      self_(self), mu_(mu) {
3175ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    mu_.ExclusiveLock(self_);
3185ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  }
3195ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
3205ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  explicit WriterMutexLock(ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
3215ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov      self_(Thread::Current()), mu_(mu) {
3225ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov    mu_.ExclusiveLock(self_);
3235ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  }
3245ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
325ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  ~WriterMutexLock() UNLOCK_FUNCTION() {
326ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko    mu_.ExclusiveUnlock(self_);
327ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  }
3285ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov
3295ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov private:
3305ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  Thread* self_;
3315ec621870ebacca414a5f8114f620854e9ab2948Anton Kirilov  ReaderWriterMutex& mu_;
332ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  DISALLOW_COPY_AND_ASSIGN(WriterMutexLock);
333ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko};
334ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko// Catch bug where variable name is omitted. "WriterMutexLock (lock);" instead of
33527292e64b312007cd301fed8aa96ed7c0215b231Petre-Ionut Tudor// "WriterMutexLock mu(lock)".
33627292e64b312007cd301fed8aa96ed7c0215b231Petre-Ionut Tudor#define WriterMutexLock(x) COMPILE_ASSERT(0, writer_mutex_lock_declaration_missing_variable_name)
33727292e64b312007cd301fed8aa96ed7c0215b231Petre-Ionut Tudor
33827292e64b312007cd301fed8aa96ed7c0215b231Petre-Ionut Tudor}  // namespace art
339ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko
340ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko#endif  // ART_SRC_MUTEX_H_
341ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko