ReactOS 0.4.16-dev-88-ga65b6ae
fxverifierlock.hpp
Go to the documentation of this file.
1/*++
2
3Copyright (c) Microsoft Corporation
4
5Module Name:
6
7 FxVerifierLock.hpp
8
9Abstract:
10
11 This is the C++ header for the verifier FxLock
12
13 This separate object allows the verifier overhead
14 to only be allocated when WdfVerifierLock is on.
15
16Author:
17
18
19
20Revision History:
21
22
23 Made it mode agnostic
24
25 New failure paths:
26 m_Mutex/m_Lock initialize
27 To enforce initialization hidden constructors
28 Callers are forced to use CreateAndInitialize methods
29
30--*/
31
32#ifndef _FXVERIFIERLOCK_HPP_
33#define _FXVERIFIERLOCK_HPP_
34
35extern "C" {
36#if defined(EVENT_TRACING)
37#include "FxVerifierLock.hpp.tmh"
38#endif
39}
40
72//
73// These locks are driver frameworks "internal" object
74// locks and are not intended to be held across callbacks
75// to the driver.
76//
77// They are acquired and released as the result of driver
78// calls into the frameworks, which may be holding a driver
79// callback lock.
80//
81#define FX_LOCK_ORDER_NONE 0x0000
82#define FX_LOCK_ORDER_UNKNOWN 0xFFFF
83
84#define FX_LOCK_ORDER_PACKAGE_PDO 0x1000
85#define FX_LOCK_ORDER_PACKAGE_FDO 0x1000
86#define FX_LOCK_ORDER_WMI_IRP_HANDLER 0x1000
87#define FX_LOCK_ORDER_PACKAGE_GENERAL 0x1000
88
89#define FX_LOCK_ORDER_IO_TARGET 0x1000
90
91#define FX_LOCK_ORDER_WMI_PROVIDER 0x1001
92#define FX_LOCK_ORDER_WMI_INSTANCE 0x1002
93
94#define FX_LOCK_ORDER_DMA_ENABLER 0x1000
95#define FX_LOCK_ORDER_DMA_TRANSACTION 0x1001
96#define FX_LOCK_ORDER_COMMON_BUFFER 0x1001
97
98//
99// A USB device owns a bunch of pipes, so make sure that device can acquire a
100// pipe lock while locked, but not vice versa
101//
102#define FX_LOCK_ORDER_USB_DEVICE_IO_TARGET 0x1000
103#define FX_LOCK_ORDER_USB_PIPE_IO_TARGET 0x1001
104
105
106#define FX_LOCK_ORDER_DRIVER 0x1010
107#define FX_LOCK_ORDER_DEVICE 0x1020
108#define FX_LOCK_ORDER_MP_DEVICE 0x1020
109#define FX_LOCK_ORDER_DEFAULT_IRP_HANDLER 0x1030
110#define FX_LOCK_ORDER_QUEUE 0x1030
111#define FX_LOCK_ORDER_PACKAGE_IO 0x1031
112#define FX_LOCK_ORDER_REQUEST 0x1040
113#define FX_LOCK_ORDER_IRPQUEUE 0x1051
114#define FX_LOCK_ORDER_TIMER 0x1059
115#define FX_LOCK_ORDER_DPC 0x1060
116#define FX_LOCK_ORDER_WORKITEM 0x1060
117#define FX_LOCK_ORDER_CLEANUPLIST 0x1060
118#define FX_LOCK_ORDER_INTERRUPT 0x1060
119#define FX_LOCK_ORDER_FILEOBJECT 0x1060
120#define FX_LOCK_ORDER_DEVICE_LIST 0x1061
121#define FX_LOCK_ORDER_COLLECTION 0x1070 // collection can be used in any
122 // of the above object's callbacks
123#define FX_LOCK_ORDER_USEROBJECT 0x2000
124
125// dispose list is very far down in the list because pretty much any item can
126// be added to the dispose list while that object's lock is being held
127#define FX_LOCK_ORDER_DISPOSELIST 0x8000
128
129#define FX_LOCK_ORDER_SYSTEMWORKITEM FX_LOCK_ORDER_UNKNOWN
130#define FX_LOCK_ORDER_SYSTEMTHREAD FX_LOCK_ORDER_UNKNOWN // No lock level
131
132//
133// These are the device driver callback locks
134// used to synchronize callback to the device
135// driver. They are "higher" than the internal
136// frameworks locks since an internal frameworks lock
137// should not be held when these are acquired.
138//
139// (which should only be due to FxCallback.Invoke to a driver
140// event handler)
141//
142// This means they must have a lower number than the internal frameworks
143// locks.
144//
145// They may be held when a device driver is calling into a frameworks
146// DDI while in an event callback handler.
147//
148// These levels enforce not only the level of locks acquired
149// and released by and for the driver, but also the rules
150// about holding internal frameworks locks when calling into
151// a driver. If a frameworks bug is holding a frameworks lock
152// when it goes to do a callback, the attempt to acquire the
153// lower numbered lock will raise the error.
154//
155#define FX_CALLBACKLOCK_ORDER_DRIVER 0x10
156#define FX_CALLBACKLOCK_ORDER_DEVICE 0x20
157#define FX_CALLBACKLOCK_ORDER_PACKAGE 0x30
158#define FX_CALLBACKLOCK_ORDER_QUEUE 0x31
159
160#define FX_VERIFIER_LOCK_ENTRY(FX_OBJECT_TYPE, FX_LOCK_ORDER) { FX_OBJECT_TYPE, FX_LOCK_ORDER }
161
162// Internal FxLock spinlock entries
163#define FX_VERIFIER_LOCK_ENTRIES() \
164 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_DRIVER, FX_LOCK_ORDER_DRIVER), \
165 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_DEVICE, FX_LOCK_ORDER_DEVICE), \
166 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_MP_DEVICE, FX_LOCK_ORDER_MP_DEVICE), \
167 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_PACKAGE_IO, FX_LOCK_ORDER_PACKAGE_IO), \
168 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_WMI_INSTANCE, FX_LOCK_ORDER_WMI_INSTANCE), \
169 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_WMI_PROVIDER, FX_LOCK_ORDER_WMI_PROVIDER), \
170 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_QUEUE, FX_LOCK_ORDER_QUEUE), \
171 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_REQUEST, FX_LOCK_ORDER_REQUEST), \
172 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_IRPQUEUE, FX_LOCK_ORDER_IRPQUEUE), \
173 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_PACKAGE_PDO, FX_LOCK_ORDER_PACKAGE_PDO), \
174 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_PACKAGE_FDO, FX_LOCK_ORDER_PACKAGE_FDO), \
175 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_WMI_IRP_HANDLER, FX_LOCK_ORDER_WMI_IRP_HANDLER), \
176 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_PACKAGE_GENERAL, FX_LOCK_ORDER_PACKAGE_GENERAL), \
177 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_DMA_ENABLER, FX_LOCK_ORDER_DMA_ENABLER), \
178 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_DMA_TRANSACTION, FX_LOCK_ORDER_DMA_TRANSACTION), \
179 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_COMMON_BUFFER, FX_LOCK_ORDER_COMMON_BUFFER), \
180 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_IO_TARGET, FX_LOCK_ORDER_IO_TARGET), \
181 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_IO_TARGET_SELF, FX_LOCK_ORDER_IO_TARGET), \
182 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_IO_TARGET_USB_DEVICE,FX_LOCK_ORDER_USB_DEVICE_IO_TARGET),\
183 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_IO_TARGET_USB_PIPE, FX_LOCK_ORDER_USB_PIPE_IO_TARGET), \
184 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_DPC, FX_LOCK_ORDER_DPC), \
185 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_WORKITEM, FX_LOCK_ORDER_WORKITEM), \
186 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_SYSTEMTHREAD, FX_LOCK_ORDER_SYSTEMTHREAD), \
187 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_CLEANUPLIST, FX_LOCK_ORDER_CLEANUPLIST), \
188 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_INTERRUPT, FX_LOCK_ORDER_INTERRUPT), \
189 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_TIMER, FX_LOCK_ORDER_TIMER), \
190 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_FILEOBJECT, FX_LOCK_ORDER_FILEOBJECT), \
191 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_CHILD_LIST, FX_LOCK_ORDER_DEVICE_LIST), \
192 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_SYSTEMWORKITEM, FX_LOCK_ORDER_SYSTEMWORKITEM), \
193 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_DEFAULT_IRP_HANDLER, FX_LOCK_ORDER_DEFAULT_IRP_HANDLER), \
194 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_COLLECTION, FX_LOCK_ORDER_COLLECTION), \
195 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_DISPOSELIST, FX_LOCK_ORDER_DISPOSELIST), \
196 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_USEROBJECT, FX_LOCK_ORDER_USEROBJECT), \
197 FX_VERIFIER_LOCK_ENTRY(0, 0)
198
199// Device Driver Callback lock entries
200#define FX_VERIFIER_CALLBACKLOCK_ENTRIES() \
201 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_DRIVER, FX_CALLBACKLOCK_ORDER_DRIVER), \
202 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_DEVICE, FX_CALLBACKLOCK_ORDER_DEVICE), \
203 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_PACKAGE_IO, FX_CALLBACKLOCK_ORDER_PACKAGE), \
204 FX_VERIFIER_LOCK_ENTRY(FX_TYPE_QUEUE, FX_CALLBACKLOCK_ORDER_QUEUE), \
205 FX_VERIFIER_LOCK_ENTRY(0, 0)
206
207//
208// Mapping table structure between Fx object types and lock orders
209//
213};
214
216//
217// This must be a power of two for hash algorithm
218//
219// Table size is dependent on the number of active threads
220// in the frameworks at a given time. This can not execeed
221// the number of (virtual due to hyperthreading) CPU's in the system.
222//
223// Setting this number lower just increases collisions, but does
224// not impede correct function.
225//
226#define VERIFIER_THREAD_HASHTABLE_SIZE 64
227
228
229//
230// This structure is used by verifier hash table implementation
231// for linking records per thread
232//
238};
239
241/*
242 * This lock performs the same actions as the base
243 * FxLock, but provides additional tracking of lock
244 * order to help detect and debug
245 * deadlock and recursive lock situations.
246 *
247 * It does not inherit from FxLock since this would
248 * cause a recursion chain.
249 *
250 * Since lock verification is already more costly than
251 * basic lock use, this verifier lock supports both the
252 * FAST_MUTEX and SpinLock modes in order to utilize common
253 * code to support verification of FxCallback locks.
254 *
255 * FxVerifierLocks are only allocated when WdfVerifierLock
256 * is turned on.
257 */
258
260
261private:
262 // Standard NT pool object identification
265
266 // Spinlock to perform our lock functionality
269
270 // Fast Mutex for thread level verifier locks
272
273 //
274 // Verifier per lock working values, protected
275 // by our m_Lock
276 //
280
281 // True if its a Mutex based (thread context) lock
283
284 // True if its used as a Callback lock
286
287 //
288 // This is the link for the per thread lock chain.
289 //
291
292private:
294 PFX_DRIVER_GLOBALS FxDriverGlobals
295 ) :
296 FxGlobalsStump(FxDriverGlobals)
297 {
298 }
299
300 void
302 VOID
303 );
304
305 void
308 __in PVOID curThread,
309 __in FxVerifierLock* PerThreadList
310 );
311
312private:
313 //
314 // This constructor is used by internal object
315 // locks, which always use a spinlock.
316 //
318 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
319 __in FxObject* ParentObject
320 ) :
321 FxGlobalsStump(FxDriverGlobals)
322 {
324 m_Size = sizeof(FxVerifierLock);
325
326 m_ParentObject = ParentObject;
327
331
335
338
340 }
341
343 __inline
346 )
347 {
349
350 if (m_UseMutex) {
352
353 if (!NT_SUCCESS(status)) {
355 "Unable to initialize paged lock for VerifierLock 0x%p "
356 "status %!STATUS!",
357 this, status);
358 return status;
359 }
360 }
361
362 return STATUS_SUCCESS;
363 }
364
365 //
366 // This constructor is used by the Callback lock
367 // functions when verifer is on.
368 //
369 // The lock utlizes the callback lock order table entries to
370 // set its level.
371 //
373 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
374 __in FxObject* ParentObject,
375 __in BOOLEAN UseMutex
376 ) :
377 FxGlobalsStump(FxDriverGlobals)
378 {
379
381 m_Size = sizeof(FxVerifierLock);
382
383 m_ParentObject = ParentObject;
384
388
392
393 // Different verifier table
395
396 if (UseMutex) {
398 }
399 else {
401 }
402
404 }
405
406public:
407
409 __inline
410 static
413 __out FxVerifierLock ** VerifierLock,
414 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
415 __in FxObject* ParentObject,
416 __in BOOLEAN UseMutex
417 )
418 {
420 FxVerifierLock * verifierLock;
421
422 verifierLock = new (FxDriverGlobals) FxVerifierLock(FxDriverGlobals,
423 ParentObject,
424 UseMutex);
425 if (NULL == verifierLock) {
428 "Failed to allocate verifier lock, returning %!STATUS!",
429 status);
430 goto exit;
431 }
432
433 status = verifierLock->Initialize();
434 if (!NT_SUCCESS(status)) {
435 delete verifierLock;
436 goto exit;
437 }
438
439 *VerifierLock = verifierLock;
440
441 exit:
442 return status;
443 }
444
446 __inline
447 static
450 __out FxVerifierLock ** VerifierLock,
451 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
452 __in FxObject* ParentObject
453 )
454 {
456 FxVerifierLock * verifierLock;
457
458 verifierLock = new (FxDriverGlobals) FxVerifierLock(FxDriverGlobals,
459 ParentObject);
460 if (NULL == verifierLock) {
463 "Failed to allocate verifier lock, returning %!STATUS!",
464 status);
465 goto exit;
466 }
467
468 status = verifierLock->Initialize();
469 if (!NT_SUCCESS(status)) {
470 delete verifierLock;
471 goto exit;
472 }
473
474 *VerifierLock = verifierLock;
475
476 exit:
477 return status;
478 }
479
481 VOID
482 )
483 {
484 if (m_OwningThread != NULL) {
486 "Lock 0x%p is being destroyed while owned by "
487 "thread 0x%p, Owning Object 0x%p",
490 }
491 }
492
493 VOID
494 Lock(
495 __out PKIRQL PreviousIrql,
496 __in BOOLEAN AtDpc
497 );
498
499 VOID
500 Unlock(
501 __in KIRQL PreviousIrql,
502 __in BOOLEAN AtDpc
503 );
504
505 KIRQL
507 VOID
508 );
509
510 //
511 // Instance data needed for the hash table chaining
512 //
514
515 //
516 // Static data and methods for hash table chaining
517 //
519
521
523
524 static
525 void
527 __in PFX_DRIVER_GLOBALS FxDriverGlobals
528 );
529
530 static
531 void
533 __in PFX_DRIVER_GLOBALS FxDriverGlobals
534 );
535
536 static
537 void
540 __in MxThread curThread,
541 __in FxVerifierLock* PerThreadList
542 );
543
544 static
547 __in MxThread curThread,
549 __in BOOLEAN LookupOnly
550 );
551
552 static
553 void
555 __in MxThread curThread,
557 );
558};
559
560#endif // _FXVERIFIERLOCK_HPP_
561
562
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
FxVerifierLock(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in FxObject *ParentObject)
static ULONG ThreadTableSize
FxVerifierThreadTableEntry m_ThreadTableEntry
_Must_inspect_result_ __inline NTSTATUS Initialize()
FxVerifierLock(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in FxObject *ParentObject, __in BOOLEAN UseMutex)
void FxVerifierLockDumpDetails(__in FxVerifierLock *Lock, __in PVOID curThread, __in FxVerifierLock *PerThreadList)
FxVerifierLock(PFX_DRIVER_GLOBALS FxDriverGlobals)
static void FreeThreadTable(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
MxPagedLock m_Mutex
KIRQL GetLockPreviousIrql(VOID)
FxVerifierLock * m_OwnedLink
MxThread m_OwningThread
static void ReleaseOrReplaceThreadTableEntry(__in MxThread curThread, __in FxVerifierLock *pLock)
static void AllocateThreadTable(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
static void DumpDetails(__in FxVerifierLock *Lock, __in MxThread curThread, __in FxVerifierLock *PerThreadList)
static pFxVerifierThreadTableEntry GetThreadTableEntry(__in MxThread curThread, __in FxVerifierLock *pLock, __in BOOLEAN LookupOnly)
_Must_inspect_result_ static __inline NTSTATUS CreateAndInitialize(__out FxVerifierLock **VerifierLock, __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in FxObject *ParentObject)
FxObject * m_ParentObject
static KSPIN_LOCK ThreadTableLock
static PLIST_ENTRY ThreadTable
void InitializeLockOrder(VOID)
_Must_inspect_result_ static __inline NTSTATUS CreateAndInitialize(__out FxVerifierLock **VerifierLock, __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in FxObject *ParentObject, __in BOOLEAN UseMutex)
Definition: mxlock.h:102
_Must_inspect_result_ __inline NTSTATUS Initialize()
Definition: mxpagedlockkm.h:52
#define __in
Definition: dbghelp.h:35
#define __out
Definition: dbghelp.h:62
#define TRACINGDEVICE
Definition: dbgtrace.h:58
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
KIRQL * PKIRQL
Definition: env_spec_w32.h:592
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
FxVerifierDbgBreakPoint(pFxDriverGlobals)
FxSpinLock * pLock
@ FX_TYPE_VERIFIERLOCK
Definition: fxtypes.h:65
#define FX_LOCK_ORDER_UNKNOWN
struct FxVerifierOrderMapping * pFxVerifierOrderMapping
struct FxVerifierThreadTableEntry * pFxVerifierThreadTableEntry
#define _Must_inspect_result_
Definition: ms_sal.h:558
@ Unlock
Definition: ntsecapi.h:294
unsigned short USHORT
Definition: pedump.c:61
#define exit(n)
Definition: config.h:202
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxstump.hpp:98
FxVerifierLock * PerThreadDispatchLockList
FxVerifierLock * PerThreadPassiveLockList
Definition: typedefs.h:120
Definition: ps.c:97
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:127