blob: 39fd8c82a391068712b4cd35f524a9f2e9ab4b7e [file] [log] [blame]
Elliott Hughes8daa0922011-09-11 13:46:25 -07001/*
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 Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_RUNTIME_BASE_MUTEX_H_
18#define ART_RUNTIME_BASE_MUTEX_H_
Elliott Hughes8daa0922011-09-11 13:46:25 -070019
20#include <pthread.h>
Brian Carlstromcd74c4b2012-01-23 13:21:00 -080021#include <stdint.h>
Hans Boehm0882af22017-08-31 15:21:57 -070022#include <unistd.h> // for pid_t
Elliott Hughesffb465f2012-03-01 18:46:05 -080023
24#include <iosfwd>
Elliott Hughes8daa0922011-09-11 13:46:25 -070025#include <string>
26
Andreas Gampe57943812017-12-06 21:39:13 -080027#include <android-base/logging.h>
28
Andreas Gampe39b378c2017-12-07 15:44:13 -080029#include "base/aborting.h"
David Sehrc431b9d2018-03-02 12:01:51 -080030#include "base/atomic.h"
Andreas Gampe5a0430d2019-01-04 14:33:57 -080031#include "runtime_globals.h"
Elliott Hughes76160052012-12-12 16:31:20 -080032#include "base/macros.h"
Andreas Gampe7cc45fd2018-11-21 16:03:08 -080033#include "locks.h"
Ian Rogers81d425b2012-09-27 16:03:43 -070034
Daniel Colascioneb4dfca52018-04-15 11:15:14 -070035#if defined(__linux__)
Chris Dearmanc0141782013-11-14 17:29:21 -080036#define ART_USE_FUTEXES 1
Daniel Colascioneb4dfca52018-04-15 11:15:14 -070037#else
38#define ART_USE_FUTEXES 0
Ian Rogersab470162012-09-29 23:06:53 -070039#endif
Elliott Hughes8daa0922011-09-11 13:46:25 -070040
Ian Rogers66aee5c2012-08-15 17:17:47 -070041// Currently Darwin doesn't support locks with timeouts.
42#if !defined(__APPLE__)
43#define HAVE_TIMED_RWLOCK 1
44#else
45#define HAVE_TIMED_RWLOCK 0
46#endif
47
Elliott Hughes8daa0922011-09-11 13:46:25 -070048namespace art {
49
Mathieu Chartier90443472015-07-16 20:32:27 -070050class SHARED_LOCKABLE ReaderWriterMutex;
51class SHARED_LOCKABLE MutatorMutex;
Ian Rogers56edc432013-01-18 16:51:51 -080052class ScopedContentionRecorder;
Ian Rogers50b35e22012-10-04 10:09:15 -070053class Thread;
Andreas Gampe7cc45fd2018-11-21 16:03:08 -080054class LOCKABLE Mutex;
Ian Rogers719d1a32014-03-06 12:13:39 -080055
Andreas Gampe5db8b7b2018-05-08 16:10:59 -070056constexpr bool kDebugLocking = kIsDebugBuild;
Ian Rogers25fd14b2012-09-05 10:56:38 -070057
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -070058// Record Log contention information, dumpable via SIGQUIT.
59#ifdef ART_USE_FUTEXES
Jeff Hao08f2e7b2013-09-09 16:44:02 -070060// To enable lock contention logging, set this to true.
Andreas Gampe5db8b7b2018-05-08 16:10:59 -070061constexpr bool kLogLockContentions = false;
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -070062#else
63// Keep this false as lock contention logging is supported only with
64// futex.
Andreas Gampe5db8b7b2018-05-08 16:10:59 -070065constexpr bool kLogLockContentions = false;
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -070066#endif
Andreas Gampe5db8b7b2018-05-08 16:10:59 -070067constexpr size_t kContentionLogSize = 4;
68constexpr size_t kContentionLogDataSize = kLogLockContentions ? 1 : 0;
69constexpr size_t kAllMutexDataSize = kLogLockContentions ? 1 : 0;
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -070070
Ian Rogers00f7d0e2012-07-19 15:28:27 -070071// Base class for all Mutex implementations
72class BaseMutex {
73 public:
Ian Rogersbab74962013-04-19 10:04:10 -070074 const char* GetName() const {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070075 return name_;
76 }
77
78 virtual bool IsMutex() const { return false; }
79 virtual bool IsReaderWriterMutex() const { return false; }
Yu Lieac44242015-06-29 10:50:03 +080080 virtual bool IsMutatorMutex() const { return false; }
Ian Rogers00f7d0e2012-07-19 15:28:27 -070081
Ian Rogers56edc432013-01-18 16:51:51 -080082 virtual void Dump(std::ostream& os) const = 0;
83
84 static void DumpAll(std::ostream& os);
85
Hiroshi Yamauchia2224042017-02-08 16:35:45 -080086 bool ShouldRespondToEmptyCheckpointRequest() const {
87 return should_respond_to_empty_checkpoint_request_;
88 }
89
90 void SetShouldRespondToEmptyCheckpointRequest(bool value) {
91 should_respond_to_empty_checkpoint_request_ = value;
92 }
93
94 virtual void WakeupToRespondToEmptyCheckpoint() = 0;
95
Ian Rogers00f7d0e2012-07-19 15:28:27 -070096 protected:
97 friend class ConditionVariable;
98
Ian Rogers81d425b2012-09-27 16:03:43 -070099 BaseMutex(const char* name, LockLevel level);
Ian Rogers56edc432013-01-18 16:51:51 -0800100 virtual ~BaseMutex();
Ian Rogers81d425b2012-09-27 16:03:43 -0700101 void RegisterAsLocked(Thread* self);
102 void RegisterAsUnlocked(Thread* self);
103 void CheckSafeToWait(Thread* self);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700104
Ian Rogers56edc432013-01-18 16:51:51 -0800105 friend class ScopedContentionRecorder;
106
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700107 void RecordContention(uint64_t blocked_tid, uint64_t owner_tid, uint64_t nano_time_blocked);
Ian Rogers56edc432013-01-18 16:51:51 -0800108 void DumpContention(std::ostream& os) const;
109
Ian Rogersbab74962013-04-19 10:04:10 -0700110 const char* const name_;
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700111
Ian Rogers56edc432013-01-18 16:51:51 -0800112 // A log entry that records contention but makes no guarantee that either tid will be held live.
113 struct ContentionLogEntry {
114 ContentionLogEntry() : blocked_tid(0), owner_tid(0) {}
115 uint64_t blocked_tid;
116 uint64_t owner_tid;
117 AtomicInteger count;
118 };
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700119 struct ContentionLogData {
120 ContentionLogEntry contention_log[kContentionLogSize];
121 // The next entry in the contention log to be updated. Value ranges from 0 to
122 // kContentionLogSize - 1.
123 AtomicInteger cur_content_log_entry;
124 // Number of times the Mutex has been contended.
125 AtomicInteger contention_count;
126 // Sum of time waited by all contenders in ns.
Ian Rogers37f3c962014-07-17 11:25:30 -0700127 Atomic<uint64_t> wait_time;
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700128 void AddToWaitTime(uint64_t value);
129 ContentionLogData() : wait_time(0) {}
130 };
Ian Rogers3e5cf302014-05-20 16:40:37 -0700131 ContentionLogData contention_log_data_[kContentionLogDataSize];
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700132
Andreas Gampe5db8b7b2018-05-08 16:10:59 -0700133 const LockLevel level_; // Support for lock hierarchy.
134 bool should_respond_to_empty_checkpoint_request_;
135
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700136 public:
137 bool HasEverContended() const {
138 if (kLogLockContentions) {
Orion Hodson88591fe2018-03-06 13:35:43 +0000139 return contention_log_data_->contention_count.load(std::memory_order_seq_cst) > 0;
Hiroshi Yamauchi1afde132013-08-06 17:09:30 -0700140 }
141 return false;
142 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700143};
144
145// A Mutex is used to achieve mutual exclusion between threads. A Mutex can be used to gain
146// exclusive access to what it guards. A Mutex can be in one of two states:
147// - Free - not owned by any thread,
148// - Exclusive - owned by a single thread.
149//
150// The effect of locking and unlocking operations on the state is:
151// State | ExclusiveLock | ExclusiveUnlock
152// -------------------------------------------
153// Free | Exclusive | error
154// Exclusive | Block* | Free
155// * Mutex is not reentrant and so an attempt to ExclusiveLock on the same thread will result in
156// an error. Being non-reentrant simplifies Waiting on ConditionVariables.
Ian Rogers01ae5802012-09-28 16:14:01 -0700157std::ostream& operator<<(std::ostream& os, const Mutex& mu);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700158class LOCKABLE Mutex : public BaseMutex {
159 public:
Ian Rogers81d425b2012-09-27 16:03:43 -0700160 explicit Mutex(const char* name, LockLevel level = kDefaultMutexLevel, bool recursive = false);
Elliott Hughes8daa0922011-09-11 13:46:25 -0700161 ~Mutex();
162
Yi Kong39402542019-03-24 02:47:16 -0700163 bool IsMutex() const override { return true; }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700164
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700165 // Block until mutex is free then acquire exclusive access.
Mathieu Chartier90443472015-07-16 20:32:27 -0700166 void ExclusiveLock(Thread* self) ACQUIRE();
167 void Lock(Thread* self) ACQUIRE() { ExclusiveLock(self); }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700168
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700169 // Returns true if acquires exclusive access, false otherwise.
Mathieu Chartier90443472015-07-16 20:32:27 -0700170 bool ExclusiveTryLock(Thread* self) TRY_ACQUIRE(true);
171 bool TryLock(Thread* self) TRY_ACQUIRE(true) { return ExclusiveTryLock(self); }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700172
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700173 // Release exclusive access.
Mathieu Chartier90443472015-07-16 20:32:27 -0700174 void ExclusiveUnlock(Thread* self) RELEASE();
175 void Unlock(Thread* self) RELEASE() { ExclusiveUnlock(self); }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700176
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700177 // Is the current thread the exclusive holder of the Mutex.
Andreas Gampeb486a982017-06-01 13:45:54 -0700178 ALWAYS_INLINE bool IsExclusiveHeld(const Thread* self) const;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700179
180 // Assert that the Mutex is exclusively held by the current thread.
Andreas Gampeb486a982017-06-01 13:45:54 -0700181 ALWAYS_INLINE void AssertExclusiveHeld(const Thread* self) const ASSERT_CAPABILITY(this);
182 ALWAYS_INLINE void AssertHeld(const Thread* self) const ASSERT_CAPABILITY(this);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700183
184 // Assert that the Mutex is not held by the current thread.
Mathieu Chartier90443472015-07-16 20:32:27 -0700185 void AssertNotHeldExclusive(const Thread* self) ASSERT_CAPABILITY(!*this) {
Nicolas Geoffraydb978712014-12-09 13:33:38 +0000186 if (kDebugLocking && (gAborting == 0)) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700187 CHECK(!IsExclusiveHeld(self)) << *this;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700188 }
189 }
Mathieu Chartier90443472015-07-16 20:32:27 -0700190 void AssertNotHeld(const Thread* self) ASSERT_CAPABILITY(!*this) {
191 AssertNotHeldExclusive(self);
192 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700193
Ian Rogersc7190692014-07-08 23:50:26 -0700194 // Id associated with exclusive owner. No memory ordering semantics if called from a thread other
195 // than the owner.
Hans Boehm0882af22017-08-31 15:21:57 -0700196 pid_t GetExclusiveOwnerTid() const;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700197
198 // Returns how many times this Mutex has been locked, it is better to use AssertHeld/NotHeld.
199 unsigned int GetDepth() const {
200 return recursion_count_;
201 }
Elliott Hughesaccd83d2011-10-17 14:25:58 -0700202
Yi Kong39402542019-03-24 02:47:16 -0700203 void Dump(std::ostream& os) const override;
Ian Rogers01ae5802012-09-28 16:14:01 -0700204
Mathieu Chartier90443472015-07-16 20:32:27 -0700205 // For negative capabilities in clang annotations.
206 const Mutex& operator!() const { return *this; }
207
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100208 void WakeupToRespondToEmptyCheckpoint() override;
Hiroshi Yamauchia2224042017-02-08 16:35:45 -0800209
Elliott Hughesaccd83d2011-10-17 14:25:58 -0700210 private:
Ian Rogersc604d732012-10-14 16:09:54 -0700211#if ART_USE_FUTEXES
212 // 0 is unheld, 1 is held.
Ian Rogersc7190692014-07-08 23:50:26 -0700213 AtomicInteger state_;
Ian Rogersc604d732012-10-14 16:09:54 -0700214 // Exclusive owner.
Hans Boehm0882af22017-08-31 15:21:57 -0700215 Atomic<pid_t> exclusive_owner_;
Ian Rogersc604d732012-10-14 16:09:54 -0700216 // Number of waiting contenders.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800217 AtomicInteger num_contenders_;
Ian Rogersc604d732012-10-14 16:09:54 -0700218#else
Elliott Hughes8daa0922011-09-11 13:46:25 -0700219 pthread_mutex_t mutex_;
Hans Boehm0882af22017-08-31 15:21:57 -0700220 Atomic<pid_t> exclusive_owner_; // Guarded by mutex_. Asynchronous reads are OK.
Ian Rogersc604d732012-10-14 16:09:54 -0700221#endif
Andreas Gampe5db8b7b2018-05-08 16:10:59 -0700222
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700223 unsigned int recursion_count_;
Andreas Gampe5db8b7b2018-05-08 16:10:59 -0700224 const bool recursive_; // Can the lock be recursively held?
225
Elliott Hughesf1498432012-03-28 19:34:27 -0700226 friend class ConditionVariable;
Elliott Hughes8daa0922011-09-11 13:46:25 -0700227 DISALLOW_COPY_AND_ASSIGN(Mutex);
228};
229
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700230// A ReaderWriterMutex is used to achieve mutual exclusion between threads, similar to a Mutex.
231// Unlike a Mutex a ReaderWriterMutex can be used to gain exclusive (writer) or shared (reader)
232// access to what it guards. A flaw in relation to a Mutex is that it cannot be used with a
233// condition variable. A ReaderWriterMutex can be in one of three states:
234// - Free - not owned by any thread,
235// - Exclusive - owned by a single thread,
236// - Shared(n) - shared amongst n threads.
237//
238// The effect of locking and unlocking operations on the state is:
239//
240// State | ExclusiveLock | ExclusiveUnlock | SharedLock | SharedUnlock
241// ----------------------------------------------------------------------------
242// Free | Exclusive | error | SharedLock(1) | error
243// Exclusive | Block | Free | Block | error
244// Shared(n) | Block | error | SharedLock(n+1)* | Shared(n-1) or Free
245// * for large values of n the SharedLock may block.
Ian Rogers01ae5802012-09-28 16:14:01 -0700246std::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu);
Mathieu Chartier90443472015-07-16 20:32:27 -0700247class SHARED_LOCKABLE ReaderWriterMutex : public BaseMutex {
Elliott Hughes8daa0922011-09-11 13:46:25 -0700248 public:
Ian Rogers81d425b2012-09-27 16:03:43 -0700249 explicit ReaderWriterMutex(const char* name, LockLevel level = kDefaultMutexLevel);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700250 ~ReaderWriterMutex();
251
Yi Kong39402542019-03-24 02:47:16 -0700252 bool IsReaderWriterMutex() const override { return true; }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700253
254 // Block until ReaderWriterMutex is free then acquire exclusive access.
Mathieu Chartier90443472015-07-16 20:32:27 -0700255 void ExclusiveLock(Thread* self) ACQUIRE();
256 void WriterLock(Thread* self) ACQUIRE() { ExclusiveLock(self); }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700257
258 // Release exclusive access.
Mathieu Chartier90443472015-07-16 20:32:27 -0700259 void ExclusiveUnlock(Thread* self) RELEASE();
260 void WriterUnlock(Thread* self) RELEASE() { ExclusiveUnlock(self); }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700261
262 // Block until ReaderWriterMutex is free and acquire exclusive access. Returns true on success
263 // or false if timeout is reached.
Ian Rogers66aee5c2012-08-15 17:17:47 -0700264#if HAVE_TIMED_RWLOCK
Ian Rogersc604d732012-10-14 16:09:54 -0700265 bool ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32_t ns)
Ian Rogers81d425b2012-09-27 16:03:43 -0700266 EXCLUSIVE_TRYLOCK_FUNCTION(true);
Ian Rogers66aee5c2012-08-15 17:17:47 -0700267#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700268
269 // Block until ReaderWriterMutex is shared or free then acquire a share on the access.
Mathieu Chartier90443472015-07-16 20:32:27 -0700270 void SharedLock(Thread* self) ACQUIRE_SHARED() ALWAYS_INLINE;
271 void ReaderLock(Thread* self) ACQUIRE_SHARED() { SharedLock(self); }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700272
273 // Try to acquire share of ReaderWriterMutex.
Mathieu Chartier90443472015-07-16 20:32:27 -0700274 bool SharedTryLock(Thread* self) SHARED_TRYLOCK_FUNCTION(true);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700275
276 // Release a share of the access.
Mathieu Chartier90443472015-07-16 20:32:27 -0700277 void SharedUnlock(Thread* self) RELEASE_SHARED() ALWAYS_INLINE;
278 void ReaderUnlock(Thread* self) RELEASE_SHARED() { SharedUnlock(self); }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700279
280 // Is the current thread the exclusive holder of the ReaderWriterMutex.
Andreas Gampeb486a982017-06-01 13:45:54 -0700281 ALWAYS_INLINE bool IsExclusiveHeld(const Thread* self) const;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700282
283 // Assert the current thread has exclusive access to the ReaderWriterMutex.
Andreas Gampeb486a982017-06-01 13:45:54 -0700284 ALWAYS_INLINE void AssertExclusiveHeld(const Thread* self) const ASSERT_CAPABILITY(this);
285 ALWAYS_INLINE void AssertWriterHeld(const Thread* self) const ASSERT_CAPABILITY(this);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700286
287 // Assert the current thread doesn't have exclusive access to the ReaderWriterMutex.
Mathieu Chartier90ef3db2015-08-04 15:19:41 -0700288 void AssertNotExclusiveHeld(const Thread* self) ASSERT_CAPABILITY(!this) {
Nicolas Geoffraydb978712014-12-09 13:33:38 +0000289 if (kDebugLocking && (gAborting == 0)) {
Ian Rogerse3359f72013-06-11 15:14:11 -0700290 CHECK(!IsExclusiveHeld(self)) << *this;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700291 }
292 }
Mathieu Chartier90ef3db2015-08-04 15:19:41 -0700293 void AssertNotWriterHeld(const Thread* self) ASSERT_CAPABILITY(!this) {
294 AssertNotExclusiveHeld(self);
295 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700296
297 // Is the current thread a shared holder of the ReaderWriterMutex.
Ian Rogers81d425b2012-09-27 16:03:43 -0700298 bool IsSharedHeld(const Thread* self) const;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700299
300 // Assert the current thread has shared access to the ReaderWriterMutex.
Mathieu Chartier3768ade2017-05-02 14:04:39 -0700301 ALWAYS_INLINE void AssertSharedHeld(const Thread* self) ASSERT_SHARED_CAPABILITY(this) {
Nicolas Geoffraydb978712014-12-09 13:33:38 +0000302 if (kDebugLocking && (gAborting == 0)) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700303 // TODO: we can only assert this well when self != null.
304 CHECK(IsSharedHeld(self) || self == nullptr) << *this;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700305 }
306 }
Mathieu Chartier3768ade2017-05-02 14:04:39 -0700307 ALWAYS_INLINE void AssertReaderHeld(const Thread* self) ASSERT_SHARED_CAPABILITY(this) {
Mathieu Chartier90ef3db2015-08-04 15:19:41 -0700308 AssertSharedHeld(self);
309 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700310
311 // Assert the current thread doesn't hold this ReaderWriterMutex either in shared or exclusive
312 // mode.
Mathieu Chartier3768ade2017-05-02 14:04:39 -0700313 ALWAYS_INLINE void AssertNotHeld(const Thread* self) ASSERT_SHARED_CAPABILITY(!this) {
Nicolas Geoffraydb978712014-12-09 13:33:38 +0000314 if (kDebugLocking && (gAborting == 0)) {
Ian Rogers01ae5802012-09-28 16:14:01 -0700315 CHECK(!IsSharedHeld(self)) << *this;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700316 }
Elliott Hughes8daa0922011-09-11 13:46:25 -0700317 }
318
Ian Rogersc7190692014-07-08 23:50:26 -0700319 // Id associated with exclusive owner. No memory ordering semantics if called from a thread other
Hans Boehm0882af22017-08-31 15:21:57 -0700320 // than the owner. Returns 0 if the lock is not held. Returns either 0 or -1 if it is held by
321 // one or more readers.
322 pid_t GetExclusiveOwnerTid() const;
Elliott Hughes8daa0922011-09-11 13:46:25 -0700323
Yi Kong39402542019-03-24 02:47:16 -0700324 void Dump(std::ostream& os) const override;
Ian Rogers01ae5802012-09-28 16:14:01 -0700325
Mathieu Chartier90443472015-07-16 20:32:27 -0700326 // For negative capabilities in clang annotations.
327 const ReaderWriterMutex& operator!() const { return *this; }
328
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100329 void WakeupToRespondToEmptyCheckpoint() override;
Hiroshi Yamauchia2224042017-02-08 16:35:45 -0800330
Ian Rogers81d425b2012-09-27 16:03:43 -0700331 private:
Ian Rogers51d212e2014-10-23 17:48:20 -0700332#if ART_USE_FUTEXES
Ian Rogerscf7f1912014-10-22 22:06:39 -0700333 // Out-of-inline path for handling contention for a SharedLock.
334 void HandleSharedLockContention(Thread* self, int32_t cur_state);
335
Ian Rogers81d425b2012-09-27 16:03:43 -0700336 // -1 implies held exclusive, +ve shared held by state_ many owners.
Ian Rogersc7190692014-07-08 23:50:26 -0700337 AtomicInteger state_;
338 // Exclusive owner. Modification guarded by this mutex.
Hans Boehm0882af22017-08-31 15:21:57 -0700339 Atomic<pid_t> exclusive_owner_;
Ian Rogersc7190692014-07-08 23:50:26 -0700340 // Number of contenders waiting for a reader share.
341 AtomicInteger num_pending_readers_;
342 // Number of contenders waiting to be the writer.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800343 AtomicInteger num_pending_writers_;
Ian Rogers81d425b2012-09-27 16:03:43 -0700344#else
345 pthread_rwlock_t rwlock_;
Hans Boehm0882af22017-08-31 15:21:57 -0700346 Atomic<pid_t> exclusive_owner_; // Writes guarded by rwlock_. Asynchronous reads are OK.
Ian Rogers81d425b2012-09-27 16:03:43 -0700347#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700348 DISALLOW_COPY_AND_ASSIGN(ReaderWriterMutex);
349};
350
Yu Lieac44242015-06-29 10:50:03 +0800351// MutatorMutex is a special kind of ReaderWriterMutex created specifically for the
352// Locks::mutator_lock_ mutex. The behaviour is identical to the ReaderWriterMutex except that
353// thread state changes also play a part in lock ownership. The mutator_lock_ will not be truly
354// held by any mutator threads. However, a thread in the kRunnable state is considered to have
355// shared ownership of the mutator lock and therefore transitions in and out of the kRunnable
356// state have associated implications on lock ownership. Extra methods to handle the state
357// transitions have been added to the interface but are only accessible to the methods dealing
358// with state transitions. The thread state and flags attributes are used to ensure thread state
359// transitions are consistent with the permitted behaviour of the mutex.
360//
361// *) The most important consequence of this behaviour is that all threads must be in one of the
362// suspended states before exclusive ownership of the mutator mutex is sought.
363//
364std::ostream& operator<<(std::ostream& os, const MutatorMutex& mu);
Mathieu Chartier90443472015-07-16 20:32:27 -0700365class SHARED_LOCKABLE MutatorMutex : public ReaderWriterMutex {
Yu Lieac44242015-06-29 10:50:03 +0800366 public:
367 explicit MutatorMutex(const char* name, LockLevel level = kDefaultMutexLevel)
368 : ReaderWriterMutex(name, level) {}
369 ~MutatorMutex() {}
370
371 virtual bool IsMutatorMutex() const { return true; }
372
Mathieu Chartier90443472015-07-16 20:32:27 -0700373 // For negative capabilities in clang annotations.
374 const MutatorMutex& operator!() const { return *this; }
375
Yu Lieac44242015-06-29 10:50:03 +0800376 private:
377 friend class Thread;
378 void TransitionFromRunnableToSuspended(Thread* self) UNLOCK_FUNCTION() ALWAYS_INLINE;
379 void TransitionFromSuspendedToRunnable(Thread* self) SHARED_LOCK_FUNCTION() ALWAYS_INLINE;
380
381 DISALLOW_COPY_AND_ASSIGN(MutatorMutex);
382};
383
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700384// ConditionVariables allow threads to queue and sleep. Threads may then be resumed individually
385// (Signal) or all at once (Broadcast).
Elliott Hughes5f791332011-09-15 17:45:30 -0700386class ConditionVariable {
387 public:
Roland Levillain3887c462015-08-12 18:15:42 +0100388 ConditionVariable(const char* name, Mutex& mutex);
Elliott Hughes5f791332011-09-15 17:45:30 -0700389 ~ConditionVariable();
390
Charles Mungerbcd16ee2018-10-22 13:03:23 -0700391 // Requires the mutex to be held.
Ian Rogersc604d732012-10-14 16:09:54 -0700392 void Broadcast(Thread* self);
Charles Mungerbcd16ee2018-10-22 13:03:23 -0700393 // Requires the mutex to be held.
Ian Rogersc604d732012-10-14 16:09:54 -0700394 void Signal(Thread* self);
395 // TODO: No thread safety analysis on Wait and TimedWait as they call mutex operations via their
396 // pointer copy, thereby defeating annotalysis.
397 void Wait(Thread* self) NO_THREAD_SAFETY_ANALYSIS;
Ian Rogers7b078e82014-09-10 14:44:24 -0700398 bool TimedWait(Thread* self, int64_t ms, int32_t ns) NO_THREAD_SAFETY_ANALYSIS;
Ian Rogers1d54e732013-05-02 21:10:01 -0700399 // Variant of Wait that should be used with caution. Doesn't validate that no mutexes are held
400 // when waiting.
401 // TODO: remove this.
402 void WaitHoldingLocks(Thread* self) NO_THREAD_SAFETY_ANALYSIS;
Elliott Hughes5f791332011-09-15 17:45:30 -0700403
404 private:
Ian Rogers23055dc2013-04-18 16:29:16 -0700405 const char* const name_;
Ian Rogersc604d732012-10-14 16:09:54 -0700406 // The Mutex being used by waiters. It is an error to mix condition variables between different
407 // Mutexes.
408 Mutex& guard_;
409#if ART_USE_FUTEXES
410 // A counter that is modified by signals and broadcasts. This ensures that when a waiter gives up
Ian Rogersd45f2012012-11-28 11:46:23 -0800411 // their Mutex and another thread takes it and signals, the waiting thread observes that sequence_
412 // changed and doesn't enter the wait. Modified while holding guard_, but is read by futex wait
413 // without guard_ held.
Ian Rogersb122a4b2013-11-19 18:00:50 -0800414 AtomicInteger sequence_;
Ian Rogersc604d732012-10-14 16:09:54 -0700415 // Number of threads that have come into to wait, not the length of the waiters on the futex as
Ian Rogers5bd97c42012-11-27 02:38:26 -0800416 // waiters may have been requeued onto guard_. Guarded by guard_.
Ian Rogersc604d732012-10-14 16:09:54 -0700417 volatile int32_t num_waiters_;
Charles Mungerbcd16ee2018-10-22 13:03:23 -0700418
419 void RequeueWaiters(int32_t count);
Ian Rogersc604d732012-10-14 16:09:54 -0700420#else
421 pthread_cond_t cond_;
422#endif
Elliott Hughes5f791332011-09-15 17:45:30 -0700423 DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
424};
425
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700426// Scoped locker/unlocker for a regular Mutex that acquires mu upon construction and releases it
427// upon destruction.
Mathieu Chartier90443472015-07-16 20:32:27 -0700428class SCOPED_CAPABILITY MutexLock {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700429 public:
Roland Levillain3887c462015-08-12 18:15:42 +0100430 MutexLock(Thread* self, Mutex& mu) ACQUIRE(mu) : self_(self), mu_(mu) {
Ian Rogers81d425b2012-09-27 16:03:43 -0700431 mu_.ExclusiveLock(self_);
432 }
433
Mathieu Chartier4e2cb092015-07-22 16:17:51 -0700434 ~MutexLock() RELEASE() {
Ian Rogers81d425b2012-09-27 16:03:43 -0700435 mu_.ExclusiveUnlock(self_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700436 }
437
438 private:
Ian Rogers81d425b2012-09-27 16:03:43 -0700439 Thread* const self_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700440 Mutex& mu_;
441 DISALLOW_COPY_AND_ASSIGN(MutexLock);
442};
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700443
444// Scoped locker/unlocker for a ReaderWriterMutex that acquires read access to mu upon
445// construction and releases it upon destruction.
Mathieu Chartier90443472015-07-16 20:32:27 -0700446class SCOPED_CAPABILITY ReaderMutexLock {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700447 public:
Andreas Gampeb486a982017-06-01 13:45:54 -0700448 ALWAYS_INLINE ReaderMutexLock(Thread* self, ReaderWriterMutex& mu) ACQUIRE(mu);
Ian Rogers81d425b2012-09-27 16:03:43 -0700449
Andreas Gampeb486a982017-06-01 13:45:54 -0700450 ALWAYS_INLINE ~ReaderMutexLock() RELEASE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700451
452 private:
Ian Rogers81d425b2012-09-27 16:03:43 -0700453 Thread* const self_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700454 ReaderWriterMutex& mu_;
455 DISALLOW_COPY_AND_ASSIGN(ReaderMutexLock);
456};
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700457
458// Scoped locker/unlocker for a ReaderWriterMutex that acquires write access to mu upon
459// construction and releases it upon destruction.
Mathieu Chartier90443472015-07-16 20:32:27 -0700460class SCOPED_CAPABILITY WriterMutexLock {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700461 public:
Roland Levillain3887c462015-08-12 18:15:42 +0100462 WriterMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
Ian Rogers81d425b2012-09-27 16:03:43 -0700463 self_(self), mu_(mu) {
464 mu_.ExclusiveLock(self_);
465 }
466
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700467 ~WriterMutexLock() UNLOCK_FUNCTION() {
Ian Rogers81d425b2012-09-27 16:03:43 -0700468 mu_.ExclusiveUnlock(self_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700469 }
470
471 private:
Ian Rogers50b35e22012-10-04 10:09:15 -0700472 Thread* const self_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700473 ReaderWriterMutex& mu_;
474 DISALLOW_COPY_AND_ASSIGN(WriterMutexLock);
475};
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700476
Elliott Hughes8daa0922011-09-11 13:46:25 -0700477} // namespace art
478
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700479#endif // ART_RUNTIME_BASE_MUTEX_H_