mutex.h revision 56edc432fa914f7ccfa87ce443e64f5ef475666d
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
1776b6167407c2b6f5d40ad895b2793a6b037f54b2Elliott Hughes#ifndef ART_SRC_BASE_MUTEX_H_
1876b6167407c2b6f5d40ad895b2793a6b037f54b2Elliott Hughes#define ART_SRC_BASE_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
2607ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
27761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/macros.h"
2800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "globals.h"
2981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#include "locks.h"
3081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
31ab47016374d340011680e9cd970ee7d6225d6704Ian Rogers#if defined(__APPLE__)
3281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#define ART_USE_FUTEXES 0
33ab47016374d340011680e9cd970ee7d6225d6704Ian Rogers#else
34a6f3aaf8ca5385d870c35d1555b7787d56a70c95Ian Rogers#define ART_USE_FUTEXES !defined(__mips__)
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
4456edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers// Record Log contention information, dumpable via SIGQUIT.
4556edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers#define CONTENTION_LOGGING (0 && ART_USE_FUTEXES)
4656edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogersconst size_t kContentionLogSize = 64;
4756edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers#if CONTENTION_LOGGING
4856edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers#include "atomic_integer.h"
4956edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers#endif
5056edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers
518daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesnamespace art {
528daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
5356edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogersclass ScopedContentionRecorder;
5450b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogersclass Thread;
5550b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers
5625fd14b87cced64a179dee885573113be5e11944Ian Rogersconst bool kDebugLocking = kIsDebugBuild;
5725fd14b87cced64a179dee885573113be5e11944Ian Rogers
5800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Base class for all Mutex implementations
5900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass BaseMutex {
6000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
6100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  const std::string& GetName() const {
6200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return name_;
6300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
6400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
6500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsMutex() const { return false; }
6600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsReaderWriterMutex() const { return false; }
6700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
6856edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  virtual void Dump(std::ostream& os) const = 0;
6956edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers
7056edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  static void DumpAll(std::ostream& os);
7156edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers
7200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers protected:
7300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  friend class ConditionVariable;
7400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
7581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  BaseMutex(const char* name, LockLevel level);
7656edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  virtual ~BaseMutex();
7781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void RegisterAsLocked(Thread* self);
7881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void RegisterAsUnlocked(Thread* self);
7981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void CheckSafeToWait(Thread* self);
8000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
8156edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  friend class ScopedContentionRecorder;
8256edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers
8356edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  void RecordContention(uint64_t blocked_tid, uint64_t owner_tid, uint64_t milli_time_blocked);
8456edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  void DumpContention(std::ostream& os) const;
8556edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers
8681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  const LockLevel level_;  // Support for lock hierarchy.
870a1038b0a30a52dff1a449a989825e808a83df80Elliott Hughes  const std::string name_;
8856edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers#if CONTENTION_LOGGING
8956edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  // A log entry that records contention but makes no guarantee that either tid will be held live.
9056edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  struct ContentionLogEntry {
9156edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers    ContentionLogEntry() : blocked_tid(0), owner_tid(0) {}
9256edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers    uint64_t blocked_tid;
9356edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers    uint64_t owner_tid;
9456edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers    AtomicInteger count;
9556edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  };
9656edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  ContentionLogEntry contention_log_[kContentionLogSize];
9756edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  // The next entry in the contention log to be updated. Value ranges from 0 to
9856edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  // kContentionLogSize - 1.
9956edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  AtomicInteger cur_content_log_entry_;
10056edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  // Number of times the Mutex has been contended.
10156edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  AtomicInteger contention_count_;
10256edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  // Sum of time waited by all contenders in ms.
10356edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  AtomicInteger wait_time_;
10456edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers#endif
10500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
10600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
10700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// A Mutex is used to achieve mutual exclusion between threads. A Mutex can be used to gain
10800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// exclusive access to what it guards. A Mutex can be in one of two states:
10900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Free - not owned by any thread,
11000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Exclusive - owned by a single thread.
11100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
11200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// The effect of locking and unlocking operations on the state is:
11300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// State     | ExclusiveLock | ExclusiveUnlock
11400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// -------------------------------------------
11500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Free      | Exclusive     | error
11600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Exclusive | Block*        | Free
11700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// * Mutex is not reentrant and so an attempt to ExclusiveLock on the same thread will result in
11800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//   an error. Being non-reentrant simplifies Waiting on ConditionVariables.
11901ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogersstd::ostream& operator<<(std::ostream& os, const Mutex& mu);
12000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE Mutex : public BaseMutex {
12100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
12281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit Mutex(const char* name, LockLevel level = kDefaultMutexLevel, bool recursive = false);
12300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~Mutex();
12400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
12500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsMutex() const { return true; }
12600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
12700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until mutex is free then acquire exclusive access.
12881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ExclusiveLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION();
12981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void Lock(Thread* self) EXCLUSIVE_LOCK_FUNCTION() {  ExclusiveLock(self); }
13000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
13100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Returns true if acquires exclusive access, false otherwise.
13281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool ExclusiveTryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true);
13381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool TryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true) { return ExclusiveTryLock(self); }
13400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
13500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release exclusive access.
13681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ExclusiveUnlock(Thread* self) UNLOCK_FUNCTION();
13781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void Unlock(Thread* self) UNLOCK_FUNCTION() {  ExclusiveUnlock(self); }
13800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
13900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Is the current thread the exclusive holder of the Mutex.
14081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool IsExclusiveHeld(const Thread* self) const;
1418daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
14200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert that the Mutex is exclusively held by the current thread.
14381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertExclusiveHeld(const Thread* self) {
14481b8871007101f42e2baabf213e1312004073eb0Brian Carlstrom    if (kDebugLocking && !gAborting) {
14501ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(IsExclusiveHeld(self)) << *this;
14600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
14700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
14881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertHeld(const Thread* self) { AssertExclusiveHeld(self); }
14900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
15000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert that the Mutex is not held by the current thread.
15181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotHeldExclusive(const Thread* self) {
15225fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
15301ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(!IsExclusiveHeld(self)) << *this;
15400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
15500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
15681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotHeld(const Thread* self) { AssertNotHeldExclusive(self); }
15700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
15800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Id associated with exclusive owner.
15900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  uint64_t GetExclusiveOwnerTid() const;
16000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
16100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Returns how many times this Mutex has been locked, it is better to use AssertHeld/NotHeld.
16200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  unsigned int GetDepth() const {
16300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return recursion_count_;
16400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
16500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
16656edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  virtual void Dump(std::ostream& os) const;
16701ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers
16800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
169c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#if ART_USE_FUTEXES
170c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  // 0 is unheld, 1 is held.
171c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  volatile int32_t state_;
172c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  // Exclusive owner.
173c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  volatile uint64_t exclusive_owner_;
174c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  // Number of waiting contenders.
175c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  volatile int32_t num_contenders_;
176c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#else
17700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  pthread_mutex_t mutex_;
178c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#endif
17900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  const bool recursive_;  // Can the lock be recursively held?
18000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  unsigned int recursion_count_;
181f1498437b0d6beb9f4f91980b98cbeb0b5c773ceElliott Hughes  friend class ConditionVariable;
1823efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes  friend class MutexTester;
1838daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  DISALLOW_COPY_AND_ASSIGN(Mutex);
1848daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes};
1858daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
18600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// A ReaderWriterMutex is used to achieve mutual exclusion between threads, similar to a Mutex.
18700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Unlike a Mutex a ReaderWriterMutex can be used to gain exclusive (writer) or shared (reader)
18800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// access to what it guards. A flaw in relation to a Mutex is that it cannot be used with a
18900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// condition variable. A ReaderWriterMutex can be in one of three states:
19000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Free - not owned by any thread,
19100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Exclusive - owned by a single thread,
19200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Shared(n) - shared amongst n threads.
19300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
19400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// The effect of locking and unlocking operations on the state is:
19500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
19600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// State     | ExclusiveLock | ExclusiveUnlock | SharedLock       | SharedUnlock
19700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// ----------------------------------------------------------------------------
19800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Free      | Exclusive     | error           | SharedLock(1)    | error
19900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Exclusive | Block         | Free            | Block            | error
20000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Shared(n) | Block         | error           | SharedLock(n+1)* | Shared(n-1) or Free
20100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// * for large values of n the SharedLock may block.
20201ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogersstd::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu);
20300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE ReaderWriterMutex : public BaseMutex {
2048daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes public:
20581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit ReaderWriterMutex(const char* name, LockLevel level = kDefaultMutexLevel);
20600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~ReaderWriterMutex();
20700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
20800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsReaderWriterMutex() const { return true; }
20900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
21000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until ReaderWriterMutex is free then acquire exclusive access.
21181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ExclusiveLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION();
21281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void WriterLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION() {  ExclusiveLock(self); }
21300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
21400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release exclusive access.
21581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ExclusiveUnlock(Thread* self) UNLOCK_FUNCTION();
21681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void WriterUnlock(Thread* self) UNLOCK_FUNCTION() {  ExclusiveUnlock(self); }
21700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
21800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until ReaderWriterMutex is free and acquire exclusive access. Returns true on success
21900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // or false if timeout is reached.
22066aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#if HAVE_TIMED_RWLOCK
221c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  bool ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32_t ns)
22281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      EXCLUSIVE_TRYLOCK_FUNCTION(true);
22366aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#endif
22400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
22500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until ReaderWriterMutex is shared or free then acquire a share on the access.
22681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void SharedLock(Thread* self) SHARED_LOCK_FUNCTION();
22781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ReaderLock(Thread* self) SHARED_LOCK_FUNCTION() { SharedLock(self); }
22800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
22900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Try to acquire share of ReaderWriterMutex.
23081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool SharedTryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true);
23100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
23200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release a share of the access.
23381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void SharedUnlock(Thread* self) UNLOCK_FUNCTION();
23481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ReaderUnlock(Thread* self) UNLOCK_FUNCTION() { SharedUnlock(self); }
23500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
23600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Is the current thread the exclusive holder of the ReaderWriterMutex.
23781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool IsExclusiveHeld(const Thread* self) const;
23800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
23900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread has exclusive access to the ReaderWriterMutex.
24081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertExclusiveHeld(const Thread* self) {
24125fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
24201ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(IsExclusiveHeld(self)) << *this;
24300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
2448daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  }
24581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertWriterHeld(const Thread* self) { AssertExclusiveHeld(self); }
2468daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
24700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread doesn't have exclusive access to the ReaderWriterMutex.
24881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotExclusiveHeld(const Thread* self) {
24925fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
25081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      CHECK(!IsExclusiveHeld(self));
25100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
25200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
25381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotWriterHeld(const Thread* self) { AssertNotExclusiveHeld(self); }
25400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
25500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Is the current thread a shared holder of the ReaderWriterMutex.
25681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool IsSharedHeld(const Thread* self) const;
25700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
25800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread has shared access to the ReaderWriterMutex.
25981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertSharedHeld(const Thread* self) {
26025fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
26101ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(IsSharedHeld(self)) << *this;
26200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
2638daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  }
26481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertReaderHeld(const Thread* self) { AssertSharedHeld(self); }
2658daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
26600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread doesn't hold this ReaderWriterMutex either in shared or exclusive
26700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // mode.
26881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotHeld(const Thread* self) {
26925fd14b87cced64a179dee885573113be5e11944Ian Rogers    if (kDebugLocking) {
27001ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(!IsSharedHeld(self)) << *this;
27100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
27200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
27300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
27400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Id associated with exclusive owner.
27500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  uint64_t GetExclusiveOwnerTid() const;
27681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
27756edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  virtual void Dump(std::ostream& os) const;
27801ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers
2798daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes private:
28081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#if ART_USE_FUTEXES
28181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  // -1 implies held exclusive, +ve shared held by state_ many owners.
28281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  volatile int32_t state_;
28381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  // Exclusive owner.
28481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  volatile uint64_t exclusive_owner_;
28581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  // Pending readers.
28681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  volatile int32_t num_pending_readers_;
28781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  // Pending writers.
28881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  volatile int32_t num_pending_writers_;
28981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#else
29000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  pthread_rwlock_t rwlock_;
29181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#endif
29200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  friend class MutexTester;
29300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(ReaderWriterMutex);
2948daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes};
2958daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
29600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// ConditionVariables allow threads to queue and sleep. Threads may then be resumed individually
29700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// (Signal) or all at once (Broadcast).
2985f79133a435ebcb20000370d56046fe01201dd80Elliott Hughesclass ConditionVariable {
2995f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes public:
300c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  explicit ConditionVariable(const std::string& name, Mutex& mutex);
3015f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  ~ConditionVariable();
3025f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
303c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  void Broadcast(Thread* self);
304c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  void Signal(Thread* self);
305c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  // TODO: No thread safety analysis on Wait and TimedWait as they call mutex operations via their
306c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  //       pointer copy, thereby defeating annotalysis.
307c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  void Wait(Thread* self) NO_THREAD_SAFETY_ANALYSIS;
308c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  void TimedWait(Thread* self, int64_t ms, int32_t ns) NO_THREAD_SAFETY_ANALYSIS;
3095f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
3105f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes private:
3115f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  std::string name_;
312c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  // The Mutex being used by waiters. It is an error to mix condition variables between different
313c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  // Mutexes.
314c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  Mutex& guard_;
315c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#if ART_USE_FUTEXES
316c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  // A counter that is modified by signals and broadcasts. This ensures that when a waiter gives up
317d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers  // their Mutex and another thread takes it and signals, the waiting thread observes that sequence_
318d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers  // changed and doesn't enter the wait. Modified while holding guard_, but is read by futex wait
319d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers  // without guard_ held.
320d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers  volatile int32_t sequence_;
321c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  // Number of threads that have come into to wait, not the length of the waiters on the futex as
3225bd97c483c1de1eb97afe76123b1b9ab53095edfIan Rogers  // waiters may have been requeued onto guard_. Guarded by guard_.
323c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  volatile int32_t num_waiters_;
324c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#else
325c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  pthread_cond_t cond_;
326c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#endif
3275f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
3285f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes};
3295f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
33000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a regular Mutex that acquires mu upon construction and releases it
33100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// upon destruction.
33200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE MutexLock {
33300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
33481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit MutexLock(Thread* self, Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : self_(self), mu_(mu) {
33581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveLock(self_);
33681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  }
33781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
33800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~MutexLock() UNLOCK_FUNCTION() {
33981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveUnlock(self_);
34000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
34100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
34200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
34381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  Thread* const self_;
34400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Mutex& mu_;
34500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(MutexLock);
34600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
34700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "MutexLock (lock);" instead of "MutexLock mu(lock)".
34800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_declaration_missing_variable_name)
34900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
35000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a ReaderWriterMutex that acquires read access to mu upon
35100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and releases it upon destruction.
35200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE ReaderMutexLock {
35300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
35481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit ReaderMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
35581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      self_(self), mu_(mu) {
35681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.SharedLock(self_);
35781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  }
35881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
35900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~ReaderMutexLock() UNLOCK_FUNCTION() {
36081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.SharedUnlock(self_);
36100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
36200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
36300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
36481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  Thread* const self_;
36500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ReaderWriterMutex& mu_;
36600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(ReaderMutexLock);
36700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
36800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "ReaderMutexLock (lock);" instead of
36900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "ReaderMutexLock mu(lock)".
37000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define ReaderMutexLock(x) COMPILE_ASSERT(0, reader_mutex_lock_declaration_missing_variable_name)
37100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
37200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a ReaderWriterMutex that acquires write access to mu upon
37300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and releases it upon destruction.
37400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE WriterMutexLock {
37500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
37681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit WriterMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
37781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      self_(self), mu_(mu) {
37881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveLock(self_);
37981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  }
38081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
38100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~WriterMutexLock() UNLOCK_FUNCTION() {
38281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveUnlock(self_);
38300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
38400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
38500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
38650b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  Thread* const self_;
38700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ReaderWriterMutex& mu_;
38800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(WriterMutexLock);
38900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
39000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "WriterMutexLock (lock);" instead of
39100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "WriterMutexLock mu(lock)".
39200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define WriterMutexLock(x) COMPILE_ASSERT(0, writer_mutex_lock_declaration_missing_variable_name)
39300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
3948daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}  // namespace art
3958daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
39676b6167407c2b6f5d40ad895b2793a6b037f54b2Elliott Hughes#endif  // ART_SRC_BASE_MUTEX_H_
397