mutex.h revision 23055dc5d7a90c4a12e259fd0ed7cd4d04d89182
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_BASE_MUTEX_H_
18#define ART_SRC_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 = kIsDebugBuild;
57
58// Base class for all Mutex implementations
59class BaseMutex {
60 public:
61  const std::string& 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 std::string 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) {
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) {
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) {
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) {
250      CHECK(!IsExclusiveHeld(self));
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) {
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) {
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
311 private:
312  const char* const name_;
313  // The Mutex being used by waiters. It is an error to mix condition variables between different
314  // Mutexes.
315  Mutex& guard_;
316#if ART_USE_FUTEXES
317  // A counter that is modified by signals and broadcasts. This ensures that when a waiter gives up
318  // their Mutex and another thread takes it and signals, the waiting thread observes that sequence_
319  // changed and doesn't enter the wait. Modified while holding guard_, but is read by futex wait
320  // without guard_ held.
321  volatile int32_t sequence_;
322  // Number of threads that have come into to wait, not the length of the waiters on the futex as
323  // waiters may have been requeued onto guard_. Guarded by guard_.
324  volatile int32_t num_waiters_;
325#else
326  pthread_cond_t cond_;
327#endif
328  DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
329};
330
331// Scoped locker/unlocker for a regular Mutex that acquires mu upon construction and releases it
332// upon destruction.
333class SCOPED_LOCKABLE MutexLock {
334 public:
335  explicit MutexLock(Thread* self, Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : self_(self), mu_(mu) {
336    mu_.ExclusiveLock(self_);
337  }
338
339  ~MutexLock() UNLOCK_FUNCTION() {
340    mu_.ExclusiveUnlock(self_);
341  }
342
343 private:
344  Thread* const self_;
345  Mutex& mu_;
346  DISALLOW_COPY_AND_ASSIGN(MutexLock);
347};
348// Catch bug where variable name is omitted. "MutexLock (lock);" instead of "MutexLock mu(lock)".
349#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_declaration_missing_variable_name)
350
351// Scoped locker/unlocker for a ReaderWriterMutex that acquires read access to mu upon
352// construction and releases it upon destruction.
353class SCOPED_LOCKABLE ReaderMutexLock {
354 public:
355  explicit ReaderMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
356      self_(self), mu_(mu) {
357    mu_.SharedLock(self_);
358  }
359
360  ~ReaderMutexLock() UNLOCK_FUNCTION() {
361    mu_.SharedUnlock(self_);
362  }
363
364 private:
365  Thread* const self_;
366  ReaderWriterMutex& mu_;
367  DISALLOW_COPY_AND_ASSIGN(ReaderMutexLock);
368};
369// Catch bug where variable name is omitted. "ReaderMutexLock (lock);" instead of
370// "ReaderMutexLock mu(lock)".
371#define ReaderMutexLock(x) COMPILE_ASSERT(0, reader_mutex_lock_declaration_missing_variable_name)
372
373// Scoped locker/unlocker for a ReaderWriterMutex that acquires write access to mu upon
374// construction and releases it upon destruction.
375class SCOPED_LOCKABLE WriterMutexLock {
376 public:
377  explicit WriterMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
378      self_(self), mu_(mu) {
379    mu_.ExclusiveLock(self_);
380  }
381
382  ~WriterMutexLock() UNLOCK_FUNCTION() {
383    mu_.ExclusiveUnlock(self_);
384  }
385
386 private:
387  Thread* const self_;
388  ReaderWriterMutex& mu_;
389  DISALLOW_COPY_AND_ASSIGN(WriterMutexLock);
390};
391// Catch bug where variable name is omitted. "WriterMutexLock (lock);" instead of
392// "WriterMutexLock mu(lock)".
393#define WriterMutexLock(x) COMPILE_ASSERT(0, writer_mutex_lock_declaration_missing_variable_name)
394
395}  // namespace art
396
397#endif  // ART_SRC_BASE_MUTEX_H_
398