1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxSpinLockAPI.cpp
8 
9 Abstract:
10 
11     This module implements external APIS to access 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 "FxSpinLockAPI.tmh"
30 }
31 
32 //
33 // Extern the entire file
34 //
35 extern "C" {
36 
37 _Must_inspect_result_
38 __drv_maxIRQL(DISPATCH_LEVEL)
39 NTSTATUS
40 STDCALL
41 WDFEXPORT(WdfSpinLockCreate)(
42     __in
43     PWDF_DRIVER_GLOBALS DriverGlobals,
44     __in_opt
45     PWDF_OBJECT_ATTRIBUTES SpinLockAttributes,
46     __out
47     WDFSPINLOCK* SpinLock
48     )
49 {
50     DDI_ENTRY();
51 
52     PFX_DRIVER_GLOBALS pFxDriverGlobals;
53     NTSTATUS status;
54     FxSpinLock* pLock;
55     WDFSPINLOCK lock;
56     USHORT extra;
57 
58     pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
59 
60     //
61     // Get the parent's globals if it is present
62     //
63     if (NT_SUCCESS(FxValidateObjectAttributesForParentHandle(
64                         pFxDriverGlobals, SpinLockAttributes))) {
65         FxObject* pParent;
66 
67         FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals,
68                                        SpinLockAttributes->ParentObject,
69                                        FX_TYPE_OBJECT,
70                                        (PVOID*)&pParent,
71                                        &pFxDriverGlobals);
72     }
73 
74     FxPointerNotNull(pFxDriverGlobals, SpinLock);
75 
76     status = FxValidateObjectAttributes(pFxDriverGlobals, SpinLockAttributes);
77     if (!NT_SUCCESS(status)) {
78         return status;
79     }
80 
81     if (pFxDriverGlobals->FxVerifierLock) {
82         extra = sizeof(FX_SPIN_LOCK_HISTORY);
83     }
84     else {
85         extra = 0;
86     }
87 
88     *SpinLock = NULL;
89 
90     pLock = new(pFxDriverGlobals, SpinLockAttributes, extra)
91         FxSpinLock(pFxDriverGlobals, extra);
92 
93     if (pLock == NULL) {
94         return STATUS_INSUFFICIENT_RESOURCES;
95     }
96 
97     status = pLock->Commit(SpinLockAttributes, (WDFOBJECT*)&lock);
98 
99     if (NT_SUCCESS(status)) {
100         *SpinLock = lock;
101     }
102     else {
103         pLock->DeleteFromFailedCreate();
104     }
105 
106     return status;
107 }
108 
109 __drv_raisesIRQL(DISPATCH_LEVEL)
110 __drv_maxIRQL(DISPATCH_LEVEL)
111 VOID
112 STDCALL
113 WDFEXPORT(WdfSpinLockAcquire)(
114     __in
115     PWDF_DRIVER_GLOBALS DriverGlobals,
116     __in
117     __drv_savesIRQL
118     _Requires_lock_not_held_(_Curr_)
119     _Acquires_lock_(_Curr_)
120     WDFSPINLOCK SpinLock
121     )
122 {
123     DDI_ENTRY();
124 
125     PFX_DRIVER_GLOBALS pFxDriverGlobals;
126     FxSpinLock* pLock;
127 
128     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
129                                    SpinLock,
130                                    FX_TYPE_SPIN_LOCK,
131                                    (PVOID*) &pLock,
132                                    &pFxDriverGlobals);
133 
134     if (pLock->IsInterruptLock()) {
135         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
136                             "WDFSPINLOCK %p is associated with an interrupt, "
137                             "cannot be used for normal sync operations",
138                             SpinLock);
139         FxVerifierDbgBreakPoint(pFxDriverGlobals);
140         return;
141     }
142 
143     pLock->AcquireLock(
144         pFxDriverGlobals->FxVerifierLock ? _ReturnAddress() : NULL);
145 }
146 
147 __drv_maxIRQL(DISPATCH_LEVEL)
148 __drv_minIRQL(DISPATCH_LEVEL)
149 VOID
150 STDCALL
151 WDFEXPORT(WdfSpinLockRelease)(
152     __in
153     PWDF_DRIVER_GLOBALS DriverGlobals,
154     __in
155     __drv_restoresIRQL
156     _Requires_lock_held_(_Curr_)
157     _Releases_lock_(_Curr_)
158     WDFSPINLOCK SpinLock
159     )
160 {
161     DDI_ENTRY();
162 
163     PFX_DRIVER_GLOBALS pFxDriverGlobals;
164     FxSpinLock* pLock;
165 
166     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
167                                    SpinLock,
168                                    FX_TYPE_SPIN_LOCK,
169                                    (PVOID*) &pLock,
170                                    &pFxDriverGlobals);
171 
172     if (pLock->IsInterruptLock()) {
173         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
174                             "WDFSPINLOCK %p is associated with an interrupt, "
175                             "cannot be used for normal sync operations",
176                             SpinLock);
177         FxVerifierDbgBreakPoint(pFxDriverGlobals);
178         return;
179     }
180 
181     pLock->ReleaseLock();
182 }
183 
184 } // extern "C"
185