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
FxSpinLock(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in USHORT ExtraSize)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)
__drv_maxIRQL(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
__drv_requiresIRQL(DISPATCH_LEVEL)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