ReactOS  0.4.15-dev-2720-g5ee0925
fxverifierlock.cpp
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7  FxVerifierLock.cpp
8 
9 Abstract:
10 
11  This module contains the implementation of the verifier lock
12 
13 Author:
14 
15 
16 
17 
18 Environment:
19 
20  Both kernel and user mode
21 
22 Revision History:
23 
24 
25 
26 
27 --*/
28 
29 #include "fxobjectpch.hpp"
30 
31 extern "C" {
32 #if defined(EVENT_TRACING)
33 #include "FxVerifierLock.tmh"
34 #endif
35 }
36 
37 //
38 // Mapping table structure between Fx object types and lock orders
39 //
41 
42  // Table is defined in fx\inc\FxVerifierLock.hpp
44 };
45 
47 
48  // Table is defined in fx\inc\FxVerifierLock.hpp
50 };
51 
52 //
53 // Organization of verifier lock structures
54 //
55 // As locks are acquired, they are added to the head of a list of locks held
56 // by the current thread if equal, or higher than the lock
57 // at the current list head.
58 //
59 // The hierachy of locks acquired by a thread is seperate for dispatch level
60 // (spinlock) and passive level (mutex) locks. These locks can not be mixed
61 // since holding a mutex lock does not prevent a DPC from interrupting the
62 // thread and properly acquiring a spinlock, which could appear to be
63 // of an improper level, giving a false report.
64 //
65 // In order to prevent memory allocations (which can fail) when locks are
66 // acquired, each FxVerifierLock structure contains members required to chain
67 // locks that are held on a per thread basis. (m_OwnedLink)
68 //
69 // Since we have no way of knowing the number of unique PETHREADS that may
70 // be holding locks at any time, a fixed size hash table is allocated
71 // and PETHREAD values are hashed into it, with chaining allowed on
72 // each entry due to overflows and collisions. The storage required for
73 // the hash table entry and chain is also allocated as member fields
74 // of the FxVerifierLock class. (m_ThreadTableEntry)
75 //
76 // The hash table and its chained entries (m_ThreadTableEntry) is protected
77 // by a global spinlock, FxDriverGlobals->ThreadTableLock.
78 //
79 // When a lock is acquired, the current threads address is used to look up
80 // a FxVerifierThreadTableEntry for it in the hash table.
81 //
82 // If one does not exist, this is the start of a new chain of locks for this
83 // ETHREAD, and the m_ThreadTableEntry of the current lock being acquired
84 // is inserted into the hash table, and the new lock chain is started using
85 // either the
86 // FxVerifierThreadTableEntry::PerThreadPassiveLockList, or
87 // FxVerifierThreadTableEntry::PerThreadDispatchLockList.
88 //
89 // If an entry does exist, the current lock is added to the head of
90 // the list in the existing entry.
91 //
92 // On lock release, the lock is identified in the list of held locks,
93 // which may not be the head if release was out of order (this is allowed),
94 // and removed from the list.
95 //
96 // If the list of locks held by the current thread is NULL for both
97 // the passive and dispatch lists, the threads entry is removed from
98 // the hash table since the thread no longer holds any locks.
99 //
100 // If either of these lists is not NULL, then the entries in the
101 // current locks FxVerifierThreadTableEntry is copied into one
102 // of the other locks on the new list head and the hash table
103 // is updated to point to the new entry.
104 //
105 // This is because the released FxVerifierLock entry may be freed
106 // as a result of its containing data structure being run down.
107 //
108 
109 //
110 // Method Definitions
111 //
112 
113 //
114 // Called at Driver Frameworks init time
115 //
116 extern "C"
117 void
119  __in PFX_DRIVER_GLOBALS FxDriverGlobals
120  )
121 {
122  if( FxDriverGlobals->FxVerifierLock ) {
123 
124  FxDriverGlobals->ThreadTableLock.Initialize();
125 
126  FxVerifierLock::AllocateThreadTable(FxDriverGlobals);
127  }
128 
129  return;
130 }
131 
132 //
133 // Called at Driver Frameworks is unloading
134 //
135 extern "C"
136 void
138  __in PFX_DRIVER_GLOBALS FxDriverGlobals
139  )
140 {
141  if( FxDriverGlobals->FxVerifierLock ) {
142  FxVerifierLock::FreeThreadTable(FxDriverGlobals);
143 
144  FxDriverGlobals->ThreadTableLock.Uninitialize();
145  }
146 
147  return;
148 }
149 
150 VOID
152  __out PKIRQL PreviousIrql,
153  __in BOOLEAN AtDpc
154  )
155 {
156  MxThread curThread;
158  pFxVerifierThreadTableEntry perThreadList;
159  KIRQL oldIrql = PASSIVE_LEVEL;
160 
161  PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
162 
163  curThread = Mx::MxGetCurrentThread();
164 
165  //
166  // First check to see if the lock is already
167  // owned.
168  //
169  // This check is race free since this can only be set
170  // to our thread from under the spinlock, and is cleared
171  // before release.
172  //
173 
174  if( m_OwningThread == curThread ) {
175 
177  FxDriverGlobals, TRACE_LEVEL_FATAL, TRACINGDEVICE,
178  "Thread 0x%p already owns lock 0x%p for object 0x%p, WDFOBJECT 0x%p",
179  curThread, this, m_ParentObject, m_ParentObject->GetObjectHandle());
180 
181  FxVerifierBugCheck( FxDriverGlobals,
184  (ULONG_PTR) this);
185  }
186 
187  if( m_UseMutex ) {
188  // Get the Mutex
189  Mx::MxEnterCriticalRegion();
191 
192  *PreviousIrql = Mx::MxGetCurrentIrql();
193  }
194  else if (AtDpc) {
195  // Get the spinlock
196  m_Lock.AcquireAtDpcLevel();
198 
199  *PreviousIrql = m_OldIrql;
200  }
201  else {
202  // Try to force a thread switch to catch synchronization errors
204  LARGE_INTEGER sleepTime;
205 
206  sleepTime.QuadPart = 0;
208  }
209 
210  // Get the spinlock using a local since KeAcquireSpinLock might use this
211  // var as temp space while spinning and we would then corrupt it if
212  // the owning thread used it in the middle of the spin.
213  //
214  m_Lock.Acquire(PreviousIrql);
215  m_OldIrql = *PreviousIrql;
216  }
217 
218  // Lock the verifier lists
219  if (m_UseMutex) {
220  FxDriverGlobals->ThreadTableLock.Acquire(&oldIrql);
221  }
222  else {
223  FxDriverGlobals->ThreadTableLock.AcquireAtDpcLevel();
224  }
225 
226  m_OwningThread = curThread;
227 
228  // Get our per thread list from the thread table
229  perThreadList = FxVerifierLock::GetThreadTableEntry(curThread, this, FALSE);
230  if( perThreadList == NULL ) {
231 
232  if (m_UseMutex) {
233  FxDriverGlobals->ThreadTableLock.Release(oldIrql);
234  }
235  else {
236  FxDriverGlobals->ThreadTableLock.ReleaseFromDpcLevel();
237  }
238 
239  // Can't get an entry, so return
240  return;
241  }
242 
243  //
244  // There are seperately sorted lists for passive and dispatch
245  // level locks since dispatch level locks of a lower level can interrupt a
246  // higher passive level lock, giving a false report.
247  //
248  if( m_UseMutex ) {
249  head = perThreadList->PerThreadPassiveLockList;
250  }
251  else {
252  head = perThreadList->PerThreadDispatchLockList;
253  }
254 
255  if( head != NULL ) {
256 
257  // Validate current is > head
258  if( m_Order > head->m_Order ) {
259  m_OwnedLink = head;
260  //perThreadList->PerThreadLockList = this;
261  }
262  else if( m_Order == head->m_Order ) {
263 
264  // Place at head if the same lock level as current head
265  m_OwnedLink = head;
266  //perThreadList->PerThreadLockList = this;
267  }
268  else {
269 
270  // Lock violation, m_Order < head->m_Order
271  FxVerifierLock::DumpDetails(this, curThread, head);
272 
273  //
274  // Caller is feeling lucky and resumed so place it at the head
275  // to keep our lists intact
276  //
277  m_OwnedLink = head;
278  //perThreadList->PerThreadLockList = this;
279  }
280  }
281  else {
282  this->m_OwnedLink = NULL;
283  //perThreadList->PerThreadLockList = this;
284  }
285 
286  //
287  // Update to the next list head
288  //
289  if (m_UseMutex) {
290  perThreadList->PerThreadPassiveLockList = this;
291  FxDriverGlobals->ThreadTableLock.Release(oldIrql);
292  }
293  else {
294  perThreadList->PerThreadDispatchLockList = this;
295  FxDriverGlobals->ThreadTableLock.ReleaseFromDpcLevel();
296  }
297 
298  return;
299 }
300 
301 void
303  __in KIRQL PreviousIrql,
304  __in BOOLEAN AtDpc
305  )
306 {
307  MxThread curThread;
308  pFxVerifierThreadTableEntry perThreadList;
309  KIRQL oldIrql;
310 
311  PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
312 
313  // Only from DISPATCH_LEVEL or below
314  curThread = Mx::MxGetCurrentThread();
315 
316  if( curThread != m_OwningThread ) {
318  "Thread 0x%p Is Attempting to release a Lock 0x%p "
319  "for Object 0x%p it does not own!",
320  curThread,this,m_ParentObject);
321  FxVerifierDbgBreakPoint(FxDriverGlobals);
322  return;
323  }
324 
325  // Lock the verifier lists
326  FxDriverGlobals->ThreadTableLock.Acquire(&oldIrql);
327 
328  // Get our per thread list from the thread table
330  if( perThreadList == NULL ) {
331 
332  // Can't get our entry, so release the spinlock and return
334  "Unlock: Can't get per thread entry for thread %p",
335  curThread);
336 
338 
339  FxDriverGlobals->ThreadTableLock.Release(oldIrql);
340 
341  if (m_UseMutex) {
343  Mx::MxLeaveCriticalRegion();
344  }
345  else if (AtDpc) {
346  m_Lock.ReleaseFromDpcLevel();
347  }
348  else {
349  m_Lock.Release(PreviousIrql);
350 
351  // Try to force a thread switch to catch synchronization errors
353  LARGE_INTEGER sleepTime;
354 
355  sleepTime.QuadPart = 0;
357  }
358  }
359  return;
360  }
361 
362  if( m_UseMutex ) {
363  if( perThreadList->PerThreadPassiveLockList == NULL ) {
364  // Problem with verifier
366  "Thread has entry, but no locks recorded as "
367  "held for passive!");
369  "this 0x%p, perThreadList 0x%p",
370  this, perThreadList);
371  FxVerifierDbgBreakPoint(FxDriverGlobals);
372 
374 
375  FxDriverGlobals->ThreadTableLock.Release(oldIrql);
376 
378  Mx::MxLeaveCriticalRegion();
379 
380  return;
381  }
382  }
383  else {
384  if( perThreadList->PerThreadDispatchLockList == NULL ) {
385  // Problem with verifier
387  "Thread has entry, but no locks recorded as held "
388  "for dispatch!");
390  "this 0x%p, perThreadList 0x%p",
391  this, perThreadList);
392  FxVerifierDbgBreakPoint(FxDriverGlobals);
393 
395 
396  FxDriverGlobals->ThreadTableLock.Release(oldIrql);
397 
398  if (AtDpc) {
399  m_Lock.ReleaseFromDpcLevel();
400  }
401  else {
402  m_Lock.Release(PreviousIrql);
403 
404  // Try to force a thread switch to catch synchronization errors
406  LARGE_INTEGER sleepTime;
407 
408  sleepTime.QuadPart = 0;
410  }
411  }
412 
413  return;
414  }
415  }
416 
417  if( m_UseMutex ) {
418 
419  // Common case is a nested release
420  if( perThreadList->PerThreadPassiveLockList == this ) {
421 
422  perThreadList->PerThreadPassiveLockList = this->m_OwnedLink;
423  m_OwnedLink = NULL;
424 
425  ReleaseOrReplaceThreadTableEntry(curThread, this);
426 
427 
428 
429 
430 
431 
432 
433 
434 
435 
436 
437 
438 
439 
440 
441 
442 
443 
444 
445 
446 
447 
448  }
449  else {
450  //
451  // Releasing out of order does not deadlock as
452  // long as all acquires are in order, but its
453  // not commmon
454  //
456  FxVerifierLock* prev = NULL;
457 
458  // Skip the first entry checked by the above if
459  prev = perThreadList->PerThreadPassiveLockList;
460  next = perThreadList->PerThreadPassiveLockList->m_OwnedLink;
461 
462  while( next != NULL ) {
463 
464  if( next == this ) {
465  prev->m_OwnedLink = m_OwnedLink;
466  m_OwnedLink = NULL;
467 
468  //
469  // The perThreadList entry may, or may not be the
470  // data structure in this lock. Sinse we are releasing
471  // the lock, this entry can no longer be referenced if
472  // so.
473  //
474  ReleaseOrReplaceThreadTableEntry(curThread, this);
475 
476 // FxVerifierLock::ReplaceThreadTableEntry(curThread, this, perThreadList->PerThreadPassiveLockList);
477 
478  break;
479  }
480 
481  prev = next;
482  next = next->m_OwnedLink;
483  }
484 
485  if( next == NULL ) {
486  // Somehow the entry is gone
488  "Record entry for VerifierLock 0x%p is missing "
489  "on list 0x%p for Thread 0x%p",
490  this,perThreadList,m_OwningThread);
491  FxVerifierDbgBreakPoint(FxDriverGlobals);
492  }
493  }
494  }
495  else {
496 
497  // Common case is a nested release
498  if( perThreadList->PerThreadDispatchLockList == this ) {
499 
500  perThreadList->PerThreadDispatchLockList = this->m_OwnedLink;
501  m_OwnedLink = NULL;
502 
503  ReleaseOrReplaceThreadTableEntry(curThread, this);
504 
505 
506 
507 
508 
509 
510 
511 
512 
513 
514 
515 
516 
517 
518 
519 
520 
521 
522 
523 
524 
525 
526  }
527  else {
528  //
529  // Releasing out of order does not deadlock as
530  // long as all acquires are in order, but its
531  // not commmon
532  //
534  FxVerifierLock* prev = NULL;
535 
536  // Skip the first entry checked by the above if
537  prev = perThreadList->PerThreadDispatchLockList;
538  next = perThreadList->PerThreadDispatchLockList->m_OwnedLink;
539 
540  while( next != NULL ) {
541 
542  if( next == this ) {
543  prev->m_OwnedLink = m_OwnedLink;
544  m_OwnedLink = NULL;
545 
546  //
547  // The perThreadList entry may, or may not be the
548  // data structure in this lock. Sinse we are releasing
549  // the lock, this entry can no longer be referenced if
550  // so.
551  //
552  ReleaseOrReplaceThreadTableEntry(curThread, this);
553 
554 // FxVerifierLock::ReplaceThreadTableEntry(curThread, this, perThreadList->PerThreadDispatchLockList);
555 
556  break;
557  }
558 
559  prev = next;
560  next = next->m_OwnedLink;
561  }
562 
563  if( next == NULL ) {
564  // Somehow the entry is gone
566  "Record entry for VerifierLock 0x%p is missing "
567  "on list 0x%p for Thread 0x%p",
568  this,perThreadList,m_OwningThread);
569  FxVerifierDbgBreakPoint(FxDriverGlobals);
570  }
571  }
572 
573  }
574 
576 
577  FxDriverGlobals->ThreadTableLock.Release(oldIrql);
578 
579  if (m_UseMutex) {
581  Mx::MxLeaveCriticalRegion();
582  }
583  else if (AtDpc) {
584  m_Lock.ReleaseFromDpcLevel();
585  }
586  else {
587  m_Lock.Release(PreviousIrql);
588 
589  // Try to force a thread switch to catch synchronization errors
591  LARGE_INTEGER sleepTime;
592 
593  sleepTime.QuadPart = 0;
595  }
596  }
597 
598  return;
599 }
600 
601 KIRQL
603 {
604  return m_OldIrql;
605 }
606 
607 void
609 {
612 
613  PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
614 
616 
617  if( m_CallbackLock ) {
619  }
620  else {
622  }
623 
624  while( p->ObjectType != 0 ) {
625 
626  if( p->ObjectType == ObjectType ) {
627  m_Order = p->ObjectLockOrder;
628  return;
629  }
630 
631  p++;
632  }
633 
635  "Object Type 0x%x does not have a lock order "
636  "defined in fx\\inc\\FxVerifierLock.hpp",
637  ObjectType);
638 
640 
641  return;
642 }
643 
644 //
645 // This looks up the supplied thread in the table, and if
646 // found returns it.
647 //
648 // If no entry for the thread is found, create one using the
649 // m_ThreadTableEntry for the lock.
650 //
653  __in MxThread curThread,
655  __in BOOLEAN LookupOnly
656  )
657 {
658  ULONG Hash, Index;
661 
662  PFX_DRIVER_GLOBALS FxDriverGlobals = pLock->GetDriverGlobals();
663 
664  // Verifier is off, or an early memory allocation failure
665  if( FxDriverGlobals->ThreadTable == NULL ) {
666  return NULL;
667  }
668 
669  //
670  // Hash the KeCurrentThread() information into an table
671  // index.
672  //
673  // Hash takes into account that NT pool items don't use
674  // the lower 4 bits (16 byte boundries)
675  //
676 
677  Hash = (ULONG)((ULONG_PTR)curThread >> 4);
678  Hash = ((Hash >> 16) & 0x0000FFFF) ^ (Hash & 0x0000FFFF);
679 
680  //
681  // Hash table is maintained as a power of two
682  //
684 
685  head = &FxDriverGlobals->ThreadTable[Index];
686 
687  //
688  // Walk the list to see if our thread has an entry
689  //
690  next = head->Flink;
691  while( next != head ) {
693 
694  if( entry->m_ThreadTableEntry.Thread == curThread ) {
695 
696  //DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
697  // "Returning existing Entry 0x%p for Thread 0x%p, "
698  // "Lock 0x%p",
699  // &entry->m_ThreadTableEntry, curThread, pLock);
700 
701  return &entry->m_ThreadTableEntry;
702  }
703 
704  next = next->Flink;
705  }
706 
707  if( LookupOnly ) {
709  "Thread 0x%p does not have an entry",curThread);
710  FxVerifierDbgBreakPoint(FxDriverGlobals);
711  return NULL;
712  }
713 
714  //
715  // The current ETHREAD has no locks it currently holds, so it has
716  // no entry in the hash table.
717  //
718  // Use the supplied locks m_ThreadTableEntry to create an entry
719  // for this ETHREAD and the start of a new list of held locks.
720  //
721  pLock->m_ThreadTableEntry.Thread = curThread;
722  pLock->m_ThreadTableEntry.PerThreadPassiveLockList = NULL;
723  pLock->m_ThreadTableEntry.PerThreadDispatchLockList = NULL;
724 
725  InsertTailList(head, &pLock->m_ThreadTableEntry.HashChain);
726 
727 // DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
728 // "Returning new Entry 0x%p for Thread 0x%p, Lock 0x%p",
729 // &pLock->m_ThreadTableEntry, curThread, pLock);
730 
731  return &pLock->m_ThreadTableEntry;
732 }
733 
734 
735 
736 
737 
738 
739 
740 
741 
742 
743 
744 
745 
746 
747 
748 
749 
750 
751 
752 
753 
754 
755 
756 
757 
758 
759 
760 
761 
762 
763 
764 
765 
766 
767 
768 
769 
770 
771 
772 
773 
774 
775 
776 
777 
778 
779 
780 
781 
782 
783 
784 
785 
786 
787 
788 
789 
790 
791 
792 
793 
794 
795 
796 
797 
798 
799 
800 
801 
802 
803 
804 
805 
806 
807 
808 
809 
810 
811 
812 
813 
814 
815 
816 
817 
818 
819 
820 
821 
822 void
824  __in MxThread curThread,
826  )
827 
828 /*++
829 
830 Routine Description:
831 
832  Removes the use of the supplied locks m_ThreadTableEntry by
833  either releasing it if the ETHREAD is holding no more locks,
834  or by copying it to the m_ThreadTableEntry of another lock
835  held by the thread.
836 
837 Arguments:
838 
839  curThread - Thread who is holding lock
840 
841  pLock - Lock whose m_ThreadTableEntry is to be released
842 
843 Returns:
844 
845 
846 Comments:
847 
848  This is called with the verifier hash table lock held
849  FxDriverGlobals->ThreadTableLock.
850 
851  The pLock has already been removed from the held locks chain,
852  so the lock at the head of the list can be used for the new hash
853  table entry.
854 
855 --*/
856 
857 {
858  ULONG Hash, Index;
860  FxVerifierLock* pNewLock = NULL;
861 
862  PFX_DRIVER_GLOBALS FxDriverGlobals = pLock->GetDriverGlobals();
863 
864  if( pLock->m_ThreadTableEntry.Thread == NULL ) {
865 
866  // This locks entry is not used for hash chaining
867  //DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
868  // "Entry 0x%p Not currently part of the hash chain",
869  // pLock);
870 
871  return;
872  }
873 
874  // It should be the current thread
875  if( pLock->m_ThreadTableEntry.Thread != curThread ) {
877  "OldEntry Thread 0x%p not Current! 0x%p",
878  pLock,curThread);
879  FxVerifierDbgBreakPoint(FxDriverGlobals);
880  }
881 
882  Hash = (ULONG)((ULONG_PTR)curThread >> 4);
883  Hash = ((Hash >> 16) & 0x0000FFFF) ^ (Hash & 0x0000FFFF);
884 
886 
887  head = &FxDriverGlobals->ThreadTable[Index];
888 
889  // Remove old entry
890  RemoveEntryList(&pLock->m_ThreadTableEntry.HashChain);
891 
892  //
893  // If both lock lists are NULL, we can just release the entry
894  //
895  if( (pLock->m_ThreadTableEntry.PerThreadPassiveLockList == NULL) &&
896  (pLock->m_ThreadTableEntry.PerThreadDispatchLockList == NULL) ) {
897 
898  //DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
899  // "Releasing entry for lock 0x%p for Thread 0x%p",
900  // pLock, curThread);
901 
902  // This is now an unused entry
903  pLock->m_ThreadTableEntry.Thread = NULL;
904  pLock->m_ThreadTableEntry.PerThreadPassiveLockList = NULL;
905  pLock->m_ThreadTableEntry.PerThreadDispatchLockList = NULL;
906 
907  return;
908  }
909 
910  //DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
911  // "Replacing Lock 0x%p, for Thread 0x%p",
912  // pLock, curThread);
913  if( pLock->m_ThreadTableEntry.PerThreadPassiveLockList != NULL ) {
914  pNewLock = pLock->m_ThreadTableEntry.PerThreadPassiveLockList;
915  }
916  else {
917  pNewLock = pLock->m_ThreadTableEntry.PerThreadDispatchLockList;
918  }
919 
920  ASSERT(pNewLock != NULL);
921  ASSERT(pNewLock->m_ThreadTableEntry.Thread == NULL);
924 
925  // Copy the old lock structures table to the next one
926  pNewLock->m_ThreadTableEntry.Thread = pLock->m_ThreadTableEntry.Thread;
927  pNewLock->m_ThreadTableEntry.PerThreadPassiveLockList = pLock->m_ThreadTableEntry.PerThreadPassiveLockList;
928  pNewLock->m_ThreadTableEntry.PerThreadDispatchLockList = pLock->m_ThreadTableEntry.PerThreadDispatchLockList;
929 
930  // Insert new entry at the end of thelist
932 
933  return;
934 }
935 
936 void
938  __in PFX_DRIVER_GLOBALS FxDriverGlobals
939  )
940 {
941  KIRQL oldIrql;
942  ULONG newEntries;
943  PLIST_ENTRY newTable;
944 
945  FxDriverGlobals->ThreadTableLock.Acquire(&oldIrql);
946 
947  if( FxDriverGlobals->ThreadTable != NULL ) {
948  FxDriverGlobals->ThreadTableLock.Release(oldIrql);
949  return;
950  }
951 
952  // Table must be kept as a power of 2 for hash algorithm
953  newEntries = VERIFIER_THREAD_HASHTABLE_SIZE;
954 
955  newTable = (PLIST_ENTRY) FxPoolAllocateWithTag(
956  FxDriverGlobals,
957  NonPagedPool,
958  sizeof(LIST_ENTRY) * newEntries,
959  FxDriverGlobals->Tag);
960 
961  if( newTable == NULL ) {
962  FxDriverGlobals->ThreadTableLock.Release(oldIrql);
964  "No Memory to allocate thread table");
965  return;
966  }
967 
968  for(ULONG index=0; index < newEntries; index++ ) {
969  InitializeListHead(&newTable[index]);
970  }
971 
972  FxDriverGlobals->ThreadTable = newTable;
973 
974  FxDriverGlobals->ThreadTableLock.Release(oldIrql);
975 
976  return;
977 }
978 
979 void
981  __in PFX_DRIVER_GLOBALS FxDriverGlobals
982  )
983 {
984  KIRQL oldIrql;
985 
986  UNREFERENCED_PARAMETER(FxDriverGlobals);
987 
988  FxDriverGlobals->ThreadTableLock.Acquire(&oldIrql);
989 
990  if( FxDriverGlobals->ThreadTable == NULL ) {
991  FxDriverGlobals->ThreadTableLock.Release(oldIrql);
992  return;
993  }
994 
995  FxPoolFree(FxDriverGlobals->ThreadTable);
996 
997  FxDriverGlobals->ThreadTable = NULL;
998 
999  FxDriverGlobals->ThreadTableLock.Release(oldIrql);
1000 
1001  return;
1002 }
1003 
1004 void
1007  __in MxThread curThread,
1008  __in FxVerifierLock* PerThreadList
1009  )
1010 {
1011  PFX_DRIVER_GLOBALS FxDriverGlobals = Lock->GetDriverGlobals();
1012 
1014 
1016  "Thread 0x%p Attempted to acquire lock on Object 0x%p, "
1017  "ObjectType 0x%x, at Level 0x%x out of sequence.",
1018  curThread,Lock->m_ParentObject,
1019  Lock->m_ParentObject->GetType(),
1020  Lock->m_Order);
1021 
1022  next = PerThreadList;
1023 
1025  "Highest Lock Currently held is level 0x%x for "
1026  "Object 0x%p, ObjectType 0x%x",
1027  next->m_Order,
1028  next->m_ParentObject,
1029  next->m_ParentObject->GetType());
1030 
1032  "List of Already Acquired Locks and Objects:");
1033 
1034  while( next != NULL ) {
1035 
1037  "Object 0x%p, ObjectType 0x%x, LockLevel 0x%x",
1038  next->m_ParentObject,
1039  next->m_ParentObject->GetType(),
1040  next->m_Order);
1041 
1042  next = next->m_OwnedLink;
1043  }
1044 
1045  FxVerifierDbgBreakPoint(FxDriverGlobals);
1046 
1047  return;
1048 }
1049 
1050 
struct _LIST_ENTRY * PLIST_ENTRY
static int Hash(const char *)
Definition: reader.c:2257
ObjectType
Definition: metafile.c:80
PLIST_ENTRY ThreadTable
Definition: fxglobals.h:400
FxVerifierOrderMapping FxVerifierCallbackOrderTable[]
#define FX_VERIFIER_CALLBACKLOCK_ENTRIES()
MxPagedLock m_Mutex
struct outqueuenode * head
Definition: adnsresfilter.c:66
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
static pFxVerifierThreadTableEntry GetThreadTableEntry(__in MxThread curThread, __in FxVerifierLock *pLock, __in BOOLEAN LookupOnly)
__inline VOID ReleaseUnsafe()
static void FreeThreadTable(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
__inline VOID AcquireUnsafe()
Definition: mxpagedlockkm.h:78
#define InsertTailList(ListHead, Entry)
VOID Unlock(__in KIRQL PreviousIrql, __in BOOLEAN AtDpc)
WDFTYPE GetType(VOID)
Definition: fxobject.hpp:742
#define FxVerifierBugCheck(FxDriverGlobals, Error,...)
Definition: fxverifier.h:58
void FxVerifierLockInitialize(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
uint32_t ULONG_PTR
Definition: typedefs.h:65
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define FALSE
Definition: types.h:117
#define TRACE_LEVEL_FATAL
Definition: storswtr.h:26
VOID Lock(__out PKIRQL PreviousIrql, __in BOOLEAN AtDpc)
void FxVerifierLockDestroy(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
PVOID __inline GetObjectHandle(VOID)
Definition: fxobject.hpp:603
#define __out
Definition: dbghelp.h:62
KIRQL GetLockPreviousIrql(VOID)
unsigned char BOOLEAN
FxVerifierLock * m_OwnedLink
FxObject * m_ParentObject
GLuint index
Definition: glext.h:6031
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
FxVerifierThreadTableEntry m_ThreadTableEntry
MxThread m_OwningThread
#define VERIFIER_THREAD_HASHTABLE_SIZE
#define TRACINGDEVICE
Definition: dbgtrace.h:58
#define ASSERT(a)
Definition: mode.c:44
_In_ WDFCOLLECTION _In_ ULONG Index
static void AllocateThreadTable(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
static __inline KIRQL MxGetCurrentIrql()
Definition: mxgeneralkm.h:86
#define FX_LOCK_ORDER_UNKNOWN
#define FX_VERIFIER_LOCK_ENTRIES()
FxSpinLock * pLock
uint32_t entry
Definition: isohybrid.c:63
KIRQL * PKIRQL
Definition: env_spec_w32.h:592
Definition: typedefs.h:119
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
FxVerifierOrderMapping FxVerifierOrderTable[]
MxLock ThreadTableLock
Definition: fxglobals.h:398
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
static __inline MxThread MxGetCurrentThread()
Definition: mxgeneralkm.h:61
static void DumpDetails(__in FxVerifierLock *Lock, __in MxThread curThread, __in FxVerifierLock *PerThreadList)
static unsigned __int64 next
Definition: rand_nt.c:6
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
FxVerifierLock * PerThreadDispatchLockList
unsigned short USHORT
Definition: pedump.c:61
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
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 ULONG_PTR
Definition: config.h:101
GLfloat GLfloat p
Definition: glext.h:8902
void FxPoolFree(__in_xcount(ptr is at an offset from AllocationStart) PVOID ptr)
Definition: wdfpool.cpp:361
#define __in
Definition: dbghelp.h:35
PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxstump.hpp:98
FxVerifierDbgBreakPoint(pFxDriverGlobals)
LONGLONG QuadPart
Definition: typedefs.h:114
static __inline VOID MxDelayExecutionThread(__in KPROCESSOR_MODE WaitMode, __in BOOLEAN Alertable, __in PLARGE_INTEGER Interval)
Definition: mxgeneralkm.h:209