mutex.h revision 08f2e7b59fab9df108d3d91e6eeb4bbccbb325d1
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
17fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#ifndef ART_RUNTIME_BASE_MUTEX_H_
18fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#define ART_RUNTIME_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
261afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi#include "atomic_integer.h"
2707ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
28761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/macros.h"
2900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "globals.h"
3081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#include "locks.h"
3181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
32ab47016374d340011680e9cd970ee7d6225d6704Ian Rogers#if defined(__APPLE__)
3381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#define ART_USE_FUTEXES 0
34ab47016374d340011680e9cd970ee7d6225d6704Ian Rogers#else
35a6f3aaf8ca5385d870c35d1555b7787d56a70c95Ian Rogers#define ART_USE_FUTEXES !defined(__mips__)
36ab47016374d340011680e9cd970ee7d6225d6704Ian Rogers#endif
378daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
3866aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers// Currently Darwin doesn't support locks with timeouts.
3966aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#if !defined(__APPLE__)
4066aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#define HAVE_TIMED_RWLOCK 1
4166aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#else
4266aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#define HAVE_TIMED_RWLOCK 0
4366aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#endif
4466aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers
458daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesnamespace art {
468daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
4756edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogersclass ScopedContentionRecorder;
4850b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogersclass Thread;
4950b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers
502e250c826b3c405d675017efe79e5db3651c9ee6Brian Carlstromconst bool kDebugLocking = kIsDebugBuild;
5125fd14b87cced64a179dee885573113be5e11944Ian Rogers
521afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi// Record Log contention information, dumpable via SIGQUIT.
531afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi#ifdef ART_USE_FUTEXES
5408f2e7b59fab9df108d3d91e6eeb4bbccbb325d1Jeff Hao// To enable lock contention logging, set this to true.
5508f2e7b59fab9df108d3d91e6eeb4bbccbb325d1Jeff Haoconst bool kLogLockContentions = false;
561afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi#else
571afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi// Keep this false as lock contention logging is supported only with
581afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi// futex.
591afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchiconst bool kLogLockContentions = false;
601afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi#endif
611afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchiconst size_t kContentionLogSize = 64;
621afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchiconst size_t kContentionLogDataSize = kLogLockContentions ? 1 : 0;
631afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchiconst size_t kAllMutexDataSize = kLogLockContentions ? 1 : 0;
641afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi
6500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Base class for all Mutex implementations
6600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass BaseMutex {
6700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
68bab74963db2484ea5f10a82ea26e8a99722bfefeIan Rogers  const char* GetName() const {
6900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return name_;
7000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
7100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
7200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsMutex() const { return false; }
7300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsReaderWriterMutex() const { return false; }
7400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
7556edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  virtual void Dump(std::ostream& os) const = 0;
7656edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers
7756edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  static void DumpAll(std::ostream& os);
7856edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers
7900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers protected:
8000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  friend class ConditionVariable;
8100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
8281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  BaseMutex(const char* name, LockLevel level);
8356edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  virtual ~BaseMutex();
8481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void RegisterAsLocked(Thread* self);
8581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void RegisterAsUnlocked(Thread* self);
8681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void CheckSafeToWait(Thread* self);
8700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
8856edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  friend class ScopedContentionRecorder;
8956edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers
901afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi  void RecordContention(uint64_t blocked_tid, uint64_t owner_tid, uint64_t nano_time_blocked);
9156edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  void DumpContention(std::ostream& os) const;
9256edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers
9381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  const LockLevel level_;  // Support for lock hierarchy.
94bab74963db2484ea5f10a82ea26e8a99722bfefeIan Rogers  const char* const name_;
951afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi
9656edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  // A log entry that records contention but makes no guarantee that either tid will be held live.
9756edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  struct ContentionLogEntry {
9856edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers    ContentionLogEntry() : blocked_tid(0), owner_tid(0) {}
9956edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers    uint64_t blocked_tid;
10056edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers    uint64_t owner_tid;
10156edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers    AtomicInteger count;
10256edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  };
1031afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi  struct ContentionLogData {
1041afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    ContentionLogEntry contention_log[kContentionLogSize];
1051afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    // The next entry in the contention log to be updated. Value ranges from 0 to
1061afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    // kContentionLogSize - 1.
1071afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    AtomicInteger cur_content_log_entry;
1081afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    // Number of times the Mutex has been contended.
1091afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    AtomicInteger contention_count;
1101afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    // Sum of time waited by all contenders in ns.
1111afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    volatile uint64_t wait_time;
1121afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    void AddToWaitTime(uint64_t value);
1131afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    ContentionLogData() : wait_time(0) {}
1141afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi  };
1151afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi  ContentionLogData contetion_log_data_[kContentionLogDataSize];
1161afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi
1171afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi public:
1181afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi  bool HasEverContended() const {
1191afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    if (kLogLockContentions) {
1201afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi      return contetion_log_data_->contention_count > 0;
1211afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    }
1221afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi    return false;
1231afde13b36cc1d67528104c2b1395495f669cd3fHiroshi Yamauchi  }
12400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
12500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
12600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// A Mutex is used to achieve mutual exclusion between threads. A Mutex can be used to gain
12700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// exclusive access to what it guards. A Mutex can be in one of two states:
12800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Free - not owned by any thread,
12900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Exclusive - owned by a single thread.
13000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
13100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// The effect of locking and unlocking operations on the state is:
13200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// State     | ExclusiveLock | ExclusiveUnlock
13300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// -------------------------------------------
13400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Free      | Exclusive     | error
13500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Exclusive | Block*        | Free
13600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// * Mutex is not reentrant and so an attempt to ExclusiveLock on the same thread will result in
13700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//   an error. Being non-reentrant simplifies Waiting on ConditionVariables.
13801ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogersstd::ostream& operator<<(std::ostream& os, const Mutex& mu);
13900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE Mutex : public BaseMutex {
14000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
14181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit Mutex(const char* name, LockLevel level = kDefaultMutexLevel, bool recursive = false);
14200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~Mutex();
14300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
14400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsMutex() const { return true; }
14500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
14600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until mutex is free then acquire exclusive access.
14781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ExclusiveLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION();
14881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void Lock(Thread* self) EXCLUSIVE_LOCK_FUNCTION() {  ExclusiveLock(self); }
14900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
15000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Returns true if acquires exclusive access, false otherwise.
15181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool ExclusiveTryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true);
15281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool TryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true) { return ExclusiveTryLock(self); }
15300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
15400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release exclusive access.
15581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ExclusiveUnlock(Thread* self) UNLOCK_FUNCTION();
15681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void Unlock(Thread* self) UNLOCK_FUNCTION() {  ExclusiveUnlock(self); }
15700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
15800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Is the current thread the exclusive holder of the Mutex.
15981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool IsExclusiveHeld(const Thread* self) const;
1608daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
16100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert that the Mutex is exclusively held by the current thread.
16281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertExclusiveHeld(const Thread* self) {
1633c539ffccabada93c404c0dfba8b52926ae06d0cAnwar Ghuloum    if (kDebugLocking && (gAborting == 0)) {
16401ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(IsExclusiveHeld(self)) << *this;
16500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
16600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
16781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertHeld(const Thread* self) { AssertExclusiveHeld(self); }
16800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
16900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert that the Mutex is not held by the current thread.
17081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotHeldExclusive(const Thread* self) {
1713c539ffccabada93c404c0dfba8b52926ae06d0cAnwar Ghuloum    if (kDebugLocking && (gAborting == 0)) {
17201ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(!IsExclusiveHeld(self)) << *this;
17300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
17400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
17581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotHeld(const Thread* self) { AssertNotHeldExclusive(self); }
17600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
17700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Id associated with exclusive owner.
17800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  uint64_t GetExclusiveOwnerTid() const;
17900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
18000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Returns how many times this Mutex has been locked, it is better to use AssertHeld/NotHeld.
18100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  unsigned int GetDepth() const {
18200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return recursion_count_;
18300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
18400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
18556edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  virtual void Dump(std::ostream& os) const;
18601ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers
18700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
188c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#if ART_USE_FUTEXES
189c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  // 0 is unheld, 1 is held.
190c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  volatile int32_t state_;
191c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  // Exclusive owner.
192c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  volatile uint64_t exclusive_owner_;
193c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  // Number of waiting contenders.
194c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  volatile int32_t num_contenders_;
195c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#else
19600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  pthread_mutex_t mutex_;
197c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#endif
19800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  const bool recursive_;  // Can the lock be recursively held?
19900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  unsigned int recursion_count_;
200f1498437b0d6beb9f4f91980b98cbeb0b5c773ceElliott Hughes  friend class ConditionVariable;
2018daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  DISALLOW_COPY_AND_ASSIGN(Mutex);
2028daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes};
2038daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
20400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// A ReaderWriterMutex is used to achieve mutual exclusion between threads, similar to a Mutex.
20500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Unlike a Mutex a ReaderWriterMutex can be used to gain exclusive (writer) or shared (reader)
20600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// access to what it guards. A flaw in relation to a Mutex is that it cannot be used with a
20700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// condition variable. A ReaderWriterMutex can be in one of three states:
20800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Free - not owned by any thread,
20900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Exclusive - owned by a single thread,
21000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Shared(n) - shared amongst n threads.
21100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
21200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// The effect of locking and unlocking operations on the state is:
21300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers//
21400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// State     | ExclusiveLock | ExclusiveUnlock | SharedLock       | SharedUnlock
21500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// ----------------------------------------------------------------------------
21600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Free      | Exclusive     | error           | SharedLock(1)    | error
21700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Exclusive | Block         | Free            | Block            | error
21800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Shared(n) | Block         | error           | SharedLock(n+1)* | Shared(n-1) or Free
21900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// * for large values of n the SharedLock may block.
22001ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogersstd::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu);
22100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE ReaderWriterMutex : public BaseMutex {
2228daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes public:
22381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit ReaderWriterMutex(const char* name, LockLevel level = kDefaultMutexLevel);
22400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~ReaderWriterMutex();
22500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
22600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual bool IsReaderWriterMutex() const { return true; }
22700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
22800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until ReaderWriterMutex is free then acquire exclusive access.
22981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ExclusiveLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION();
23081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void WriterLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION() {  ExclusiveLock(self); }
23100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
23200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release exclusive access.
23381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ExclusiveUnlock(Thread* self) UNLOCK_FUNCTION();
23481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void WriterUnlock(Thread* self) UNLOCK_FUNCTION() {  ExclusiveUnlock(self); }
23500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
23600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until ReaderWriterMutex is free and acquire exclusive access. Returns true on success
23700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // or false if timeout is reached.
23866aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#if HAVE_TIMED_RWLOCK
239c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  bool ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32_t ns)
24081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      EXCLUSIVE_TRYLOCK_FUNCTION(true);
24166aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#endif
24200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
24300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Block until ReaderWriterMutex is shared or free then acquire a share on the access.
2441ffa32f0be7becec4907b26ead353e4b17e1219cIan Rogers  void SharedLock(Thread* self) SHARED_LOCK_FUNCTION() ALWAYS_INLINE;
24581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ReaderLock(Thread* self) SHARED_LOCK_FUNCTION() { SharedLock(self); }
24600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
24700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Try to acquire share of ReaderWriterMutex.
24881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool SharedTryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true);
24900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
25000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Release a share of the access.
2511ffa32f0be7becec4907b26ead353e4b17e1219cIan Rogers  void SharedUnlock(Thread* self) UNLOCK_FUNCTION() ALWAYS_INLINE;
25281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void ReaderUnlock(Thread* self) UNLOCK_FUNCTION() { SharedUnlock(self); }
25300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
25400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Is the current thread the exclusive holder of the ReaderWriterMutex.
25581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool IsExclusiveHeld(const Thread* self) const;
25600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
25700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread has exclusive access to the ReaderWriterMutex.
25881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertExclusiveHeld(const Thread* self) {
259702a85b33c57da99e83698129a289687cdb0be1fSebastien Hertz    if (kDebugLocking && (gAborting == 0)) {
26001ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(IsExclusiveHeld(self)) << *this;
26100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
2628daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  }
26381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertWriterHeld(const Thread* self) { AssertExclusiveHeld(self); }
2648daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
26500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread doesn't have exclusive access to the ReaderWriterMutex.
26681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotExclusiveHeld(const Thread* self) {
267702a85b33c57da99e83698129a289687cdb0be1fSebastien Hertz    if (kDebugLocking && (gAborting == 0)) {
268e3359f7ad7671c5816f17145ca3a01516512e8d6Ian Rogers      CHECK(!IsExclusiveHeld(self)) << *this;
26900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
27000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
27181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotWriterHeld(const Thread* self) { AssertNotExclusiveHeld(self); }
27200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
27300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Is the current thread a shared holder of the ReaderWriterMutex.
27481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  bool IsSharedHeld(const Thread* self) const;
27500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
27600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread has shared access to the ReaderWriterMutex.
27781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertSharedHeld(const Thread* self) {
278702a85b33c57da99e83698129a289687cdb0be1fSebastien Hertz    if (kDebugLocking && (gAborting == 0)) {
27923055dc5d7a90c4a12e259fd0ed7cd4d04d89182Ian Rogers      // TODO: we can only assert this well when self != NULL.
28023055dc5d7a90c4a12e259fd0ed7cd4d04d89182Ian Rogers      CHECK(IsSharedHeld(self) || self == NULL) << *this;
28100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
2828daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes  }
28381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertReaderHeld(const Thread* self) { AssertSharedHeld(self); }
2848daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
28500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Assert the current thread doesn't hold this ReaderWriterMutex either in shared or exclusive
28600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // mode.
28781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  void AssertNotHeld(const Thread* self) {
2883c539ffccabada93c404c0dfba8b52926ae06d0cAnwar Ghuloum    if (kDebugLocking && (gAborting == 0)) {
28901ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers      CHECK(!IsSharedHeld(self)) << *this;
29000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
29100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
29200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
29300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Id associated with exclusive owner.
29400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  uint64_t GetExclusiveOwnerTid() const;
29581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
29656edc432fa914f7ccfa87ce443e64f5ef475666dIan Rogers  virtual void Dump(std::ostream& os) const;
29701ae5808367e641a983e3f8bb82b3e0d364cd03eIan Rogers
2988daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes private:
29981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#if ART_USE_FUTEXES
30081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  // -1 implies held exclusive, +ve shared held by state_ many owners.
30181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  volatile int32_t state_;
30281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  // Exclusive owner.
30381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  volatile uint64_t exclusive_owner_;
30481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  // Pending readers.
30581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  volatile int32_t num_pending_readers_;
30681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  // Pending writers.
30781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  volatile int32_t num_pending_writers_;
30881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#else
30900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  pthread_rwlock_t rwlock_;
31081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers#endif
31100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(ReaderWriterMutex);
3128daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes};
3138daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
31400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// ConditionVariables allow threads to queue and sleep. Threads may then be resumed individually
31500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// (Signal) or all at once (Broadcast).
3165f79133a435ebcb20000370d56046fe01201dd80Elliott Hughesclass ConditionVariable {
3175f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes public:
31823055dc5d7a90c4a12e259fd0ed7cd4d04d89182Ian Rogers  explicit ConditionVariable(const char* name, Mutex& mutex);
3195f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  ~ConditionVariable();
3205f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
321c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  void Broadcast(Thread* self);
322c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  void Signal(Thread* self);
323c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  // TODO: No thread safety analysis on Wait and TimedWait as they call mutex operations via their
324c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  //       pointer copy, thereby defeating annotalysis.
325c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  void Wait(Thread* self) NO_THREAD_SAFETY_ANALYSIS;
326c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  void TimedWait(Thread* self, int64_t ms, int32_t ns) NO_THREAD_SAFETY_ANALYSIS;
3271d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  // Variant of Wait that should be used with caution. Doesn't validate that no mutexes are held
3281d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  // when waiting.
3291d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  // TODO: remove this.
3301d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  void WaitHoldingLocks(Thread* self) NO_THREAD_SAFETY_ANALYSIS;
3315f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
3325f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes private:
33323055dc5d7a90c4a12e259fd0ed7cd4d04d89182Ian Rogers  const char* const name_;
334c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  // The Mutex being used by waiters. It is an error to mix condition variables between different
335c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  // Mutexes.
336c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  Mutex& guard_;
337c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#if ART_USE_FUTEXES
338c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  // A counter that is modified by signals and broadcasts. This ensures that when a waiter gives up
339d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers  // their Mutex and another thread takes it and signals, the waiting thread observes that sequence_
340d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers  // changed and doesn't enter the wait. Modified while holding guard_, but is read by futex wait
341d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers  // without guard_ held.
342d45f201e9bd43490e30a35710865789b8d70e249Ian Rogers  volatile int32_t sequence_;
343c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  // Number of threads that have come into to wait, not the length of the waiters on the futex as
3445bd97c483c1de1eb97afe76123b1b9ab53095edfIan Rogers  // waiters may have been requeued onto guard_. Guarded by guard_.
345c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  volatile int32_t num_waiters_;
346c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#else
347c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  pthread_cond_t cond_;
348c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers#endif
3495f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes  DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
3505f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes};
3515f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes
35200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a regular Mutex that acquires mu upon construction and releases it
35300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// upon destruction.
35400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE MutexLock {
35500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
35681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit MutexLock(Thread* self, Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : self_(self), mu_(mu) {
35781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveLock(self_);
35881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  }
35981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
36000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~MutexLock() UNLOCK_FUNCTION() {
36181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveUnlock(self_);
36200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
36300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
36400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
36581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  Thread* const self_;
36600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Mutex& mu_;
36700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(MutexLock);
36800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
36900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "MutexLock (lock);" instead of "MutexLock mu(lock)".
37000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_declaration_missing_variable_name)
37100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
37200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a ReaderWriterMutex that acquires read access to mu upon
37300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and releases it upon destruction.
37400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE ReaderMutexLock {
37500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
37681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit ReaderMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
37781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      self_(self), mu_(mu) {
37881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.SharedLock(self_);
37981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  }
38081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
38100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~ReaderMutexLock() UNLOCK_FUNCTION() {
38281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.SharedUnlock(self_);
38300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
38400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
38500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
38681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  Thread* const self_;
38700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ReaderWriterMutex& mu_;
38800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(ReaderMutexLock);
38900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
39000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "ReaderMutexLock (lock);" instead of
39100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "ReaderMutexLock mu(lock)".
39200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define ReaderMutexLock(x) COMPILE_ASSERT(0, reader_mutex_lock_declaration_missing_variable_name)
39300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
39400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a ReaderWriterMutex that acquires write access to mu upon
39500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and releases it upon destruction.
39600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE WriterMutexLock {
39700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public:
39881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  explicit WriterMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
39981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers      self_(self), mu_(mu) {
40081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveLock(self_);
40181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  }
40281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers
40300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ~WriterMutexLock() UNLOCK_FUNCTION() {
40481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    mu_.ExclusiveUnlock(self_);
40500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
40600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
40700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private:
40850b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  Thread* const self_;
40900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ReaderWriterMutex& mu_;
41000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  DISALLOW_COPY_AND_ASSIGN(WriterMutexLock);
41100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers};
41200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "WriterMutexLock (lock);" instead of
41300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "WriterMutexLock mu(lock)".
41400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define WriterMutexLock(x) COMPILE_ASSERT(0, writer_mutex_lock_declaration_missing_variable_name)
41500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
4168daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}  // namespace art
4178daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
418fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#endif  // ART_RUNTIME_BASE_MUTEX_H_
419