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