ReactOS  0.4.15-dev-3324-gda4e15f
fxverifierlock.hpp
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7  FxVerifierLock.hpp
8 
9 Abstract:
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 
16 Author:
17 
18 
19 
20 Revision 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 
35 extern "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 
261 private:
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 
292 private:
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 
312 private:
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 
329  m_OwnedLink = NULL;
331 
335 
336  m_UseMutex = FALSE;
338 
340  }
341 
343  __inline
344  NTSTATUS
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 
386  m_OwnedLink = NULL;
388 
392 
393  // Different verifier table
395 
396  if (UseMutex) {
397  m_UseMutex = TRUE;
398  }
399  else {
400  m_UseMutex = FALSE;
401  }
402 
404  }
405 
406 public:
407 
409  __inline
410  static
411  NTSTATUS
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
448  NTSTATUS
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
538  DumpDetails(
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 
void FxVerifierLockDumpDetails(__in FxVerifierLock *Lock, __in PVOID curThread, __in FxVerifierLock *PerThreadList)
_Must_inspect_result_ __inline NTSTATUS Initialize()
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
static ULONG ThreadTableSize
MxPagedLock m_Mutex
#define TRUE
Definition: types.h:120
static pFxVerifierThreadTableEntry GetThreadTableEntry(__in MxThread curThread, __in FxVerifierLock *pLock, __in BOOLEAN LookupOnly)
struct FxVerifierThreadTableEntry * pFxVerifierThreadTableEntry
LONG NTSTATUS
Definition: precomp.h:26
static void FreeThreadTable(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
_Must_inspect_result_ static __inline NTSTATUS CreateAndInitialize(__out FxVerifierLock **VerifierLock, __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in FxObject *ParentObject)
VOID Unlock(__in KIRQL PreviousIrql, __in BOOLEAN AtDpc)
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define FALSE
Definition: types.h:117
VOID Lock(__out PKIRQL PreviousIrql, __in BOOLEAN AtDpc)
#define __out
Definition: dbghelp.h:62
KIRQL GetLockPreviousIrql(VOID)
unsigned char BOOLEAN
FxVerifierLock * m_OwnedLink
FxObject * m_ParentObject
FxVerifierThreadTableEntry m_ThreadTableEntry
MxThread m_OwningThread
#define TRACINGDEVICE
Definition: dbgtrace.h:58
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static void AllocateThreadTable(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
struct FxVerifierOrderMapping * pFxVerifierOrderMapping
#define FX_LOCK_ORDER_UNKNOWN
static PLIST_ENTRY ThreadTable
_Must_inspect_result_ __inline NTSTATUS Initialize()
Definition: mxpagedlockkm.h:52
FxSpinLock * pLock
KIRQL * PKIRQL
Definition: env_spec_w32.h:592
Definition: typedefs.h:119
FxVerifierLock(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in FxObject *ParentObject)
#define _Must_inspect_result_
Definition: ms_sal.h:558
Definition: mxlock.h:101
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
static void DumpDetails(__in FxVerifierLock *Lock, __in MxThread curThread, __in FxVerifierLock *PerThreadList)
FxVerifierLock * PerThreadDispatchLockList
unsigned short USHORT
Definition: pedump.c:61
FxVerifierLock(PFX_DRIVER_GLOBALS FxDriverGlobals)
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
void InitializeLockOrder(VOID)
#define NULL
Definition: types.h:112
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:124
static void ReleaseOrReplaceThreadTableEntry(__in MxThread curThread, __in FxVerifierLock *pLock)
unsigned int ULONG
Definition: retypes.h:1
FxVerifierLock * PerThreadPassiveLockList
#define STATUS_SUCCESS
Definition: shellext.h:65
static KSPIN_LOCK ThreadTableLock
void exit(int exitcode)
Definition: _exit.c:33
_Must_inspect_result_ static __inline NTSTATUS CreateAndInitialize(__out FxVerifierLock **VerifierLock, __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in FxObject *ParentObject, __in BOOLEAN UseMutex)
#define __in
Definition: dbghelp.h:35
static SERVICE_STATUS status
Definition: service.c:31
PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxstump.hpp:98
FxVerifierDbgBreakPoint(pFxDriverGlobals)
FxVerifierLock(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in FxObject *ParentObject, __in BOOLEAN UseMutex)
Definition: ps.c:97