mutex.h revision b0f871965d588cce066785728fb105248b38bb4a
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 DISALLOW_COPY_AND_ASSIGN(Mutex); 183}; 184 185// A ReaderWriterMutex is used to achieve mutual exclusion between threads, similar to a Mutex. 186// Unlike a Mutex a ReaderWriterMutex can be used to gain exclusive (writer) or shared (reader) 187// access to what it guards. A flaw in relation to a Mutex is that it cannot be used with a 188// condition variable. A ReaderWriterMutex can be in one of three states: 189// - Free - not owned by any thread, 190// - Exclusive - owned by a single thread, 191// - Shared(n) - shared amongst n threads. 192// 193// The effect of locking and unlocking operations on the state is: 194// 195// State | ExclusiveLock | ExclusiveUnlock | SharedLock | SharedUnlock 196// ---------------------------------------------------------------------------- 197// Free | Exclusive | error | SharedLock(1) | error 198// Exclusive | Block | Free | Block | error 199// Shared(n) | Block | error | SharedLock(n+1)* | Shared(n-1) or Free 200// * for large values of n the SharedLock may block. 201std::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu); 202class LOCKABLE ReaderWriterMutex : public BaseMutex { 203 public: 204 explicit ReaderWriterMutex(const char* name, LockLevel level = kDefaultMutexLevel); 205 ~ReaderWriterMutex(); 206 207 virtual bool IsReaderWriterMutex() const { return true; } 208 209 // Block until ReaderWriterMutex is free then acquire exclusive access. 210 void ExclusiveLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION(); 211 void WriterLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION() { ExclusiveLock(self); } 212 213 // Release exclusive access. 214 void ExclusiveUnlock(Thread* self) UNLOCK_FUNCTION(); 215 void WriterUnlock(Thread* self) UNLOCK_FUNCTION() { ExclusiveUnlock(self); } 216 217 // Block until ReaderWriterMutex is free and acquire exclusive access. Returns true on success 218 // or false if timeout is reached. 219#if HAVE_TIMED_RWLOCK 220 bool ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32_t ns) 221 EXCLUSIVE_TRYLOCK_FUNCTION(true); 222#endif 223 224 // Block until ReaderWriterMutex is shared or free then acquire a share on the access. 225 void SharedLock(Thread* self) SHARED_LOCK_FUNCTION() ALWAYS_INLINE; 226 void ReaderLock(Thread* self) SHARED_LOCK_FUNCTION() { SharedLock(self); } 227 228 // Try to acquire share of ReaderWriterMutex. 229 bool SharedTryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true); 230 231 // Release a share of the access. 232 void SharedUnlock(Thread* self) UNLOCK_FUNCTION() ALWAYS_INLINE; 233 void ReaderUnlock(Thread* self) UNLOCK_FUNCTION() { SharedUnlock(self); } 234 235 // Is the current thread the exclusive holder of the ReaderWriterMutex. 236 bool IsExclusiveHeld(const Thread* self) const; 237 238 // Assert the current thread has exclusive access to the ReaderWriterMutex. 239 void AssertExclusiveHeld(const Thread* self) { 240 if (kDebugLocking && (gAborting == 0)) { 241 CHECK(IsExclusiveHeld(self)) << *this; 242 } 243 } 244 void AssertWriterHeld(const Thread* self) { AssertExclusiveHeld(self); } 245 246 // Assert the current thread doesn't have exclusive access to the ReaderWriterMutex. 247 void AssertNotExclusiveHeld(const Thread* self) { 248 if (kDebugLocking && (gAborting == 0)) { 249 CHECK(!IsExclusiveHeld(self)) << *this; 250 } 251 } 252 void AssertNotWriterHeld(const Thread* self) { AssertNotExclusiveHeld(self); } 253 254 // Is the current thread a shared holder of the ReaderWriterMutex. 255 bool IsSharedHeld(const Thread* self) const; 256 257 // Assert the current thread has shared access to the ReaderWriterMutex. 258 void AssertSharedHeld(const Thread* self) { 259 if (kDebugLocking && (gAborting == 0)) { 260 // TODO: we can only assert this well when self != NULL. 261 CHECK(IsSharedHeld(self) || self == NULL) << *this; 262 } 263 } 264 void AssertReaderHeld(const Thread* self) { AssertSharedHeld(self); } 265 266 // Assert the current thread doesn't hold this ReaderWriterMutex either in shared or exclusive 267 // mode. 268 void AssertNotHeld(const Thread* self) { 269 if (kDebugLocking && (gAborting == 0)) { 270 CHECK(!IsSharedHeld(self)) << *this; 271 } 272 } 273 274 // Id associated with exclusive owner. 275 uint64_t GetExclusiveOwnerTid() const; 276 277 virtual void Dump(std::ostream& os) const; 278 279 private: 280#if ART_USE_FUTEXES 281 // -1 implies held exclusive, +ve shared held by state_ many owners. 282 volatile int32_t state_; 283 // Exclusive owner. 284 volatile uint64_t exclusive_owner_; 285 // Pending readers. 286 volatile int32_t num_pending_readers_; 287 // Pending writers. 288 volatile int32_t num_pending_writers_; 289#else 290 pthread_rwlock_t rwlock_; 291#endif 292 DISALLOW_COPY_AND_ASSIGN(ReaderWriterMutex); 293}; 294 295// ConditionVariables allow threads to queue and sleep. Threads may then be resumed individually 296// (Signal) or all at once (Broadcast). 297class ConditionVariable { 298 public: 299 explicit ConditionVariable(const char* name, Mutex& mutex); 300 ~ConditionVariable(); 301 302 void Broadcast(Thread* self); 303 void Signal(Thread* self); 304 // TODO: No thread safety analysis on Wait and TimedWait as they call mutex operations via their 305 // pointer copy, thereby defeating annotalysis. 306 void Wait(Thread* self) NO_THREAD_SAFETY_ANALYSIS; 307 void TimedWait(Thread* self, int64_t ms, int32_t ns) NO_THREAD_SAFETY_ANALYSIS; 308 // Variant of Wait that should be used with caution. Doesn't validate that no mutexes are held 309 // when waiting. 310 // TODO: remove this. 311 void WaitHoldingLocks(Thread* self) NO_THREAD_SAFETY_ANALYSIS; 312 313 private: 314 const char* const name_; 315 // The Mutex being used by waiters. It is an error to mix condition variables between different 316 // Mutexes. 317 Mutex& guard_; 318#if ART_USE_FUTEXES 319 // A counter that is modified by signals and broadcasts. This ensures that when a waiter gives up 320 // their Mutex and another thread takes it and signals, the waiting thread observes that sequence_ 321 // changed and doesn't enter the wait. Modified while holding guard_, but is read by futex wait 322 // without guard_ held. 323 volatile int32_t sequence_; 324 // Number of threads that have come into to wait, not the length of the waiters on the futex as 325 // waiters may have been requeued onto guard_. Guarded by guard_. 326 volatile int32_t num_waiters_; 327#else 328 pthread_cond_t cond_; 329#endif 330 DISALLOW_COPY_AND_ASSIGN(ConditionVariable); 331}; 332 333// Scoped locker/unlocker for a regular Mutex that acquires mu upon construction and releases it 334// upon destruction. 335class SCOPED_LOCKABLE MutexLock { 336 public: 337 explicit MutexLock(Thread* self, Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : self_(self), mu_(mu) { 338 mu_.ExclusiveLock(self_); 339 } 340 341 ~MutexLock() UNLOCK_FUNCTION() { 342 mu_.ExclusiveUnlock(self_); 343 } 344 345 private: 346 Thread* const self_; 347 Mutex& mu_; 348 DISALLOW_COPY_AND_ASSIGN(MutexLock); 349}; 350// Catch bug where variable name is omitted. "MutexLock (lock);" instead of "MutexLock mu(lock)". 351#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_declaration_missing_variable_name) 352 353// Scoped locker/unlocker for a ReaderWriterMutex that acquires read access to mu upon 354// construction and releases it upon destruction. 355class SCOPED_LOCKABLE ReaderMutexLock { 356 public: 357 explicit ReaderMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : 358 self_(self), mu_(mu) { 359 mu_.SharedLock(self_); 360 } 361 362 ~ReaderMutexLock() UNLOCK_FUNCTION() { 363 mu_.SharedUnlock(self_); 364 } 365 366 private: 367 Thread* const self_; 368 ReaderWriterMutex& mu_; 369 DISALLOW_COPY_AND_ASSIGN(ReaderMutexLock); 370}; 371// Catch bug where variable name is omitted. "ReaderMutexLock (lock);" instead of 372// "ReaderMutexLock mu(lock)". 373#define ReaderMutexLock(x) COMPILE_ASSERT(0, reader_mutex_lock_declaration_missing_variable_name) 374 375// Scoped locker/unlocker for a ReaderWriterMutex that acquires write access to mu upon 376// construction and releases it upon destruction. 377class SCOPED_LOCKABLE WriterMutexLock { 378 public: 379 explicit WriterMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : 380 self_(self), mu_(mu) { 381 mu_.ExclusiveLock(self_); 382 } 383 384 ~WriterMutexLock() UNLOCK_FUNCTION() { 385 mu_.ExclusiveUnlock(self_); 386 } 387 388 private: 389 Thread* const self_; 390 ReaderWriterMutex& mu_; 391 DISALLOW_COPY_AND_ASSIGN(WriterMutexLock); 392}; 393// Catch bug where variable name is omitted. "WriterMutexLock (lock);" instead of 394// "WriterMutexLock mu(lock)". 395#define WriterMutexLock(x) COMPILE_ASSERT(0, writer_mutex_lock_declaration_missing_variable_name) 396 397} // namespace art 398 399#endif // ART_RUNTIME_BASE_MUTEX_H_ 400