1 /*++ 2 3 Copyright (c) Microsoft Corporation 4 5 Module Name: 6 7 FxSpinLock.cpp 8 9 Abstract: 10 11 This module implements FxSpinLock 12 13 Author: 14 15 16 17 Environment: 18 19 Both kernel and user mode 20 21 Revision History: 22 23 --*/ 24 25 #include "fxsupportpch.hpp" 26 #include "fxspinlock.hpp" 27 28 extern "C" { 29 // #include "FxSpinLock.tmh" 30 } 31 32 FxSpinLock::FxSpinLock( 33 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 34 __in USHORT ExtraSize 35 ) : 36 FxObject(FX_TYPE_SPIN_LOCK, COMPUTE_OBJECT_SIZE(sizeof(FxSpinLock), ExtraSize), FxDriverGlobals) 37 { 38 FX_SPIN_LOCK_HISTORY* pHistory; 39 40 m_Irql = 0; 41 m_InterruptLock = FALSE; 42 43 pHistory = GetHistory(); 44 45 if (pHistory != NULL) { 46 RtlZeroMemory(pHistory, sizeof(FX_SPIN_LOCK_HISTORY)); 47 48 pHistory->CurrentHistory = &pHistory->History[0]; 49 } 50 } 51 52 53 __drv_raisesIRQL(DISPATCH_LEVEL) 54 __drv_maxIRQL(DISPATCH_LEVEL) 55 VOID 56 FxSpinLock::AcquireLock( 57 __in PVOID CallersAddress 58 ) 59 { 60 PFX_SPIN_LOCK_HISTORY pHistory; 61 KIRQL irql; 62 63 m_SpinLock.Acquire(&irql); 64 65 m_Irql = irql; 66 67 pHistory = GetHistory(); 68 69 if (pHistory != NULL) { 70 PFX_SPIN_LOCK_HISTORY_ENTRY pCur; 71 72 // 73 // This assert should never fire here, but this helps track ownership 74 // in the case of a release without an acquire. 75 // 76 ASSERT(pHistory->OwningThread == NULL); 77 pHistory->OwningThread = Mx::MxGetCurrentThread(); 78 79 pCur = pHistory->CurrentHistory; 80 81 Mx::MxQueryTickCount(&pCur->AcquiredAtTime); 82 pCur->CallersAddress = CallersAddress; 83 } 84 } 85 86 __drv_requiresIRQL(DISPATCH_LEVEL) 87 VOID 88 FxSpinLock::ReleaseLock( 89 VOID 90 ) 91 { 92 PFX_SPIN_LOCK_HISTORY pHistory; 93 94 pHistory = GetHistory(); 95 96 if (pHistory != NULL) { 97 LARGE_INTEGER now; 98 PFX_SPIN_LOCK_HISTORY_ENTRY pCur; 99 100 if (pHistory->OwningThread != Mx::MxGetCurrentThread()) { 101 if (pHistory->OwningThread == NULL) { 102 DoTraceLevelMessage( 103 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGERROR, 104 "WDFSPINLOCK %p being released by thread 0x%p, but was " 105 "never acquired!", GetObjectHandle(), Mx::MxGetCurrentThread()); 106 } 107 else { 108 DoTraceLevelMessage( 109 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGERROR, 110 "WDFSPINLOCK 0x%p not owned by thread 0x%p, owned by thread 0x%p", 111 GetObjectHandle(), Mx::MxGetCurrentThread(), 112 pHistory->OwningThread); 113 } 114 115 FxVerifierBugCheck(GetDriverGlobals(), 116 WDF_INVALID_LOCK_OPERATION, 117 (ULONG_PTR) GetObjectHandle(), 118 0x1); 119 // 120 // Will not get here 121 // 122 return; 123 } 124 125 ASSERT(pHistory->OwningThread != NULL); 126 127 Mx::MxQueryTickCount(&now); 128 129 pCur = pHistory->CurrentHistory; 130 pCur->LockedDuraction = now.QuadPart - pCur->AcquiredAtTime.QuadPart; 131 132 pHistory->CurrentHistory++; 133 if (pHistory->CurrentHistory >= 134 pHistory->History + FX_SPIN_LOCK_NUM_HISTORY_ENTRIES) { 135 pHistory->CurrentHistory = pHistory->History; 136 } 137 138 pHistory->OwningThread = NULL; 139 } 140 141 m_SpinLock.Release(m_Irql); 142 } 143