| Elliott Hughes | 8daa092 | 2011-09-11 13:46:25 -0700 | [diff] [blame] | 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 |  | 
| Brian Carlstrom | fc0e321 | 2013-07-17 14:40:12 -0700 | [diff] [blame] | 17 | #ifndef ART_RUNTIME_BASE_MUTEX_H_ | 
 | 18 | #define ART_RUNTIME_BASE_MUTEX_H_ | 
| Elliott Hughes | 8daa092 | 2011-09-11 13:46:25 -0700 | [diff] [blame] | 19 |  | 
 | 20 | #include <pthread.h> | 
| Brian Carlstrom | cd74c4b | 2012-01-23 13:21:00 -0800 | [diff] [blame] | 21 | #include <stdint.h> | 
| Elliott Hughes | ffb465f | 2012-03-01 18:46:05 -0800 | [diff] [blame] | 22 |  | 
 | 23 | #include <iosfwd> | 
| Elliott Hughes | 8daa092 | 2011-09-11 13:46:25 -0700 | [diff] [blame] | 24 | #include <string> | 
 | 25 |  | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 26 | #include "atomic.h" | 
| Elliott Hughes | 07ed66b | 2012-12-12 18:34:25 -0800 | [diff] [blame] | 27 | #include "base/logging.h" | 
| Elliott Hughes | 7616005 | 2012-12-12 16:31:20 -0800 | [diff] [blame] | 28 | #include "base/macros.h" | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 29 | #include "globals.h" | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 30 |  | 
| Ian Rogers | ab47016 | 2012-09-29 23:06:53 -0700 | [diff] [blame] | 31 | #if defined(__APPLE__) | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 32 | #define ART_USE_FUTEXES 0 | 
| Ian Rogers | ab47016 | 2012-09-29 23:06:53 -0700 | [diff] [blame] | 33 | #else | 
| Chris Dearman | c014178 | 2013-11-14 17:29:21 -0800 | [diff] [blame] | 34 | #define ART_USE_FUTEXES 1 | 
| Ian Rogers | ab47016 | 2012-09-29 23:06:53 -0700 | [diff] [blame] | 35 | #endif | 
| Elliott Hughes | 8daa092 | 2011-09-11 13:46:25 -0700 | [diff] [blame] | 36 |  | 
| Ian Rogers | 66aee5c | 2012-08-15 17:17:47 -0700 | [diff] [blame] | 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 |  | 
| Elliott Hughes | 8daa092 | 2011-09-11 13:46:25 -0700 | [diff] [blame] | 44 | namespace art { | 
 | 45 |  | 
| Ian Rogers | 719d1a3 | 2014-03-06 12:13:39 -0800 | [diff] [blame^] | 46 | class LOCKABLE ReaderWriterMutex; | 
| Ian Rogers | 56edc43 | 2013-01-18 16:51:51 -0800 | [diff] [blame] | 47 | class ScopedContentionRecorder; | 
| Ian Rogers | 50b35e2 | 2012-10-04 10:09:15 -0700 | [diff] [blame] | 48 | class Thread; | 
 | 49 |  | 
| Ian Rogers | 719d1a3 | 2014-03-06 12:13:39 -0800 | [diff] [blame^] | 50 | // LockLevel is used to impose a lock hierarchy [1] where acquisition of a Mutex at a higher or | 
 | 51 | // equal level to a lock a thread holds is invalid. The lock hierarchy achieves a cycle free | 
 | 52 | // partial ordering and thereby cause deadlock situations to fail checks. | 
 | 53 | // | 
 | 54 | // [1] http://www.drdobbs.com/parallel/use-lock-hierarchies-to-avoid-deadlock/204801163 | 
 | 55 | enum LockLevel { | 
 | 56 |   kLoggingLock = 0, | 
 | 57 |   kUnexpectedSignalLock, | 
 | 58 |   kThreadSuspendCountLock, | 
 | 59 |   kAbortLock, | 
 | 60 |   kJdwpSocketLock, | 
 | 61 |   kRosAllocGlobalLock, | 
 | 62 |   kRosAllocBracketLock, | 
 | 63 |   kRosAllocBulkFreeLock, | 
 | 64 |   kAllocSpaceLock, | 
 | 65 |   kDexFileMethodInlinerLock, | 
 | 66 |   kDexFileToMethodInlinerMapLock, | 
 | 67 |   kMarkSweepMarkStackLock, | 
 | 68 |   kTransactionLogLock, | 
 | 69 |   kInternTableLock, | 
 | 70 |   kMonitorPoolLock, | 
 | 71 |   kDefaultMutexLevel, | 
 | 72 |   kMarkSweepLargeObjectLock, | 
 | 73 |   kPinTableLock, | 
 | 74 |   kLoadLibraryLock, | 
 | 75 |   kJdwpObjectRegistryLock, | 
 | 76 |   kClassLinkerClassesLock, | 
 | 77 |   kBreakpointLock, | 
 | 78 |   kMonitorLock, | 
 | 79 |   kThreadListLock, | 
 | 80 |   kBreakpointInvokeLock, | 
 | 81 |   kDeoptimizationLock, | 
 | 82 |   kTraceLock, | 
 | 83 |   kProfilerLock, | 
 | 84 |   kJdwpEventListLock, | 
 | 85 |   kJdwpAttachLock, | 
 | 86 |   kJdwpStartLock, | 
 | 87 |   kRuntimeShutdownLock, | 
 | 88 |   kHeapBitmapLock, | 
 | 89 |   kMutatorLock, | 
 | 90 |   kZygoteCreationLock, | 
 | 91 |  | 
 | 92 |   kLockLevelCount  // Must come last. | 
 | 93 | }; | 
 | 94 | std::ostream& operator<<(std::ostream& os, const LockLevel& rhs); | 
 | 95 |  | 
| Brian Carlstrom | 2e250c8 | 2013-08-14 18:08:52 -0700 | [diff] [blame] | 96 | const bool kDebugLocking = kIsDebugBuild; | 
| Ian Rogers | 25fd14b | 2012-09-05 10:56:38 -0700 | [diff] [blame] | 97 |  | 
| Hiroshi Yamauchi | 1afde13 | 2013-08-06 17:09:30 -0700 | [diff] [blame] | 98 | // Record Log contention information, dumpable via SIGQUIT. | 
 | 99 | #ifdef ART_USE_FUTEXES | 
| Jeff Hao | 08f2e7b | 2013-09-09 16:44:02 -0700 | [diff] [blame] | 100 | // To enable lock contention logging, set this to true. | 
 | 101 | const bool kLogLockContentions = false; | 
| Hiroshi Yamauchi | 1afde13 | 2013-08-06 17:09:30 -0700 | [diff] [blame] | 102 | #else | 
 | 103 | // Keep this false as lock contention logging is supported only with | 
 | 104 | // futex. | 
 | 105 | const bool kLogLockContentions = false; | 
 | 106 | #endif | 
| Ian Rogers | d9c4fc9 | 2013-10-01 19:45:43 -0700 | [diff] [blame] | 107 | const size_t kContentionLogSize = 4; | 
| Hiroshi Yamauchi | 1afde13 | 2013-08-06 17:09:30 -0700 | [diff] [blame] | 108 | const size_t kContentionLogDataSize = kLogLockContentions ? 1 : 0; | 
 | 109 | const size_t kAllMutexDataSize = kLogLockContentions ? 1 : 0; | 
 | 110 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 111 | // Base class for all Mutex implementations | 
 | 112 | class BaseMutex { | 
 | 113 |  public: | 
| Ian Rogers | bab7496 | 2013-04-19 10:04:10 -0700 | [diff] [blame] | 114 |   const char* GetName() const { | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 115 |     return name_; | 
 | 116 |   } | 
 | 117 |  | 
 | 118 |   virtual bool IsMutex() const { return false; } | 
 | 119 |   virtual bool IsReaderWriterMutex() const { return false; } | 
 | 120 |  | 
| Ian Rogers | 56edc43 | 2013-01-18 16:51:51 -0800 | [diff] [blame] | 121 |   virtual void Dump(std::ostream& os) const = 0; | 
 | 122 |  | 
 | 123 |   static void DumpAll(std::ostream& os); | 
 | 124 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 125 |  protected: | 
 | 126 |   friend class ConditionVariable; | 
 | 127 |  | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 128 |   BaseMutex(const char* name, LockLevel level); | 
| Ian Rogers | 56edc43 | 2013-01-18 16:51:51 -0800 | [diff] [blame] | 129 |   virtual ~BaseMutex(); | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 130 |   void RegisterAsLocked(Thread* self); | 
 | 131 |   void RegisterAsUnlocked(Thread* self); | 
 | 132 |   void CheckSafeToWait(Thread* self); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 133 |  | 
| Ian Rogers | 56edc43 | 2013-01-18 16:51:51 -0800 | [diff] [blame] | 134 |   friend class ScopedContentionRecorder; | 
 | 135 |  | 
| Hiroshi Yamauchi | 1afde13 | 2013-08-06 17:09:30 -0700 | [diff] [blame] | 136 |   void RecordContention(uint64_t blocked_tid, uint64_t owner_tid, uint64_t nano_time_blocked); | 
| Ian Rogers | 56edc43 | 2013-01-18 16:51:51 -0800 | [diff] [blame] | 137 |   void DumpContention(std::ostream& os) const; | 
 | 138 |  | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 139 |   const LockLevel level_;  // Support for lock hierarchy. | 
| Ian Rogers | bab7496 | 2013-04-19 10:04:10 -0700 | [diff] [blame] | 140 |   const char* const name_; | 
| Hiroshi Yamauchi | 1afde13 | 2013-08-06 17:09:30 -0700 | [diff] [blame] | 141 |  | 
| Ian Rogers | 56edc43 | 2013-01-18 16:51:51 -0800 | [diff] [blame] | 142 |   // A log entry that records contention but makes no guarantee that either tid will be held live. | 
 | 143 |   struct ContentionLogEntry { | 
 | 144 |     ContentionLogEntry() : blocked_tid(0), owner_tid(0) {} | 
 | 145 |     uint64_t blocked_tid; | 
 | 146 |     uint64_t owner_tid; | 
 | 147 |     AtomicInteger count; | 
 | 148 |   }; | 
| Hiroshi Yamauchi | 1afde13 | 2013-08-06 17:09:30 -0700 | [diff] [blame] | 149 |   struct ContentionLogData { | 
 | 150 |     ContentionLogEntry contention_log[kContentionLogSize]; | 
 | 151 |     // The next entry in the contention log to be updated. Value ranges from 0 to | 
 | 152 |     // kContentionLogSize - 1. | 
 | 153 |     AtomicInteger cur_content_log_entry; | 
 | 154 |     // Number of times the Mutex has been contended. | 
 | 155 |     AtomicInteger contention_count; | 
 | 156 |     // Sum of time waited by all contenders in ns. | 
 | 157 |     volatile uint64_t wait_time; | 
 | 158 |     void AddToWaitTime(uint64_t value); | 
 | 159 |     ContentionLogData() : wait_time(0) {} | 
 | 160 |   }; | 
 | 161 |   ContentionLogData contetion_log_data_[kContentionLogDataSize]; | 
 | 162 |  | 
 | 163 |  public: | 
 | 164 |   bool HasEverContended() const { | 
 | 165 |     if (kLogLockContentions) { | 
 | 166 |       return contetion_log_data_->contention_count > 0; | 
 | 167 |     } | 
 | 168 |     return false; | 
 | 169 |   } | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 170 | }; | 
 | 171 |  | 
 | 172 | // A Mutex is used to achieve mutual exclusion between threads. A Mutex can be used to gain | 
 | 173 | // exclusive access to what it guards. A Mutex can be in one of two states: | 
 | 174 | // - Free - not owned by any thread, | 
 | 175 | // - Exclusive - owned by a single thread. | 
 | 176 | // | 
 | 177 | // The effect of locking and unlocking operations on the state is: | 
 | 178 | // State     | ExclusiveLock | ExclusiveUnlock | 
 | 179 | // ------------------------------------------- | 
 | 180 | // Free      | Exclusive     | error | 
 | 181 | // Exclusive | Block*        | Free | 
 | 182 | // * Mutex is not reentrant and so an attempt to ExclusiveLock on the same thread will result in | 
 | 183 | //   an error. Being non-reentrant simplifies Waiting on ConditionVariables. | 
| Ian Rogers | 01ae580 | 2012-09-28 16:14:01 -0700 | [diff] [blame] | 184 | std::ostream& operator<<(std::ostream& os, const Mutex& mu); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 185 | class LOCKABLE Mutex : public BaseMutex { | 
 | 186 |  public: | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 187 |   explicit Mutex(const char* name, LockLevel level = kDefaultMutexLevel, bool recursive = false); | 
| Elliott Hughes | 8daa092 | 2011-09-11 13:46:25 -0700 | [diff] [blame] | 188 |   ~Mutex(); | 
 | 189 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 190 |   virtual bool IsMutex() const { return true; } | 
| Elliott Hughes | 8daa092 | 2011-09-11 13:46:25 -0700 | [diff] [blame] | 191 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 192 |   // Block until mutex is free then acquire exclusive access. | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 193 |   void ExclusiveLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION(); | 
 | 194 |   void Lock(Thread* self) EXCLUSIVE_LOCK_FUNCTION() {  ExclusiveLock(self); } | 
| Elliott Hughes | 8daa092 | 2011-09-11 13:46:25 -0700 | [diff] [blame] | 195 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 196 |   // Returns true if acquires exclusive access, false otherwise. | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 197 |   bool ExclusiveTryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true); | 
 | 198 |   bool TryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true) { return ExclusiveTryLock(self); } | 
| Elliott Hughes | 8daa092 | 2011-09-11 13:46:25 -0700 | [diff] [blame] | 199 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 200 |   // Release exclusive access. | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 201 |   void ExclusiveUnlock(Thread* self) UNLOCK_FUNCTION(); | 
 | 202 |   void Unlock(Thread* self) UNLOCK_FUNCTION() {  ExclusiveUnlock(self); } | 
| Elliott Hughes | 8daa092 | 2011-09-11 13:46:25 -0700 | [diff] [blame] | 203 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 204 |   // Is the current thread the exclusive holder of the Mutex. | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 205 |   bool IsExclusiveHeld(const Thread* self) const; | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 206 |  | 
 | 207 |   // Assert that the Mutex is exclusively held by the current thread. | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 208 |   void AssertExclusiveHeld(const Thread* self) { | 
| Anwar Ghuloum | 3c539ff | 2013-06-20 08:58:23 -0700 | [diff] [blame] | 209 |     if (kDebugLocking && (gAborting == 0)) { | 
| Ian Rogers | 01ae580 | 2012-09-28 16:14:01 -0700 | [diff] [blame] | 210 |       CHECK(IsExclusiveHeld(self)) << *this; | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 211 |     } | 
 | 212 |   } | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 213 |   void AssertHeld(const Thread* self) { AssertExclusiveHeld(self); } | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 214 |  | 
 | 215 |   // Assert that the Mutex is not held by the current thread. | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 216 |   void AssertNotHeldExclusive(const Thread* self) { | 
| Anwar Ghuloum | 3c539ff | 2013-06-20 08:58:23 -0700 | [diff] [blame] | 217 |     if (kDebugLocking && (gAborting == 0)) { | 
| Ian Rogers | 01ae580 | 2012-09-28 16:14:01 -0700 | [diff] [blame] | 218 |       CHECK(!IsExclusiveHeld(self)) << *this; | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 219 |     } | 
 | 220 |   } | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 221 |   void AssertNotHeld(const Thread* self) { AssertNotHeldExclusive(self); } | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 222 |  | 
 | 223 |   // Id associated with exclusive owner. | 
 | 224 |   uint64_t GetExclusiveOwnerTid() const; | 
 | 225 |  | 
 | 226 |   // Returns how many times this Mutex has been locked, it is better to use AssertHeld/NotHeld. | 
 | 227 |   unsigned int GetDepth() const { | 
 | 228 |     return recursion_count_; | 
 | 229 |   } | 
| Elliott Hughes | accd83d | 2011-10-17 14:25:58 -0700 | [diff] [blame] | 230 |  | 
| Ian Rogers | 56edc43 | 2013-01-18 16:51:51 -0800 | [diff] [blame] | 231 |   virtual void Dump(std::ostream& os) const; | 
| Ian Rogers | 01ae580 | 2012-09-28 16:14:01 -0700 | [diff] [blame] | 232 |  | 
| Elliott Hughes | accd83d | 2011-10-17 14:25:58 -0700 | [diff] [blame] | 233 |  private: | 
| Ian Rogers | c604d73 | 2012-10-14 16:09:54 -0700 | [diff] [blame] | 234 | #if ART_USE_FUTEXES | 
 | 235 |   // 0 is unheld, 1 is held. | 
 | 236 |   volatile int32_t state_; | 
 | 237 |   // Exclusive owner. | 
 | 238 |   volatile uint64_t exclusive_owner_; | 
 | 239 |   // Number of waiting contenders. | 
| Ian Rogers | b122a4b | 2013-11-19 18:00:50 -0800 | [diff] [blame] | 240 |   AtomicInteger num_contenders_; | 
| Ian Rogers | c604d73 | 2012-10-14 16:09:54 -0700 | [diff] [blame] | 241 | #else | 
| Elliott Hughes | 8daa092 | 2011-09-11 13:46:25 -0700 | [diff] [blame] | 242 |   pthread_mutex_t mutex_; | 
| Ian Rogers | c604d73 | 2012-10-14 16:09:54 -0700 | [diff] [blame] | 243 | #endif | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 244 |   const bool recursive_;  // Can the lock be recursively held? | 
 | 245 |   unsigned int recursion_count_; | 
| Elliott Hughes | f149843 | 2012-03-28 19:34:27 -0700 | [diff] [blame] | 246 |   friend class ConditionVariable; | 
| Elliott Hughes | 8daa092 | 2011-09-11 13:46:25 -0700 | [diff] [blame] | 247 |   DISALLOW_COPY_AND_ASSIGN(Mutex); | 
 | 248 | }; | 
 | 249 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 250 | // A ReaderWriterMutex is used to achieve mutual exclusion between threads, similar to a Mutex. | 
 | 251 | // Unlike a Mutex a ReaderWriterMutex can be used to gain exclusive (writer) or shared (reader) | 
 | 252 | // access to what it guards. A flaw in relation to a Mutex is that it cannot be used with a | 
 | 253 | // condition variable. A ReaderWriterMutex can be in one of three states: | 
 | 254 | // - Free - not owned by any thread, | 
 | 255 | // - Exclusive - owned by a single thread, | 
 | 256 | // - Shared(n) - shared amongst n threads. | 
 | 257 | // | 
 | 258 | // The effect of locking and unlocking operations on the state is: | 
 | 259 | // | 
 | 260 | // State     | ExclusiveLock | ExclusiveUnlock | SharedLock       | SharedUnlock | 
 | 261 | // ---------------------------------------------------------------------------- | 
 | 262 | // Free      | Exclusive     | error           | SharedLock(1)    | error | 
 | 263 | // Exclusive | Block         | Free            | Block            | error | 
 | 264 | // Shared(n) | Block         | error           | SharedLock(n+1)* | Shared(n-1) or Free | 
 | 265 | // * for large values of n the SharedLock may block. | 
| Ian Rogers | 01ae580 | 2012-09-28 16:14:01 -0700 | [diff] [blame] | 266 | std::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 267 | class LOCKABLE ReaderWriterMutex : public BaseMutex { | 
| Elliott Hughes | 8daa092 | 2011-09-11 13:46:25 -0700 | [diff] [blame] | 268 |  public: | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 269 |   explicit ReaderWriterMutex(const char* name, LockLevel level = kDefaultMutexLevel); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 270 |   ~ReaderWriterMutex(); | 
 | 271 |  | 
 | 272 |   virtual bool IsReaderWriterMutex() const { return true; } | 
 | 273 |  | 
 | 274 |   // Block until ReaderWriterMutex is free then acquire exclusive access. | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 275 |   void ExclusiveLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION(); | 
 | 276 |   void WriterLock(Thread* self) EXCLUSIVE_LOCK_FUNCTION() {  ExclusiveLock(self); } | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 277 |  | 
 | 278 |   // Release exclusive access. | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 279 |   void ExclusiveUnlock(Thread* self) UNLOCK_FUNCTION(); | 
 | 280 |   void WriterUnlock(Thread* self) UNLOCK_FUNCTION() {  ExclusiveUnlock(self); } | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 281 |  | 
 | 282 |   // Block until ReaderWriterMutex is free and acquire exclusive access. Returns true on success | 
 | 283 |   // or false if timeout is reached. | 
| Ian Rogers | 66aee5c | 2012-08-15 17:17:47 -0700 | [diff] [blame] | 284 | #if HAVE_TIMED_RWLOCK | 
| Ian Rogers | c604d73 | 2012-10-14 16:09:54 -0700 | [diff] [blame] | 285 |   bool ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32_t ns) | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 286 |       EXCLUSIVE_TRYLOCK_FUNCTION(true); | 
| Ian Rogers | 66aee5c | 2012-08-15 17:17:47 -0700 | [diff] [blame] | 287 | #endif | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 288 |  | 
 | 289 |   // Block until ReaderWriterMutex is shared or free then acquire a share on the access. | 
| Ian Rogers | 1ffa32f | 2013-02-05 18:29:08 -0800 | [diff] [blame] | 290 |   void SharedLock(Thread* self) SHARED_LOCK_FUNCTION() ALWAYS_INLINE; | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 291 |   void ReaderLock(Thread* self) SHARED_LOCK_FUNCTION() { SharedLock(self); } | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 292 |  | 
 | 293 |   // Try to acquire share of ReaderWriterMutex. | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 294 |   bool SharedTryLock(Thread* self) EXCLUSIVE_TRYLOCK_FUNCTION(true); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 295 |  | 
 | 296 |   // Release a share of the access. | 
| Ian Rogers | 1ffa32f | 2013-02-05 18:29:08 -0800 | [diff] [blame] | 297 |   void SharedUnlock(Thread* self) UNLOCK_FUNCTION() ALWAYS_INLINE; | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 298 |   void ReaderUnlock(Thread* self) UNLOCK_FUNCTION() { SharedUnlock(self); } | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 299 |  | 
 | 300 |   // Is the current thread the exclusive holder of the ReaderWriterMutex. | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 301 |   bool IsExclusiveHeld(const Thread* self) const; | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 302 |  | 
 | 303 |   // Assert the current thread has exclusive access to the ReaderWriterMutex. | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 304 |   void AssertExclusiveHeld(const Thread* self) { | 
| Sebastien Hertz | 702a85b | 2013-08-05 16:37:51 +0200 | [diff] [blame] | 305 |     if (kDebugLocking && (gAborting == 0)) { | 
| Ian Rogers | 01ae580 | 2012-09-28 16:14:01 -0700 | [diff] [blame] | 306 |       CHECK(IsExclusiveHeld(self)) << *this; | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 307 |     } | 
 | 308 |   } | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 309 |   void AssertWriterHeld(const Thread* self) { AssertExclusiveHeld(self); } | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 310 |  | 
 | 311 |   // Assert the current thread doesn't have exclusive access to the ReaderWriterMutex. | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 312 |   void AssertNotExclusiveHeld(const Thread* self) { | 
| Sebastien Hertz | 702a85b | 2013-08-05 16:37:51 +0200 | [diff] [blame] | 313 |     if (kDebugLocking && (gAborting == 0)) { | 
| Ian Rogers | e3359f7 | 2013-06-11 15:14:11 -0700 | [diff] [blame] | 314 |       CHECK(!IsExclusiveHeld(self)) << *this; | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 315 |     } | 
 | 316 |   } | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 317 |   void AssertNotWriterHeld(const Thread* self) { AssertNotExclusiveHeld(self); } | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 318 |  | 
 | 319 |   // Is the current thread a shared holder of the ReaderWriterMutex. | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 320 |   bool IsSharedHeld(const Thread* self) const; | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 321 |  | 
 | 322 |   // Assert the current thread has shared access to the ReaderWriterMutex. | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 323 |   void AssertSharedHeld(const Thread* self) { | 
| Sebastien Hertz | 702a85b | 2013-08-05 16:37:51 +0200 | [diff] [blame] | 324 |     if (kDebugLocking && (gAborting == 0)) { | 
| Ian Rogers | 23055dc | 2013-04-18 16:29:16 -0700 | [diff] [blame] | 325 |       // TODO: we can only assert this well when self != NULL. | 
 | 326 |       CHECK(IsSharedHeld(self) || self == NULL) << *this; | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 327 |     } | 
 | 328 |   } | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 329 |   void AssertReaderHeld(const Thread* self) { AssertSharedHeld(self); } | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 330 |  | 
 | 331 |   // Assert the current thread doesn't hold this ReaderWriterMutex either in shared or exclusive | 
 | 332 |   // mode. | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 333 |   void AssertNotHeld(const Thread* self) { | 
| Anwar Ghuloum | 3c539ff | 2013-06-20 08:58:23 -0700 | [diff] [blame] | 334 |     if (kDebugLocking && (gAborting == 0)) { | 
| Ian Rogers | 01ae580 | 2012-09-28 16:14:01 -0700 | [diff] [blame] | 335 |       CHECK(!IsSharedHeld(self)) << *this; | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 336 |     } | 
| Elliott Hughes | 8daa092 | 2011-09-11 13:46:25 -0700 | [diff] [blame] | 337 |   } | 
 | 338 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 339 |   // Id associated with exclusive owner. | 
 | 340 |   uint64_t GetExclusiveOwnerTid() const; | 
| Elliott Hughes | 8daa092 | 2011-09-11 13:46:25 -0700 | [diff] [blame] | 341 |  | 
| Ian Rogers | 56edc43 | 2013-01-18 16:51:51 -0800 | [diff] [blame] | 342 |   virtual void Dump(std::ostream& os) const; | 
| Ian Rogers | 01ae580 | 2012-09-28 16:14:01 -0700 | [diff] [blame] | 343 |  | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 344 |  private: | 
 | 345 | #if ART_USE_FUTEXES | 
 | 346 |   // -1 implies held exclusive, +ve shared held by state_ many owners. | 
 | 347 |   volatile int32_t state_; | 
 | 348 |   // Exclusive owner. | 
 | 349 |   volatile uint64_t exclusive_owner_; | 
 | 350 |   // Pending readers. | 
 | 351 |   volatile int32_t num_pending_readers_; | 
 | 352 |   // Pending writers. | 
| Ian Rogers | b122a4b | 2013-11-19 18:00:50 -0800 | [diff] [blame] | 353 |   AtomicInteger num_pending_writers_; | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 354 | #else | 
 | 355 |   pthread_rwlock_t rwlock_; | 
 | 356 | #endif | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 357 |   DISALLOW_COPY_AND_ASSIGN(ReaderWriterMutex); | 
 | 358 | }; | 
 | 359 |  | 
 | 360 | // ConditionVariables allow threads to queue and sleep. Threads may then be resumed individually | 
 | 361 | // (Signal) or all at once (Broadcast). | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 362 | class ConditionVariable { | 
 | 363 |  public: | 
| Ian Rogers | 23055dc | 2013-04-18 16:29:16 -0700 | [diff] [blame] | 364 |   explicit ConditionVariable(const char* name, Mutex& mutex); | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 365 |   ~ConditionVariable(); | 
 | 366 |  | 
| Ian Rogers | c604d73 | 2012-10-14 16:09:54 -0700 | [diff] [blame] | 367 |   void Broadcast(Thread* self); | 
 | 368 |   void Signal(Thread* self); | 
 | 369 |   // TODO: No thread safety analysis on Wait and TimedWait as they call mutex operations via their | 
 | 370 |   //       pointer copy, thereby defeating annotalysis. | 
 | 371 |   void Wait(Thread* self) NO_THREAD_SAFETY_ANALYSIS; | 
 | 372 |   void TimedWait(Thread* self, int64_t ms, int32_t ns) NO_THREAD_SAFETY_ANALYSIS; | 
| Ian Rogers | 1d54e73 | 2013-05-02 21:10:01 -0700 | [diff] [blame] | 373 |   // Variant of Wait that should be used with caution. Doesn't validate that no mutexes are held | 
 | 374 |   // when waiting. | 
 | 375 |   // TODO: remove this. | 
 | 376 |   void WaitHoldingLocks(Thread* self) NO_THREAD_SAFETY_ANALYSIS; | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 377 |  | 
 | 378 |  private: | 
| Ian Rogers | 23055dc | 2013-04-18 16:29:16 -0700 | [diff] [blame] | 379 |   const char* const name_; | 
| Ian Rogers | c604d73 | 2012-10-14 16:09:54 -0700 | [diff] [blame] | 380 |   // The Mutex being used by waiters. It is an error to mix condition variables between different | 
 | 381 |   // Mutexes. | 
 | 382 |   Mutex& guard_; | 
 | 383 | #if ART_USE_FUTEXES | 
 | 384 |   // A counter that is modified by signals and broadcasts. This ensures that when a waiter gives up | 
| Ian Rogers | d45f201 | 2012-11-28 11:46:23 -0800 | [diff] [blame] | 385 |   // their Mutex and another thread takes it and signals, the waiting thread observes that sequence_ | 
 | 386 |   // changed and doesn't enter the wait. Modified while holding guard_, but is read by futex wait | 
 | 387 |   // without guard_ held. | 
| Ian Rogers | b122a4b | 2013-11-19 18:00:50 -0800 | [diff] [blame] | 388 |   AtomicInteger sequence_; | 
| Ian Rogers | c604d73 | 2012-10-14 16:09:54 -0700 | [diff] [blame] | 389 |   // Number of threads that have come into to wait, not the length of the waiters on the futex as | 
| Ian Rogers | 5bd97c4 | 2012-11-27 02:38:26 -0800 | [diff] [blame] | 390 |   // waiters may have been requeued onto guard_. Guarded by guard_. | 
| Ian Rogers | c604d73 | 2012-10-14 16:09:54 -0700 | [diff] [blame] | 391 |   volatile int32_t num_waiters_; | 
| Ian Rogers | c604d73 | 2012-10-14 16:09:54 -0700 | [diff] [blame] | 392 | #else | 
 | 393 |   pthread_cond_t cond_; | 
 | 394 | #endif | 
| Elliott Hughes | 5f79133 | 2011-09-15 17:45:30 -0700 | [diff] [blame] | 395 |   DISALLOW_COPY_AND_ASSIGN(ConditionVariable); | 
 | 396 | }; | 
 | 397 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 398 | // Scoped locker/unlocker for a regular Mutex that acquires mu upon construction and releases it | 
 | 399 | // upon destruction. | 
 | 400 | class SCOPED_LOCKABLE MutexLock { | 
 | 401 |  public: | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 402 |   explicit MutexLock(Thread* self, Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : self_(self), mu_(mu) { | 
 | 403 |     mu_.ExclusiveLock(self_); | 
 | 404 |   } | 
 | 405 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 406 |   ~MutexLock() UNLOCK_FUNCTION() { | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 407 |     mu_.ExclusiveUnlock(self_); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 408 |   } | 
 | 409 |  | 
 | 410 |  private: | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 411 |   Thread* const self_; | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 412 |   Mutex& mu_; | 
 | 413 |   DISALLOW_COPY_AND_ASSIGN(MutexLock); | 
 | 414 | }; | 
 | 415 | // Catch bug where variable name is omitted. "MutexLock (lock);" instead of "MutexLock mu(lock)". | 
 | 416 | #define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_declaration_missing_variable_name) | 
 | 417 |  | 
 | 418 | // Scoped locker/unlocker for a ReaderWriterMutex that acquires read access to mu upon | 
 | 419 | // construction and releases it upon destruction. | 
 | 420 | class SCOPED_LOCKABLE ReaderMutexLock { | 
 | 421 |  public: | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 422 |   explicit ReaderMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : | 
 | 423 |       self_(self), mu_(mu) { | 
 | 424 |     mu_.SharedLock(self_); | 
 | 425 |   } | 
 | 426 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 427 |   ~ReaderMutexLock() UNLOCK_FUNCTION() { | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 428 |     mu_.SharedUnlock(self_); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 429 |   } | 
 | 430 |  | 
 | 431 |  private: | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 432 |   Thread* const self_; | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 433 |   ReaderWriterMutex& mu_; | 
 | 434 |   DISALLOW_COPY_AND_ASSIGN(ReaderMutexLock); | 
 | 435 | }; | 
 | 436 | // Catch bug where variable name is omitted. "ReaderMutexLock (lock);" instead of | 
 | 437 | // "ReaderMutexLock mu(lock)". | 
 | 438 | #define ReaderMutexLock(x) COMPILE_ASSERT(0, reader_mutex_lock_declaration_missing_variable_name) | 
 | 439 |  | 
 | 440 | // Scoped locker/unlocker for a ReaderWriterMutex that acquires write access to mu upon | 
 | 441 | // construction and releases it upon destruction. | 
 | 442 | class SCOPED_LOCKABLE WriterMutexLock { | 
 | 443 |  public: | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 444 |   explicit WriterMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : | 
 | 445 |       self_(self), mu_(mu) { | 
 | 446 |     mu_.ExclusiveLock(self_); | 
 | 447 |   } | 
 | 448 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 449 |   ~WriterMutexLock() UNLOCK_FUNCTION() { | 
| Ian Rogers | 81d425b | 2012-09-27 16:03:43 -0700 | [diff] [blame] | 450 |     mu_.ExclusiveUnlock(self_); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 451 |   } | 
 | 452 |  | 
 | 453 |  private: | 
| Ian Rogers | 50b35e2 | 2012-10-04 10:09:15 -0700 | [diff] [blame] | 454 |   Thread* const self_; | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 455 |   ReaderWriterMutex& mu_; | 
 | 456 |   DISALLOW_COPY_AND_ASSIGN(WriterMutexLock); | 
 | 457 | }; | 
 | 458 | // Catch bug where variable name is omitted. "WriterMutexLock (lock);" instead of | 
 | 459 | // "WriterMutexLock mu(lock)". | 
 | 460 | #define WriterMutexLock(x) COMPILE_ASSERT(0, writer_mutex_lock_declaration_missing_variable_name) | 
 | 461 |  | 
| Ian Rogers | 719d1a3 | 2014-03-06 12:13:39 -0800 | [diff] [blame^] | 462 | // Global mutexes corresponding to the levels above. | 
 | 463 | class Locks { | 
 | 464 |  public: | 
 | 465 |   static void Init(); | 
 | 466 |  | 
 | 467 |   // The mutator_lock_ is used to allow mutators to execute in a shared (reader) mode or to block | 
 | 468 |   // mutators by having an exclusive (writer) owner. In normal execution each mutator thread holds | 
 | 469 |   // a share on the mutator_lock_. The garbage collector may also execute with shared access but | 
 | 470 |   // at times requires exclusive access to the heap (not to be confused with the heap meta-data | 
 | 471 |   // guarded by the heap_lock_ below). When the garbage collector requires exclusive access it asks | 
 | 472 |   // the mutators to suspend themselves which also involves usage of the thread_suspend_count_lock_ | 
 | 473 |   // to cover weaknesses in using ReaderWriterMutexes with ConditionVariables. We use a condition | 
 | 474 |   // variable to wait upon in the suspension logic as releasing and then re-acquiring a share on | 
 | 475 |   // the mutator lock doesn't necessarily allow the exclusive user (e.g the garbage collector) | 
 | 476 |   // chance to acquire the lock. | 
 | 477 |   // | 
 | 478 |   // Thread suspension: | 
 | 479 |   // Shared users                                  | Exclusive user | 
 | 480 |   // (holding mutator lock and in kRunnable state) |   .. running .. | 
 | 481 |   //   .. running ..                               | Request thread suspension by: | 
 | 482 |   //   .. running ..                               |   - acquiring thread_suspend_count_lock_ | 
 | 483 |   //   .. running ..                               |   - incrementing Thread::suspend_count_ on | 
 | 484 |   //   .. running ..                               |     all mutator threads | 
 | 485 |   //   .. running ..                               |   - releasing thread_suspend_count_lock_ | 
 | 486 |   //   .. running ..                               | Block trying to acquire exclusive mutator lock | 
 | 487 |   // Poll Thread::suspend_count_ and enter full    |   .. blocked .. | 
 | 488 |   // suspend code.                                 |   .. blocked .. | 
 | 489 |   // Change state to kSuspended                    |   .. blocked .. | 
 | 490 |   // x: Release share on mutator_lock_             | Carry out exclusive access | 
 | 491 |   // Acquire thread_suspend_count_lock_            |   .. exclusive .. | 
 | 492 |   // while Thread::suspend_count_ > 0              |   .. exclusive .. | 
 | 493 |   //   - wait on Thread::resume_cond_              |   .. exclusive .. | 
 | 494 |   //     (releases thread_suspend_count_lock_)     |   .. exclusive .. | 
 | 495 |   //   .. waiting ..                               | Release mutator_lock_ | 
 | 496 |   //   .. waiting ..                               | Request thread resumption by: | 
 | 497 |   //   .. waiting ..                               |   - acquiring thread_suspend_count_lock_ | 
 | 498 |   //   .. waiting ..                               |   - decrementing Thread::suspend_count_ on | 
 | 499 |   //   .. waiting ..                               |     all mutator threads | 
 | 500 |   //   .. waiting ..                               |   - notifying on Thread::resume_cond_ | 
 | 501 |   //    - re-acquire thread_suspend_count_lock_    |   - releasing thread_suspend_count_lock_ | 
 | 502 |   // Release thread_suspend_count_lock_            |  .. running .. | 
 | 503 |   // Acquire share on mutator_lock_                |  .. running .. | 
 | 504 |   //  - This could block but the thread still      |  .. running .. | 
 | 505 |   //    has a state of kSuspended and so this      |  .. running .. | 
 | 506 |   //    isn't an issue.                            |  .. running .. | 
 | 507 |   // Acquire thread_suspend_count_lock_            |  .. running .. | 
 | 508 |   //  - we poll here as we're transitioning into   |  .. running .. | 
 | 509 |   //    kRunnable and an individual thread suspend |  .. running .. | 
 | 510 |   //    request (e.g for debugging) won't try      |  .. running .. | 
 | 511 |   //    to acquire the mutator lock (which would   |  .. running .. | 
 | 512 |   //    block as we hold the mutator lock). This   |  .. running .. | 
 | 513 |   //    poll ensures that if the suspender thought |  .. running .. | 
 | 514 |   //    we were suspended by incrementing our      |  .. running .. | 
 | 515 |   //    Thread::suspend_count_ and then reading    |  .. running .. | 
 | 516 |   //    our state we go back to waiting on         |  .. running .. | 
 | 517 |   //    Thread::resume_cond_.                      |  .. running .. | 
 | 518 |   // can_go_runnable = Thread::suspend_count_ == 0 |  .. running .. | 
 | 519 |   // Release thread_suspend_count_lock_            |  .. running .. | 
 | 520 |   // if can_go_runnable                            |  .. running .. | 
 | 521 |   //   Change state to kRunnable                   |  .. running .. | 
 | 522 |   // else                                          |  .. running .. | 
 | 523 |   //   Goto x                                      |  .. running .. | 
 | 524 |   //  .. running ..                                |  .. running .. | 
 | 525 |   static ReaderWriterMutex* mutator_lock_; | 
 | 526 |  | 
 | 527 |   // Allow reader-writer mutual exclusion on the mark and live bitmaps of the heap. | 
 | 528 |   static ReaderWriterMutex* heap_bitmap_lock_ ACQUIRED_AFTER(mutator_lock_); | 
 | 529 |  | 
 | 530 |   // Guards shutdown of the runtime. | 
 | 531 |   static Mutex* runtime_shutdown_lock_ ACQUIRED_AFTER(heap_bitmap_lock_); | 
 | 532 |  | 
 | 533 |   // The thread_list_lock_ guards ThreadList::list_. It is also commonly held to stop threads | 
 | 534 |   // attaching and detaching. | 
 | 535 |   static Mutex* thread_list_lock_ ACQUIRED_AFTER(runtime_shutdown_lock_); | 
 | 536 |  | 
 | 537 |   // Guards breakpoints. | 
 | 538 |   static Mutex* breakpoint_lock_ ACQUIRED_AFTER(thread_list_lock_); | 
 | 539 |  | 
 | 540 |   // Guards deoptimization requests. | 
 | 541 |   static Mutex* deoptimization_lock_ ACQUIRED_AFTER(breakpoint_lock_); | 
 | 542 |  | 
 | 543 |   // Guards trace requests. | 
 | 544 |   static Mutex* trace_lock_ ACQUIRED_AFTER(deoptimization_lock_); | 
 | 545 |  | 
 | 546 |   // Guards profile objects. | 
 | 547 |   static Mutex* profiler_lock_ ACQUIRED_AFTER(trace_lock_); | 
 | 548 |  | 
 | 549 |   // Guards lists of classes within the class linker. | 
 | 550 |   static ReaderWriterMutex* classlinker_classes_lock_ ACQUIRED_AFTER(profiler_lock_); | 
 | 551 |  | 
 | 552 |   // When declaring any Mutex add DEFAULT_MUTEX_ACQUIRED_AFTER to use annotalysis to check the code | 
 | 553 |   // doesn't try to hold a higher level Mutex. | 
 | 554 |   #define DEFAULT_MUTEX_ACQUIRED_AFTER ACQUIRED_AFTER(Locks::classlinker_classes_lock_) | 
 | 555 |  | 
 | 556 |   // Guards intern table. | 
 | 557 |   static Mutex* intern_table_lock_ ACQUIRED_AFTER(classlinker_classes_lock_); | 
 | 558 |  | 
 | 559 |   // Have an exclusive aborting thread. | 
 | 560 |   static Mutex* abort_lock_ ACQUIRED_AFTER(classlinker_classes_lock_); | 
 | 561 |  | 
 | 562 |   // Allow mutual exclusion when manipulating Thread::suspend_count_. | 
 | 563 |   // TODO: Does the trade-off of a per-thread lock make sense? | 
 | 564 |   static Mutex* thread_suspend_count_lock_ ACQUIRED_AFTER(abort_lock_); | 
 | 565 |  | 
 | 566 |   // One unexpected signal at a time lock. | 
 | 567 |   static Mutex* unexpected_signal_lock_ ACQUIRED_AFTER(thread_suspend_count_lock_); | 
 | 568 |  | 
 | 569 |   // Have an exclusive logging thread. | 
 | 570 |   static Mutex* logging_lock_ ACQUIRED_AFTER(unexpected_signal_lock_); | 
 | 571 | }; | 
 | 572 |  | 
| Elliott Hughes | 8daa092 | 2011-09-11 13:46:25 -0700 | [diff] [blame] | 573 | }  // namespace art | 
 | 574 |  | 
| Brian Carlstrom | fc0e321 | 2013-07-17 14:40:12 -0700 | [diff] [blame] | 575 | #endif  // ART_RUNTIME_BASE_MUTEX_H_ |