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