mutex.h revision 50b35e2fd1a68cd1240e4a9d9f363e11764957d1
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_SRC_MUTEX_H_ 18#define ART_SRC_MUTEX_H_ 19 20#include <pthread.h> 21#include <stdint.h> 22 23#include <iosfwd> 24#include <string> 25 26#include "globals.h" 27#include "locks.h" 28#include "logging.h" 29#include "macros.h" 30 31#if defined(__APPLE__) 32#define ART_USE_FUTEXES 0 33#else 34#define ART_USE_FUTEXES 0 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 44namespace art { 45 46class Thread; 47 48const bool kDebugLocking = kIsDebugBuild; 49 50// Base class for all Mutex implementations 51class BaseMutex { 52 public: 53 const std::string& GetName() const { 54 return name_; 55 } 56 57 virtual bool IsMutex() const { return false; } 58 virtual bool IsReaderWriterMutex() const { return false; } 59 60 protected: 61 friend class ConditionVariable; 62 63 BaseMutex(const char* name, LockLevel level); 64 virtual ~BaseMutex() {} 65 void RegisterAsLocked(Thread* self); 66 void RegisterAsUnlocked(Thread* self); 67 void CheckSafeToWait(Thread* self); 68 69 const LockLevel level_; // Support for lock hierarchy. 70 const std::string name_; 71}; 72 73// A Mutex is used to achieve mutual exclusion between threads. A Mutex can be used to gain 74// exclusive access to what it guards. A Mutex can be in one of two states: 75// - Free - not owned by any thread, 76// - Exclusive - owned by a single thread. 77// 78// The effect of locking and unlocking operations on the state is: 79// State | ExclusiveLock | ExclusiveUnlock 80// ------------------------------------------- 81// Free | Exclusive | error 82// Exclusive | Block* | Free 83// * Mutex is not reentrant and so an attempt to ExclusiveLock on the same thread will result in 84// an error. Being non-reentrant simplifies Waiting on ConditionVariables. 85std::ostream& operator<<(std::ostream& os, const Mutex& mu); 86class LOCKABLE Mutex : public BaseMutex { 87 public: 88 explicit Mutex(const char* name, LockLevel level = kDefaultMutexLevel, bool recursive = false); 89 ~Mutex(); 90 91 virtual bool IsMutex() const { return true; } 92 93 // Block until mutex is free then acquire exclusive access. 94 void ExclusiveLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION(); 95 void Lock(Thread* self) EXCLUSIVE_LOCK_FUNCTION() { ExclusiveLock(self); } 96 97 // Returns true if acquires exclusive access, false otherwise. 98 bool ExclusiveTryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true); 99 bool TryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true) { return ExclusiveTryLock(self); } 100 101 // Release exclusive access. 102 void ExclusiveUnlock(Thread* self) UNLOCK_FUNCTION(); 103 void Unlock(Thread* self) UNLOCK_FUNCTION() { ExclusiveUnlock(self); } 104 105 // Is the current thread the exclusive holder of the Mutex. 106 bool IsExclusiveHeld(const Thread* self) const; 107 108 // Assert that the Mutex is exclusively held by the current thread. 109 void AssertExclusiveHeld(const Thread* self) { 110 if (kDebugLocking) { 111 CHECK(IsExclusiveHeld(self)) << *this; 112 } 113 } 114 void AssertHeld(const Thread* self) { AssertExclusiveHeld(self); } 115 116 // Assert that the Mutex is not held by the current thread. 117 void AssertNotHeldExclusive(const Thread* self) { 118 if (kDebugLocking) { 119 CHECK(!IsExclusiveHeld(self)) << *this; 120 } 121 } 122 void AssertNotHeld(const Thread* self) { AssertNotHeldExclusive(self); } 123 124 // Id associated with exclusive owner. 125 uint64_t GetExclusiveOwnerTid() const; 126 127 // Returns how many times this Mutex has been locked, it is better to use AssertHeld/NotHeld. 128 unsigned int GetDepth() const { 129 return recursion_count_; 130 } 131 132 std::string Dump() const; 133 134 private: 135 pthread_mutex_t mutex_; 136 const bool recursive_; // Can the lock be recursively held? 137 unsigned int recursion_count_; 138 friend class ConditionVariable; 139 friend class MutexTester; 140 DISALLOW_COPY_AND_ASSIGN(Mutex); 141}; 142 143// A ReaderWriterMutex is used to achieve mutual exclusion between threads, similar to a Mutex. 144// Unlike a Mutex a ReaderWriterMutex can be used to gain exclusive (writer) or shared (reader) 145// access to what it guards. A flaw in relation to a Mutex is that it cannot be used with a 146// condition variable. A ReaderWriterMutex can be in one of three states: 147// - Free - not owned by any thread, 148// - Exclusive - owned by a single thread, 149// - Shared(n) - shared amongst n threads. 150// 151// The effect of locking and unlocking operations on the state is: 152// 153// State | ExclusiveLock | ExclusiveUnlock | SharedLock | SharedUnlock 154// ---------------------------------------------------------------------------- 155// Free | Exclusive | error | SharedLock(1) | error 156// Exclusive | Block | Free | Block | error 157// Shared(n) | Block | error | SharedLock(n+1)* | Shared(n-1) or Free 158// * for large values of n the SharedLock may block. 159std::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu); 160class LOCKABLE ReaderWriterMutex : public BaseMutex { 161 public: 162 explicit ReaderWriterMutex(const char* name, LockLevel level = kDefaultMutexLevel); 163 ~ReaderWriterMutex(); 164 165 virtual bool IsReaderWriterMutex() const { return true; } 166 167 // Block until ReaderWriterMutex is free then acquire exclusive access. 168 void ExclusiveLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION(); 169 void WriterLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION() { ExclusiveLock(self); } 170 171 // Release exclusive access. 172 void ExclusiveUnlock(Thread* self) UNLOCK_FUNCTION(); 173 void WriterUnlock(Thread* self) UNLOCK_FUNCTION() { ExclusiveUnlock(self); } 174 175 // Block until ReaderWriterMutex is free and acquire exclusive access. Returns true on success 176 // or false if timeout is reached. 177#if HAVE_TIMED_RWLOCK 178 bool ExclusiveLockWithTimeout(Thread* self, const timespec& abs_timeout) 179 EXCLUSIVE_TRYLOCK_FUNCTION(true); 180#endif 181 182 // Block until ReaderWriterMutex is shared or free then acquire a share on the access. 183 void SharedLock(Thread* self) SHARED_LOCK_FUNCTION(); 184 void ReaderLock(Thread* self) SHARED_LOCK_FUNCTION() { SharedLock(self); } 185 186 // Try to acquire share of ReaderWriterMutex. 187 bool SharedTryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true); 188 189 // Release a share of the access. 190 void SharedUnlock(Thread* self) UNLOCK_FUNCTION(); 191 void ReaderUnlock(Thread* self) UNLOCK_FUNCTION() { SharedUnlock(self); } 192 193 // Is the current thread the exclusive holder of the ReaderWriterMutex. 194 bool IsExclusiveHeld(const Thread* self) const; 195 196 // Assert the current thread has exclusive access to the ReaderWriterMutex. 197 void AssertExclusiveHeld(const Thread* self) { 198 if (kDebugLocking) { 199 CHECK(IsExclusiveHeld(self)) << *this; 200 } 201 } 202 void AssertWriterHeld(const Thread* self) { AssertExclusiveHeld(self); } 203 204 // Assert the current thread doesn't have exclusive access to the ReaderWriterMutex. 205 void AssertNotExclusiveHeld(const Thread* self) { 206 if (kDebugLocking) { 207 CHECK(!IsExclusiveHeld(self)); 208 } 209 } 210 void AssertNotWriterHeld(const Thread* self) { AssertNotExclusiveHeld(self); } 211 212 // Is the current thread a shared holder of the ReaderWriterMutex. 213 bool IsSharedHeld(const Thread* self) const; 214 215 // Assert the current thread has shared access to the ReaderWriterMutex. 216 void AssertSharedHeld(const Thread* self) { 217 if (kDebugLocking) { 218 CHECK(IsSharedHeld(self)) << *this; 219 } 220 } 221 void AssertReaderHeld(const Thread* self) { AssertSharedHeld(self); } 222 223 // Assert the current thread doesn't hold this ReaderWriterMutex either in shared or exclusive 224 // mode. 225 void AssertNotHeld(const Thread* self) { 226 if (kDebugLocking) { 227 CHECK(!IsSharedHeld(self)) << *this; 228 } 229 } 230 231 // Id associated with exclusive owner. 232 uint64_t GetExclusiveOwnerTid() const; 233 234 std::string Dump() const; 235 236 private: 237#if ART_USE_FUTEXES 238 // -1 implies held exclusive, +ve shared held by state_ many owners. 239 volatile int32_t state_; 240 // Exclusive owner. 241 volatile uint64_t exclusive_owner_; 242 // Pending readers. 243 volatile int32_t num_pending_readers_; 244 // Pending writers. 245 volatile int32_t num_pending_writers_; 246#else 247 pthread_rwlock_t rwlock_; 248#endif 249 friend class MutexTester; 250 DISALLOW_COPY_AND_ASSIGN(ReaderWriterMutex); 251}; 252 253// ConditionVariables allow threads to queue and sleep. Threads may then be resumed individually 254// (Signal) or all at once (Broadcast). 255class ConditionVariable { 256 public: 257 explicit ConditionVariable(const std::string& name); 258 ~ConditionVariable(); 259 260 void Broadcast(); 261 void Signal(); 262 void Wait(Thread* self, Mutex& mutex); 263 void TimedWait(Thread* self, Mutex& mutex, const timespec& ts); 264 265 private: 266 pthread_cond_t cond_; 267 std::string name_; 268 DISALLOW_COPY_AND_ASSIGN(ConditionVariable); 269}; 270 271// Scoped locker/unlocker for a regular Mutex that acquires mu upon construction and releases it 272// upon destruction. 273class SCOPED_LOCKABLE MutexLock { 274 public: 275 explicit MutexLock(Thread* self, Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : self_(self), mu_(mu) { 276 mu_.ExclusiveLock(self_); 277 } 278 279 ~MutexLock() UNLOCK_FUNCTION() { 280 mu_.ExclusiveUnlock(self_); 281 } 282 283 private: 284 Thread* const self_; 285 Mutex& mu_; 286 DISALLOW_COPY_AND_ASSIGN(MutexLock); 287}; 288// Catch bug where variable name is omitted. "MutexLock (lock);" instead of "MutexLock mu(lock)". 289#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_declaration_missing_variable_name) 290 291// Scoped locker/unlocker for a ReaderWriterMutex that acquires read access to mu upon 292// construction and releases it upon destruction. 293class SCOPED_LOCKABLE ReaderMutexLock { 294 public: 295 explicit ReaderMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : 296 self_(self), mu_(mu) { 297 mu_.SharedLock(self_); 298 } 299 300 ~ReaderMutexLock() UNLOCK_FUNCTION() { 301 mu_.SharedUnlock(self_); 302 } 303 304 private: 305 Thread* const self_; 306 ReaderWriterMutex& mu_; 307 DISALLOW_COPY_AND_ASSIGN(ReaderMutexLock); 308}; 309// Catch bug where variable name is omitted. "ReaderMutexLock (lock);" instead of 310// "ReaderMutexLock mu(lock)". 311#define ReaderMutexLock(x) COMPILE_ASSERT(0, reader_mutex_lock_declaration_missing_variable_name) 312 313// Scoped locker/unlocker for a ReaderWriterMutex that acquires write access to mu upon 314// construction and releases it upon destruction. 315class SCOPED_LOCKABLE WriterMutexLock { 316 public: 317 explicit WriterMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : 318 self_(self), mu_(mu) { 319 mu_.ExclusiveLock(self_); 320 } 321 322 ~WriterMutexLock() UNLOCK_FUNCTION() { 323 mu_.ExclusiveUnlock(self_); 324 } 325 326 private: 327 Thread* const self_; 328 ReaderWriterMutex& mu_; 329 DISALLOW_COPY_AND_ASSIGN(WriterMutexLock); 330}; 331// Catch bug where variable name is omitted. "WriterMutexLock (lock);" instead of 332// "WriterMutexLock mu(lock)". 333#define WriterMutexLock(x) COMPILE_ASSERT(0, writer_mutex_lock_declaration_missing_variable_name) 334 335} // namespace art 336 337#endif // ART_SRC_MUTEX_H_ 338