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