mutex.h revision d9c4fc94fa618617f94e1de9af5f034549100753
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 61d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogersconst size_t kContentionLogSize = 4; 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