1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/lock_impl.h" 6 #include "base/logging.h" 7 8 // NOTE: Although windows critical sections support recursive locks, we do not 9 // allow this, and we will commonly fire a DCHECK() if a thread attempts to 10 // acquire the lock a second time (while already holding it). 11 LockImpl()12LockImpl::LockImpl() { 13 #ifndef NDEBUG 14 recursion_count_shadow_ = 0; 15 recursion_used_ = false; 16 owning_thread_id_ = 0; 17 #endif // NDEBUG 18 // The second parameter is the spin count, for short-held locks it avoid the 19 // contending thread from going to sleep which helps performance greatly. 20 ::InitializeCriticalSectionAndSpinCount(&os_lock_, 2000); 21 } 22 ~LockImpl()23LockImpl::~LockImpl() { 24 ::DeleteCriticalSection(&os_lock_); 25 } 26 Try()27bool LockImpl::Try() { 28 if (::TryEnterCriticalSection(&os_lock_) != FALSE) { 29 #ifndef NDEBUG 30 // ONLY access data after locking. 31 owning_thread_id_ = PlatformThread::CurrentId(); 32 DCHECK_NE(owning_thread_id_, 0); 33 recursion_count_shadow_++; 34 if (2 == recursion_count_shadow_ && !recursion_used_) { 35 recursion_used_ = true; 36 DCHECK(false); // Catch accidental redundant lock acquisition. 37 } 38 #endif 39 return true; 40 } 41 return false; 42 } 43 Lock()44void LockImpl::Lock() { 45 ::EnterCriticalSection(&os_lock_); 46 #ifndef NDEBUG 47 // ONLY access data after locking. 48 owning_thread_id_ = PlatformThread::CurrentId(); 49 DCHECK_NE(owning_thread_id_, 0); 50 recursion_count_shadow_++; 51 if (2 == recursion_count_shadow_ && !recursion_used_) { 52 recursion_used_ = true; 53 DCHECK(false); // Catch accidental redundant lock acquisition. 54 } 55 #endif // NDEBUG 56 } 57 Unlock()58void LockImpl::Unlock() { 59 #ifndef NDEBUG 60 --recursion_count_shadow_; // ONLY access while lock is still held. 61 DCHECK(0 <= recursion_count_shadow_); 62 owning_thread_id_ = 0; 63 #endif // NDEBUG 64 ::LeaveCriticalSection(&os_lock_); 65 } 66 67 // In non-debug builds, this method is declared as an empty inline method. 68 #ifndef NDEBUG AssertAcquired() const69void LockImpl::AssertAcquired() const { 70 DCHECK(recursion_count_shadow_ > 0); 71 DCHECK_EQ(owning_thread_id_, PlatformThread::CurrentId()); 72 } 73 #endif 74