// Add this mutex to those owned by self, and optionally perform lock order checking. Caller // may wish to disable checking for trylock calls that cannot result in deadlock. For this call // only, self may also be another suspended thread. void RegisterAsLocked(Thread* self, bool check = kDebugLocking); void RegisterAsLockedImpl(Thread* self, LockLevel level, bool check);
// A log entry that records contention but makes no guarantee that either tid will be held live. struct ContentionLogEntry {
ContentionLogEntry() : blocked_tid(0), owner_tid(0) {}
uint64_t blocked_tid;
uint64_t owner_tid;
AtomicInteger count;
}; struct ContentionLogData {
ContentionLogEntry contention_log[kContentionLogSize]; // The next entry in the contention log to be updated. Value ranges from 0 to // kContentionLogSize - 1.
AtomicInteger cur_content_log_entry; // Number of times the Mutex has been contended.
AtomicInteger contention_count; // Sum of time waited by all contenders in ns.
Atomic<uint64_t> wait_time; void AddToWaitTime(uint64_t value);
ContentionLogData() : wait_time(0) {}
};
ContentionLogData contention_log_data_[kContentionLogDataSize];
const LockLevel level_; // Support for lock hierarchy. bool should_respond_to_empty_checkpoint_request_;
// A Mutex is used to achieve mutual exclusion between threads. A Mutex can be used to gain // exclusive access to what it guards. A Mutex can be in one of two states: // - Free - not owned by any thread, // - Exclusive - owned by a single thread. // // The effect of locking and unlocking operations on the state is: // State | ExclusiveLock | ExclusiveUnlock // ------------------------------------------- // Free | Exclusive | error // Exclusive | Block* | Free // * Mutex is not reentrant unless recursive is true. An attempt to ExclusiveLock on a // recursive=false Mutex on a thread already owning the Mutex results in an error. // // TODO(b/140590186): Remove support for recursive == true. // // Some mutexes, including those associated with Java monitors may be accessed (in particular // acquired) by a thread in suspended state. Suspending all threads does NOT prevent mutex state // from changing.
std::ostream& operator<<(std::ostream& os, const Mutex& mu); class EXPORT LOCKABLE Mutex : public BaseMutex { public: explicit Mutex(constchar* name, LockLevel level = kDefaultMutexLevel, bool recursive = false);
~Mutex();
bool IsMutex() const override { returntrue; }
// Block until mutex is free then acquire exclusive access. void ExclusiveLock(Thread* self) ACQUIRE(); void Lock(Thread* self) ACQUIRE() { ExclusiveLock(self); }
// Returns true if acquires exclusive access, false otherwise. The `check` argument specifies // whether lock level checking should be performed. Should be defaulted unless we are using // TryLock instead of Lock for deadlock avoidance. template <bool kCheck = kDebugLocking> bool ExclusiveTryLock(Thread* self) TRY_ACQUIRE(true); bool TryLock(Thread* self) TRY_ACQUIRE(true) { return ExclusiveTryLock(self); } // Equivalent to ExclusiveTryLock, but retry for a short period before giving up. bool ExclusiveTryLockWithSpinning(Thread* self) TRY_ACQUIRE(true);
// Is the current thread the exclusive holder of the Mutex.
ALWAYS_INLINE bool IsExclusiveHeld(const Thread* self) const;
// Assert that the Mutex is exclusively held by the current thread.
ALWAYS_INLINE void AssertExclusiveHeld(const Thread* self) const ASSERT_CAPABILITY(this);
ALWAYS_INLINE void AssertHeld(const Thread* self) const ASSERT_CAPABILITY(this);
// Assert that the Mutex is not held by the current thread. void AssertNotHeldExclusive(const Thread* self) ASSERT_CAPABILITY(!*this) { if (kDebugLocking && (gAborting == 0)) {
CHECK(!IsExclusiveHeld(self)) << *this;
}
} void AssertNotHeld(const Thread* self) ASSERT_CAPABILITY(!*this) {
AssertNotHeldExclusive(self);
}
// Id associated with exclusive owner. No memory ordering semantics if called from a thread // other than the owner. GetTid() == GetExclusiveOwnerTid() is a reliable way to determine // whether we hold the lock; any other information may be invalidated before we return.
pid_t GetExclusiveOwnerTid() const;
// Returns how many times this Mutex has been locked, it is typically better to use // AssertHeld/NotHeld. For a simply held mutex this method returns 1. Should only be called // while holding the mutex or threads are suspended. unsignedint GetDepth() const { return recursion_count_;
}
// For negative capabilities in clang annotations. const Mutex& operator!() const { return *this; }
void WakeupToRespondToEmptyCheckpoint() override;
#if ART_USE_FUTEXES // Acquire the mutex, possibly on behalf of another thread. Acquisition must be // uncontended. New_owner must be current thread or suspended. // Mutex must be at level kMonitorLock. // Not implementable for the pthreads version, so we must avoid calling it there. void ExclusiveLockUncontendedFor(Thread* new_owner);
// Undo the effect of the previous calling, setting the mutex back to unheld. // Still assumes no concurrent access. void ExclusiveUnlockUncontended(); #endif// ART_USE_FUTEXES
protected: // The default implementation returns the tid of the thread. virtual pid_t GetSelfId(const Thread* self) const; void ExclusiveLockUncontendedForSelfId(pid_t selfId);
private: #if ART_USE_FUTEXES // Low order bit: 0 is unheld, 1 is held. // High order bits: Number of waiting contenders.
AtomicInteger state_and_contenders_;
int32_t get_contenders() { // Result is guaranteed to include any contention added by this thread; otherwise approximate. // Treat contenders as unsigned because we're concerned about overflow; should never matter. returnstatic_cast<uint32_t>(state_and_contenders_.load(std::memory_order_relaxed))
>> kContenderShift;
}
// Exclusive owner.
Atomic<pid_t> exclusive_owner_; #else
pthread_mutex_t mutex_;
Atomic<pid_t> exclusive_owner_; // Guarded by mutex_. Asynchronous reads are OK. #endif
unsignedint recursion_count_; constbool recursive_; // Can the lock be recursively held?
// Acquire the mutex, possibly on behalf of another thread. Acquisition must be // uncontended. The virtual thread represented by virtual_thread_id must be // either suspended or mounted to the current platform thread, i.e. Thread::Current(). void ExclusiveLockUncontendedForVirtualThreadId(uint32_t virtual_thread_id);
protected: // Use the most significant bit of a 32-bit integer to indicate that it's a virtual thread. // The max of PID_MAX_LIMIT on Android is 2^22. See Android kernel's <include/linux/threads.h> // pid_t should have at least 32 bits.
pid_t GetSelfId(const Thread* self) const override;
// A ReaderWriterMutex is used to achieve mutual exclusion between threads, similar to a Mutex. // Unlike a Mutex a ReaderWriterMutex can be used to gain exclusive (writer) or shared (reader) // access to what it guards. A flaw in relation to a Mutex is that it cannot be used with a // condition variable. A ReaderWriterMutex can be in one of three states: // - Free - not owned by any thread, // - Exclusive - owned by a single thread, // - Shared(n) - shared amongst n threads. // // The effect of locking and unlocking operations on the state is: // // State | ExclusiveLock | ExclusiveUnlock | SharedLock | SharedUnlock // ---------------------------------------------------------------------------- // Free | Exclusive | error | SharedLock(1) | error // Exclusive | Block | Free | Block | error // Shared(n) | Block | error | SharedLock(n+1)* | Shared(n-1) or Free // * for large values of n the SharedLock may block.
EXPORT std::ostream& operator<<(std::ostream& os, const ReaderWriterMutex& mu); class EXPORT SHARED_LOCKABLE ReaderWriterMutex : public BaseMutex { public: explicit ReaderWriterMutex(constchar* name, LockLevel level = kDefaultMutexLevel);
~ReaderWriterMutex();
// Block until ReaderWriterMutex is free and acquire exclusive access. Returns true on success // or false if timeout is reached. #if HAVE_TIMED_RWLOCK bool ExclusiveLockWithTimeout(Thread* self, int64_t ms, int32_t ns)
EXCLUSIVE_TRYLOCK_FUNCTION(true); #endif
// Block until ReaderWriterMutex is shared or free then acquire a share on the access. void SharedLock(Thread* self) ACQUIRE_SHARED() ALWAYS_INLINE; void ReaderLock(Thread* self) ACQUIRE_SHARED() { SharedLock(self); }
// Try to acquire share of ReaderWriterMutex. bool SharedTryLock(Thread* self, bool check = kDebugLocking) SHARED_TRYLOCK_FUNCTION(true);
// Release a share of the access. void SharedUnlock(Thread* self) RELEASE_SHARED() ALWAYS_INLINE; void ReaderUnlock(Thread* self) RELEASE_SHARED() { SharedUnlock(self); }
// Is the current thread the exclusive holder of the ReaderWriterMutex.
ALWAYS_INLINE bool IsExclusiveHeld(const Thread* self) const;
// Assert the current thread has exclusive access to the ReaderWriterMutex.
ALWAYS_INLINE void AssertExclusiveHeld(const Thread* self) const ASSERT_CAPABILITY(this);
ALWAYS_INLINE void AssertWriterHeld(const Thread* self) const ASSERT_CAPABILITY(this);
// Assert the current thread doesn't have exclusive access to the ReaderWriterMutex. void AssertNotExclusiveHeld(const Thread* self) ASSERT_CAPABILITY(!this) { if (kDebugLocking && (gAborting == 0)) {
CHECK(!IsExclusiveHeld(self)) << *this;
}
} void AssertNotWriterHeld(const Thread* self) ASSERT_CAPABILITY(!this) {
AssertNotExclusiveHeld(self);
}
// Is the current thread a shared holder of the ReaderWriterMutex. bool IsSharedHeld(const Thread* self) const;
// Assert the current thread has shared access to the ReaderWriterMutex.
ALWAYS_INLINE void AssertSharedHeld(const Thread* self) ASSERT_SHARED_CAPABILITY(this) { if (kDebugLocking && (gAborting == 0)) { // TODO: we can only assert this well when self != null.
CHECK(IsSharedHeld(self) || self == nullptr) << *this;
}
}
ALWAYS_INLINE void AssertReaderHeld(const Thread* self) ASSERT_SHARED_CAPABILITY(this) {
AssertSharedHeld(self);
}
// Assert the current thread doesn't hold this ReaderWriterMutex either in shared or exclusive // mode.
ALWAYS_INLINE void AssertNotHeld(const Thread* self)
ASSERT_CAPABILITY(!this) ASSERT_SHARED_CAPABILITY(!this) { if (kDebugLocking && (gAborting == 0)) {
CHECK(!IsExclusiveHeld(self)) << *this;
CHECK(!IsSharedHeld(self)) << *this;
}
}
// Id associated with exclusive owner. No memory ordering semantics if called from a thread other // than the owner. Returns 0 if the lock is not held. Returns either 0 or -1 if it is held by // one or more readers. Not reliable unless the mutex is held.
pid_t GetExclusiveOwnerTid() const;
void Dump(std::ostream& os) const override;
// For negative capabilities in clang annotations. const ReaderWriterMutex& operator!() const { return *this; }
void WakeupToRespondToEmptyCheckpoint() override;
private:
ALWAYS_INLINE void FinishRWExclusiveLock(Thread* self); #if ART_USE_FUTEXES // Out-of-inline path for handling contention for a SharedLock. void HandleSharedLockContention(Thread* self, int32_t cur_state);
// -1 implies held exclusive, >= 0: shared held by state_ many owners.
AtomicInteger state_; // Number of contenders waiting for either a reader share or exclusive access. We only maintain // the sum, since we would otherwise need to read both in all unlock operations. // We keep this separate from the state, since futexes are limited to 32 bits, and obvious // approaches to combining with state_ risk overflow.
AtomicInteger num_contenders_; #else
pthread_rwlock_t rwlock_; // We use a second lock to allow downgrades from exclusive to shared, in spite of the fact that // pthread_wlock_t does not support it directly. This second lock is acquired around any writer // critical section, and retained during the downgrade operation.
pthread_mutex_t pre_write_lock_; #endif
Atomic<pid_t> exclusive_owner_; // Writes guarded by this rwlock. Asynchronous reads are OK.
DISALLOW_COPY_AND_ASSIGN(ReaderWriterMutex);
};
// MutatorMutex is a special kind of ReaderWriterMutex created specifically for the // Locks::mutator_lock_ mutex. The behaviour is identical to the ReaderWriterMutex except that // thread state changes also play a part in lock ownership. The mutator_lock_ will not be truly // held by any mutator threads. However, a thread in the kRunnable state is considered to have // shared ownership of the mutator lock and therefore transitions in and out of the kRunnable // state have associated implications on lock ownership. Extra methods to handle the state // transitions have been added to the interface but are only accessible to the methods dealing // with state transitions. The thread state and flags attributes are used to ensure thread state // transitions are consistent with the permitted behaviour of the mutex. // // *) The most important consequence of this behaviour is that all threads must be in one of the // suspended states before exclusive ownership of the mutator mutex is sought. //
std::ostream& operator<<(std::ostream& os, const MutatorMutex& mu); class SHARED_LOCKABLE MutatorMutex : public ReaderWriterMutex { public: explicit MutatorMutex(constchar* name, LockLevel level = kDefaultMutexLevel)
: ReaderWriterMutex(name, level) {}
~MutatorMutex() {}
// ConditionVariables allow threads to queue and sleep. Threads may then be resumed individually // (Signal) or all at once (Broadcast). class EXPORT ConditionVariable { public:
ConditionVariable(constchar* name, Mutex& mutex);
~ConditionVariable();
// Requires the mutex to be held. void Broadcast(Thread* self); // Requires the mutex to be held. void Signal(Thread* self); // TODO: No thread safety analysis on Wait and TimedWait as they call mutex operations via their // pointer copy, thereby defeating annotalysis. void Wait(Thread* self) NO_THREAD_SAFETY_ANALYSIS; bool TimedWait(Thread* self, int64_t ms, int32_t ns) NO_THREAD_SAFETY_ANALYSIS; // Variant of Wait that should be used with caution. Doesn't validate that no mutexes are held // when waiting. // TODO: remove this. void WaitHoldingLocks(Thread* self) NO_THREAD_SAFETY_ANALYSIS;
private: constchar* const name_; // The Mutex being used by waiters. It is an error to mix condition variables between different // Mutexes.
Mutex& guard_; #if ART_USE_FUTEXES // A counter that is modified by signals and broadcasts. This ensures that when a waiter gives up // their Mutex and another thread takes it and signals, the waiting thread observes that sequence_ // changed and doesn't enter the wait. Modified while holding guard_, but is read by futex wait // without guard_ held.
AtomicInteger sequence_; // Number of threads that have come into to wait, not the length of the waiters on the futex as // waiters may have been requeued onto guard_. Guarded by guard_.
int32_t num_waiters_;
// Scoped locker/unlocker for a regular Mutex that acquires mu upon construction and releases it // upon destruction. class SCOPED_CAPABILITY MutexLock { public:
MutexLock(Thread* self, Mutex& mu) ACQUIRE(mu) : self_(self), mu_(mu) {
mu_.ExclusiveLock(self_);
}
// Pretend to acquire a mutex for checking purposes, without actually doing so. Use with // extreme caution when it is known the condition that the mutex would guard against cannot arise. template <typename T> class SCOPED_CAPABILITY FakeMutexLock { public: explicit FakeMutexLock(T& mu) ACQUIRE(mu) NO_THREAD_SAFETY_ANALYSIS {}
// Scoped locker/unlocker for a ReaderWriterMutex that acquires read access to mu upon // construction and releases it upon destruction. class SCOPED_CAPABILITY ReaderMutexLock { public:
ALWAYS_INLINE ReaderMutexLock(Thread* self, ReaderWriterMutex& mu) ACQUIRE(mu);
// Pretend to acquire read access for checking purposes, without actually doing so. Use with // extreme caution when it is known the condition that the mutex would guard against cannot arise. class SCOPED_CAPABILITY FakeReaderMutexLock { public:
ALWAYS_INLINE FakeReaderMutexLock(ReaderWriterMutex& mu) ACQUIRE(mu) NO_THREAD_SAFETY_ANALYSIS {}
// Scoped locker/unlocker for a ReaderWriterMutex that acquires write access to mu upon // construction and releases it upon destruction. class SCOPED_CAPABILITY WriterMutexLock { public:
WriterMutexLock(Thread* self, ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) :
self_(self), mu_(mu) {
mu_.ExclusiveLock(self_);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.