1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_SYNCHRONIZATION_LOCK_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_SYNCHRONIZATION_LOCK_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h" 9*6777b538SAndroid Build Coastguard Worker #include "base/dcheck_is_on.h" 10*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/lock_impl.h" 11*6777b538SAndroid Build Coastguard Worker #include "base/thread_annotations.h" 12*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h" 13*6777b538SAndroid Build Coastguard Worker 14*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON() 15*6777b538SAndroid Build Coastguard Worker #include "base/threading/platform_thread_ref.h" 16*6777b538SAndroid Build Coastguard Worker #endif 17*6777b538SAndroid Build Coastguard Worker 18*6777b538SAndroid Build Coastguard Worker namespace base { 19*6777b538SAndroid Build Coastguard Worker 20*6777b538SAndroid Build Coastguard Worker // A convenient wrapper for an OS specific critical section. The only real 21*6777b538SAndroid Build Coastguard Worker // intelligence in this class is in debug mode for the support for the 22*6777b538SAndroid Build Coastguard Worker // AssertAcquired() method. 23*6777b538SAndroid Build Coastguard Worker class LOCKABLE BASE_EXPORT Lock { 24*6777b538SAndroid Build Coastguard Worker public: 25*6777b538SAndroid Build Coastguard Worker #if !DCHECK_IS_ON() 26*6777b538SAndroid Build Coastguard Worker // Optimized wrapper implementation Lock()27*6777b538SAndroid Build Coastguard Worker Lock() : lock_() {} 28*6777b538SAndroid Build Coastguard Worker 29*6777b538SAndroid Build Coastguard Worker Lock(const Lock&) = delete; 30*6777b538SAndroid Build Coastguard Worker Lock& operator=(const Lock&) = delete; 31*6777b538SAndroid Build Coastguard Worker ~Lock()32*6777b538SAndroid Build Coastguard Worker ~Lock() {} 33*6777b538SAndroid Build Coastguard Worker Acquire()34*6777b538SAndroid Build Coastguard Worker void Acquire() EXCLUSIVE_LOCK_FUNCTION() { lock_.Lock(); } Release()35*6777b538SAndroid Build Coastguard Worker void Release() UNLOCK_FUNCTION() { lock_.Unlock(); } 36*6777b538SAndroid Build Coastguard Worker 37*6777b538SAndroid Build Coastguard Worker // If the lock is not held, take it and return true. If the lock is already 38*6777b538SAndroid Build Coastguard Worker // held by another thread, immediately return false. This must not be called 39*6777b538SAndroid Build Coastguard Worker // by a thread already holding the lock (what happens is undefined and an 40*6777b538SAndroid Build Coastguard Worker // assertion may fail). Try()41*6777b538SAndroid Build Coastguard Worker bool Try() EXCLUSIVE_TRYLOCK_FUNCTION(true) { return lock_.Try(); } 42*6777b538SAndroid Build Coastguard Worker 43*6777b538SAndroid Build Coastguard Worker // Null implementation if not debug. AssertAcquired()44*6777b538SAndroid Build Coastguard Worker void AssertAcquired() const ASSERT_EXCLUSIVE_LOCK() {} AssertNotHeld()45*6777b538SAndroid Build Coastguard Worker void AssertNotHeld() const {} 46*6777b538SAndroid Build Coastguard Worker #else 47*6777b538SAndroid Build Coastguard Worker Lock(); 48*6777b538SAndroid Build Coastguard Worker ~Lock(); 49*6777b538SAndroid Build Coastguard Worker 50*6777b538SAndroid Build Coastguard Worker // NOTE: We do not permit recursive locks and will commonly fire a DCHECK() if 51*6777b538SAndroid Build Coastguard Worker // a thread attempts to acquire the lock a second time (while already holding 52*6777b538SAndroid Build Coastguard Worker // it). 53*6777b538SAndroid Build Coastguard Worker void Acquire() EXCLUSIVE_LOCK_FUNCTION() { 54*6777b538SAndroid Build Coastguard Worker lock_.Lock(); 55*6777b538SAndroid Build Coastguard Worker CheckUnheldAndMark(); 56*6777b538SAndroid Build Coastguard Worker } 57*6777b538SAndroid Build Coastguard Worker void Release() UNLOCK_FUNCTION() { 58*6777b538SAndroid Build Coastguard Worker CheckHeldAndUnmark(); 59*6777b538SAndroid Build Coastguard Worker lock_.Unlock(); 60*6777b538SAndroid Build Coastguard Worker } 61*6777b538SAndroid Build Coastguard Worker 62*6777b538SAndroid Build Coastguard Worker bool Try() EXCLUSIVE_TRYLOCK_FUNCTION(true) { 63*6777b538SAndroid Build Coastguard Worker bool rv = lock_.Try(); 64*6777b538SAndroid Build Coastguard Worker if (rv) { 65*6777b538SAndroid Build Coastguard Worker CheckUnheldAndMark(); 66*6777b538SAndroid Build Coastguard Worker } 67*6777b538SAndroid Build Coastguard Worker return rv; 68*6777b538SAndroid Build Coastguard Worker } 69*6777b538SAndroid Build Coastguard Worker 70*6777b538SAndroid Build Coastguard Worker void AssertAcquired() const ASSERT_EXCLUSIVE_LOCK(); 71*6777b538SAndroid Build Coastguard Worker void AssertNotHeld() const; 72*6777b538SAndroid Build Coastguard Worker #endif // DCHECK_IS_ON() 73*6777b538SAndroid Build Coastguard Worker 74*6777b538SAndroid Build Coastguard Worker // Whether Lock mitigates priority inversion when used from different thread 75*6777b538SAndroid Build Coastguard Worker // priorities. HandlesMultipleThreadPriorities()76*6777b538SAndroid Build Coastguard Worker static bool HandlesMultipleThreadPriorities() { 77*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN) 78*6777b538SAndroid Build Coastguard Worker // Windows mitigates priority inversion by randomly boosting the priority of 79*6777b538SAndroid Build Coastguard Worker // ready threads. 80*6777b538SAndroid Build Coastguard Worker // https://msdn.microsoft.com/library/windows/desktop/ms684831.aspx 81*6777b538SAndroid Build Coastguard Worker return true; 82*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) 83*6777b538SAndroid Build Coastguard Worker // POSIX mitigates priority inversion by setting the priority of a thread 84*6777b538SAndroid Build Coastguard Worker // holding a Lock to the maximum priority of any other thread waiting on it. 85*6777b538SAndroid Build Coastguard Worker return internal::LockImpl::PriorityInheritanceAvailable(); 86*6777b538SAndroid Build Coastguard Worker #else 87*6777b538SAndroid Build Coastguard Worker #error Unsupported platform 88*6777b538SAndroid Build Coastguard Worker #endif 89*6777b538SAndroid Build Coastguard Worker } 90*6777b538SAndroid Build Coastguard Worker 91*6777b538SAndroid Build Coastguard Worker // Both Windows and POSIX implementations of ConditionVariable need to be 92*6777b538SAndroid Build Coastguard Worker // able to see our lock and tweak our debugging counters, as they release and 93*6777b538SAndroid Build Coastguard Worker // acquire locks inside of their condition variable APIs. 94*6777b538SAndroid Build Coastguard Worker friend class ConditionVariable; 95*6777b538SAndroid Build Coastguard Worker 96*6777b538SAndroid Build Coastguard Worker private: 97*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON() 98*6777b538SAndroid Build Coastguard Worker // Members and routines taking care of locks assertions. 99*6777b538SAndroid Build Coastguard Worker // Note that this checks for recursive locks and allows them 100*6777b538SAndroid Build Coastguard Worker // if the variable is set. This is allowed by the underlying implementation 101*6777b538SAndroid Build Coastguard Worker // on windows but not on Posix, so we're doing unneeded checks on Posix. 102*6777b538SAndroid Build Coastguard Worker // It's worth it to share the code. 103*6777b538SAndroid Build Coastguard Worker void CheckHeldAndUnmark(); 104*6777b538SAndroid Build Coastguard Worker void CheckUnheldAndMark(); 105*6777b538SAndroid Build Coastguard Worker 106*6777b538SAndroid Build Coastguard Worker // All private data is implicitly protected by lock_. 107*6777b538SAndroid Build Coastguard Worker // Be VERY careful to only access members under that lock. 108*6777b538SAndroid Build Coastguard Worker base::PlatformThreadRef owning_thread_ref_; 109*6777b538SAndroid Build Coastguard Worker #endif // DCHECK_IS_ON() 110*6777b538SAndroid Build Coastguard Worker 111*6777b538SAndroid Build Coastguard Worker // Platform specific underlying lock implementation. 112*6777b538SAndroid Build Coastguard Worker internal::LockImpl lock_; 113*6777b538SAndroid Build Coastguard Worker }; 114*6777b538SAndroid Build Coastguard Worker 115*6777b538SAndroid Build Coastguard Worker // A helper class that acquires the given Lock while the AutoLock is in scope. 116*6777b538SAndroid Build Coastguard Worker using AutoLock = internal::BasicAutoLock<Lock>; 117*6777b538SAndroid Build Coastguard Worker 118*6777b538SAndroid Build Coastguard Worker // A helper class that tries to acquire the given Lock while the AutoTryLock is 119*6777b538SAndroid Build Coastguard Worker // in scope. 120*6777b538SAndroid Build Coastguard Worker using AutoTryLock = internal::BasicAutoTryLock<Lock>; 121*6777b538SAndroid Build Coastguard Worker 122*6777b538SAndroid Build Coastguard Worker // AutoUnlock is a helper that will Release() the |lock| argument in the 123*6777b538SAndroid Build Coastguard Worker // constructor, and re-Acquire() it in the destructor. 124*6777b538SAndroid Build Coastguard Worker using AutoUnlock = internal::BasicAutoUnlock<Lock>; 125*6777b538SAndroid Build Coastguard Worker 126*6777b538SAndroid Build Coastguard Worker // Like AutoLock but is a no-op when the provided Lock* is null. Inspired from 127*6777b538SAndroid Build Coastguard Worker // absl::MutexLockMaybe. Use this instead of std::optional<base::AutoLock> to 128*6777b538SAndroid Build Coastguard Worker // get around -Wthread-safety-analysis warnings for conditional locking. 129*6777b538SAndroid Build Coastguard Worker using AutoLockMaybe = internal::BasicAutoLockMaybe<Lock>; 130*6777b538SAndroid Build Coastguard Worker 131*6777b538SAndroid Build Coastguard Worker // Like AutoLock but permits Release() of its mutex before destruction. 132*6777b538SAndroid Build Coastguard Worker // Release() may be called at most once. Inspired from 133*6777b538SAndroid Build Coastguard Worker // absl::ReleasableMutexLock. Use this instead of std::optional<base::AutoLock> 134*6777b538SAndroid Build Coastguard Worker // to get around -Wthread-safety-analysis warnings for AutoLocks that are 135*6777b538SAndroid Build Coastguard Worker // explicitly released early (prefer proper scoping to this). 136*6777b538SAndroid Build Coastguard Worker using ReleasableAutoLock = internal::BasicReleasableAutoLock<Lock>; 137*6777b538SAndroid Build Coastguard Worker 138*6777b538SAndroid Build Coastguard Worker } // namespace base 139*6777b538SAndroid Build Coastguard Worker 140*6777b538SAndroid Build Coastguard Worker #endif // BASE_SYNCHRONIZATION_LOCK_H_ 141