mutex.h revision 00ae676e307c8e3c3b19852f41ad0547c4c523b8
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef ART_RUNTIME_BASE_MUTEX_H_ 18#define ART_RUNTIME_BASE_MUTEX_H_ 19 20#include <pthread.h> 21#include <stdint.h> 22 23#include <iosfwd> 24#include <string> 25 26#include "base/logging.h" 27#include "base/macros.h" 28#include "globals.h" 29#include "locks.h" 30 31#if defined(__APPLE__) 32#define ART_USE_FUTEXES 0 33#else 34#define ART_USE_FUTEXES !defined(__mips__) 35#endif 36 37// Currently Darwin doesn't support locks with timeouts. 38#if !defined(__APPLE__) 39#define HAVE_TIMED_RWLOCK 1 40#else 41#define HAVE_TIMED_RWLOCK 0 42#endif 43 44// Record Log contention information, dumpable via SIGQUIT. 45#define CONTENTION_LOGGING (0 && ART_USE_FUTEXES) 46const size_t kContentionLogSize = 64; 47#if CONTENTION_LOGGING 48#include "atomic_integer.h" 49#endif 50 51namespace art { 52 53class ScopedContentionRecorder; 54class Thread; 55 56const bool kDebugLocking = true || kIsDebugBuild; 57 58// Base class for all Mutex implementations 59class BaseMutex { 60 public: 61 const char* GetName() const { 62 return name_; 63 } 64 65 virtual bool IsMutex() const { return false; } 66 virtual bool IsReaderWriterMutex() const { return false; } 67 68 virtual void Dump(std::ostream& os) const = 0; 69 70 static void DumpAll(std::ostream& os); 71 72 protected: 73 friend class ConditionVariable; 74 75 BaseMutex(const char* name, LockLevel level); 76 virtual ~BaseMutex(); 77 void RegisterAsLocked(Thread* self); 78 void RegisterAsUnlocked(Thread* self); 79 void CheckSafeToWait(Thread* self); 80 81 friend class ScopedContentionRecorder; 82 83 void RecordContention(uint64_t blocked_tid, uint64_t owner_tid, uint64_t milli_time_blocked); 84 void DumpContention(std::ostream& os) const; 85 86 const LockLevel level_; // Support for lock hierarchy. 87 const char* const name_; 88#if CONTENTION_LOGGING 89 // A log entry that records contention but makes no guarantee that either tid will be held live. 90 struct ContentionLogEntry { 91 ContentionLogEntry() : blocked_tid(0), owner_tid(0) {} 92 uint64_t blocked_tid; 93 uint64_t owner_tid; 94 AtomicInteger count; 95 }; 96 ContentionLogEntry contention_log_[kContentionLogSize]; 97 // The next entry in the contention log to be updated. Value ranges from 0 to 98 // kContentionLogSize - 1. 99 AtomicInteger cur_content_log_entry_; 100 // Number of times the Mutex has been contended. 101 AtomicInteger contention_count_; 102 // Sum of time waited by all contenders in ms. 103 AtomicInteger wait_time_; 104#endif 105}; 106 107// A Mutex is used to achieve mutual exclusion between threads. A Mutex can be used to gain 108// exclusive access to what it guards. A Mutex can be in one of two states: 109// - Free - not owned by any thread, 110// - Exclusive - owned by a single thread. 111// 112// The effect of locking and unlocking operations on the state is: 113// State | ExclusiveLock | ExclusiveUnlock 114// ------------------------------------------- 115// Free | Exclusive | error 116// Exclusive | Block* | Free 117// * Mutex is not reentrant and so an attempt to ExclusiveLock on the same thread will result in 118// an error. Being non-reentrant simplifies Waiting on ConditionVariables. 119std::ostream& operator<<(std::ostream& os, const Mutex& mu); 120class LOCKABLE Mutex : public BaseMutex { 121 public: 122 explicit Mutex(const char* name, LockLevel level = kDefaultMutexLevel, bool recursive = false); 123 ~Mutex(); 124 125 virtual bool IsMutex() const { return true; } 126 127 // Block until mutex is free then acquire exclusive access. 128 void ExclusiveLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION(); 129 void Lock(Thread* self) EXCLUSIVE_LOCK_FUNCTION() { ExclusiveLock(self); } 130 131 // Returns true if acquires exclusive access, false otherwise. 132 bool ExclusiveTryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true); 133 bool TryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true) { return ExclusiveTryLock(self); } 134 135 // Release exclusive access. 136 void ExclusiveUnlock(Thread* self) UNLOCK_FUNCTION(); 137 void Unlock(Thread* self) UNLOCK_FUNCTION() { ExclusiveUnlock(self); } 138 139 // Is the current thread the exclusive holder of the Mutex. 140 bool IsExclusiveHeld(const Thread* self) const; 141 142 // Assert that the Mutex is exclusively held by the current thread. 143 void AssertExclusiveHeld(const Thread* self) { 144 if (kDebugLocking && (gAborting == 0)) { 145 CHECK(IsExclusiveHeld(self)) << *this; 146 } 147 } 148 void AssertHeld(const Thread* self) { AssertExclusiveHeld(self); } 149 150 // Assert that the Mutex is not held by the current thread. 151 void AssertNotHeldExclusive(const Thread* self) { 152 if (kDebugLocking && (gAborting == 0)) { 153 CHECK(!IsExclusiveHeld(self)) << *this; 154 } 155 } 156 void AssertNotHeld(const Thread* self) { AssertNotHeldExclusive(self); } 157 158 // Id associated with exclusive owner. 159 uint64_t GetExclusiveOwnerTid() const; 160 161 // Returns how many times this Mutex has been locked, it is better to use AssertHeld/NotHeld. 162 unsigned int GetDepth() const { 163 return recursion_count_; 164 } 165 166 virtual void Dump(std::ostream& os) const; 167 168 private: 169#if ART_USE_FUTEXES 170 // 0 is unheld, 1 is held. 171 volatile int32_t state_; 172 // Exclusive owner. 173 volatile uint64_t exclusive_owner_; 174 // Number of waiting contenders. 175 volatile int32_t num_contenders_; 176#else 177 pthread_mutex_t mutex_; 178#endif 179 const bool recursive_; // Can the lock be recursively held? 180 unsigned int recursion_count_; 181 friend class ConditionVariable; 182 friend class MutexTester; 183 DISALLOW_COPY_AND_ASSIGN(Mutex); 184}; 185 186// A ReaderWriterMutex is used to achieve mutual exclusion between threads, similar to a Mutex. 187// Unlike a Mutex a ReaderWriterMutex can be used to gain exclusive (writer) or shared (reader) 188// access to what it guards. A flaw in relation to a Mutex is that it cannot be used with a 189// condition variable. A ReaderWriterMutex can be in one of three states: 190// - Free - not owned by any thread, 191// - Exclusive - owned by a single thread, 192// - Shared(n) - shared amongst n threads. 193// 194// The effect of locking and unlocking operations on the state is: 195// 196// State | ExclusiveLock | ExclusiveUnlock | SharedLock | SharedUnlock 197// ---------------------------------------------------------------------------- 198// Free | Exclusive | error | SharedLock(1) | error 199// Exclusive | Block | Free | Block | error 200// Shared(n) | Block | error | SharedLock(n+1)* | Shared(n-1) or Free 201// * for large values of n the SharedLock may block. 202std::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu); 203class LOCKABLE ReaderWriterMutex : public BaseMutex { 204 public: 205 explicit ReaderWriterMutex(const char* name, LockLevel level = kDefaultMutexLevel); 206 ~ReaderWriterMutex(); 207 208 virtual bool IsReaderWriterMutex() const { return true; } 209 210 // Block until ReaderWriterMutex is free then acquire exclusive access. 211 void ExclusiveLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION(); 212 void WriterLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION() { ExclusiveLock(self); } 213 214 // Release exclusive access. 215 void ExclusiveUnlock(Thread* self) UNLOCK_FUNCTION(); 216 void WriterUnlock(Thread* self) UNLOCK_FUNCTION() { ExclusiveUnlock(self); } 217 218 // Block until ReaderWriterMutex is free and acquire exclusive access. Returns true on success 219 // or false if timeout is reached. 220#if HAVE_TIMED_RWLOCK 221 bool ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32_t ns) 222 EXCLUSIVE_TRYLOCK_FUNCTION(true); 223#endif 224 225 // Block until ReaderWriterMutex is shared or free then acquire a share on the access. 226 void SharedLock(Thread* self) SHARED_LOCK_FUNCTION() ALWAYS_INLINE; 227 void ReaderLock(Thread* self) SHARED_LOCK_FUNCTION() { SharedLock(self); } 228 229 // Try to acquire share of ReaderWriterMutex. 230 bool SharedTryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true); 231 232 // Release a share of the access. 233 void SharedUnlock(Thread* self) UNLOCK_FUNCTION() ALWAYS_INLINE; 234 void ReaderUnlock(Thread* self) UNLOCK_FUNCTION() { SharedUnlock(self); } 235 236 // Is the current thread the exclusive holder of the ReaderWriterMutex. 237 bool IsExclusiveHeld(const Thread* self) const; 238 239 // Assert the current thread has exclusive access to the ReaderWriterMutex. 240 void AssertExclusiveHeld(const Thread* self) { 241 if (kDebugLocking && (gAborting == 0)) { 242 CHECK(IsExclusiveHeld(self)) << *this; 243 } 244 } 245 void AssertWriterHeld(const Thread* self) { AssertExclusiveHeld(self); } 246 247 // Assert the current thread doesn't have exclusive access to the ReaderWriterMutex. 248 void AssertNotExclusiveHeld(const Thread* self) { 249 if (kDebugLocking && (gAborting == 0)) { 250 CHECK(!IsExclusiveHeld(self)) << *this; 251 } 252 } 253 void AssertNotWriterHeld(const Thread* self) { AssertNotExclusiveHeld(self); } 254 255 // Is the current thread a shared holder of the ReaderWriterMutex. 256 bool IsSharedHeld(const Thread* self) const; 257 258 // Assert the current thread has shared access to the ReaderWriterMutex. 259 void AssertSharedHeld(const Thread* self) { 260 if (kDebugLocking && (gAborting == 0)) { 261 // TODO: we can only assert this well when self != NULL. 262 CHECK(IsSharedHeld(self) || self == NULL) << *this; 263 } 264 } 265 void AssertReaderHeld(const Thread* self) { AssertSharedHeld(self); } 266 267 // Assert the current thread doesn't hold this ReaderWriterMutex either in shared or exclusive 268 // mode. 269 void AssertNotHeld(const Thread* self) { 270 if (kDebugLocking && (gAborting == 0)) { 271 CHECK(!IsSharedHeld(self)) << *this; 272 } 273 } 274 275 // Id associated with exclusive owner. 276 uint64_t GetExclusiveOwnerTid() const; 277 278 virtual void Dump(std::ostream& os) const; 279 280 private: 281#if ART_USE_FUTEXES 282 // -1 implies held exclusive, +ve shared held by state_ many owners. 283 volatile int32_t state_; 284 // Exclusive owner. 285 volatile uint64_t exclusive_owner_; 286 // Pending readers. 287 volatile int32_t num_pending_readers_; 288 // Pending writers. 289 volatile int32_t num_pending_writers_; 290#else 291 pthread_rwlock_t rwlock_; 292#endif 293 friend class MutexTester; 294 DISALLOW_COPY_AND_ASSIGN(ReaderWriterMutex); 295}; 296 297// ConditionVariables allow threads to queue and sleep. Threads may then be resumed individually 298// (Signal) or all at once (Broadcast). 299class ConditionVariable { 300 public: 301 explicit ConditionVariable(const char* name, Mutex& mutex); 302 ~ConditionVariable(); 303 304 void Broadcast(Thread* self); 305 void Signal(Thread* self); 306 // TODO: No thread safety analysis on Wait and TimedWait as they call mutex operations via their 307 // pointer copy, thereby defeating annotalysis. 308 void Wait(Thread* self) NO_THREAD_SAFETY_ANALYSIS; 309 void TimedWait(Thread* self, int64_t ms, int32_t ns) NO_THREAD_SAFETY_ANALYSIS; 310 // Variant of Wait that should be used with caution. Doesn't validate that no mutexes are held 311 // when waiting. 312 // TODO: remove this. 313 void WaitHoldingLocks(Thread* self) NO_THREAD_SAFETY_ANALYSIS; 314 315 private: 316 const char* const name_; 317 // The Mutex being used by waiters. It is an error to mix condition variables between different 318 // Mutexes. 319 Mutex& guard_; 320#if ART_USE_FUTEXES 321 // A counter that is modified by signals and broadcasts. This ensures that when a waiter gives up 322 // their Mutex and another thread takes it and signals, the waiting thread observes that sequence_ 323 // changed and doesn't enter the wait. Modified while holding guard_, but is read by futex wait 324 // without guard_ held. 325 volatile int32_t sequence_; 326 // Number of threads that have come into to wait, not the length of the waiters on the futex as 327 // waiters may have been requeued onto guard_. Guarded by guard_. 328 volatile int32_t num_waiters_; 329#else 330 pthread_cond_t cond_; 331#endif 332 DISALLOW_COPY_AND_ASSIGN(ConditionVariable); 333}; 334 335// Scoped locker/unlocker for a regular Mutex that acquires mu upon construction and releases it 336// upon destruction. 337class SCOPED_LOCKABLE MutexLock { 338 public: 339 explicit MutexLock(Thread* self, Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : self_(self), mu_(mu) { 340 mu_.ExclusiveLock(self_); 341 } 342 343 ~MutexLock() UNLOCK_FUNCTION() { 344 mu_.ExclusiveUnlock(self_); 345 } 346 347 private: 348 Thread* const self_; 349 Mutex& mu_; 350 DISALLOW_COPY_AND_ASSIGN(MutexLock); 351}; 352// Catch bug where variable name is omitted. "MutexLock (lock);" instead of "MutexLock mu(lock)". 353#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_declaration_missing_variable_name) 354 355// Scoped locker/unlocker for a ReaderWriterMutex that acquires read access to mu upon 356// construction and releases it upon destruction. 357class SCOPED_LOCKABLE ReaderMutexLock { 358 public: 359 explicit ReaderMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : 360 self_(self), mu_(mu) { 361 mu_.SharedLock(self_); 362 } 363 364 ~ReaderMutexLock() UNLOCK_FUNCTION() { 365 mu_.SharedUnlock(self_); 366 } 367 368 private: 369 Thread* const self_; 370 ReaderWriterMutex& mu_; 371 DISALLOW_COPY_AND_ASSIGN(ReaderMutexLock); 372}; 373// Catch bug where variable name is omitted. "ReaderMutexLock (lock);" instead of 374// "ReaderMutexLock mu(lock)". 375#define ReaderMutexLock(x) COMPILE_ASSERT(0, reader_mutex_lock_declaration_missing_variable_name) 376 377// Scoped locker/unlocker for a ReaderWriterMutex that acquires write access to mu upon 378// construction and releases it upon destruction. 379class SCOPED_LOCKABLE WriterMutexLock { 380 public: 381 explicit WriterMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : 382 self_(self), mu_(mu) { 383 mu_.ExclusiveLock(self_); 384 } 385 386 ~WriterMutexLock() UNLOCK_FUNCTION() { 387 mu_.ExclusiveUnlock(self_); 388 } 389 390 private: 391 Thread* const self_; 392 ReaderWriterMutex& mu_; 393 DISALLOW_COPY_AND_ASSIGN(WriterMutexLock); 394}; 395// Catch bug where variable name is omitted. "WriterMutexLock (lock);" instead of 396// "WriterMutexLock mu(lock)". 397#define WriterMutexLock(x) COMPILE_ASSERT(0, writer_mutex_lock_declaration_missing_variable_name) 398 399} // namespace art 400 401#endif // ART_RUNTIME_BASE_MUTEX_H_ 402