ReactOS 0.4.15-dev-7924-g5949c20
fxverifierlock.cpp
Go to the documentation of this file.
1/*++
2
3Copyright (c) Microsoft Corporation
4
5Module Name:
6
7 FxVerifierLock.cpp
8
9Abstract:
10
11 This module contains the implementation of the verifier lock
12
13Author:
14
15
16
17
18Environment:
19
20 Both kernel and user mode
21
22Revision History:
23
24
25
26
27--*/
28
29#include "fxobjectpch.hpp"
30
31extern "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//
116extern "C"
117void
119 __in PFX_DRIVER_GLOBALS FxDriverGlobals
120 )
121{
122 if( FxDriverGlobals->FxVerifierLock ) {
123
124 FxDriverGlobals->ThreadTableLock.Initialize();
125
127 }
128
129 return;
130}
131
132//
133// Called at Driver Frameworks is unloading
134//
135extern "C"
136void
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
150VOID
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 ) {
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
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 //
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
301void
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;
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;
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;
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;
539
540 while( next != NULL ) {
541
542 if( next == this ) {
543 prev->m_OwnedLink = m_OwnedLink;
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
601KIRQL
603{
604 return m_OldIrql;
605}
606
607void
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{
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
822void
824 __in MxThread curThread,
826 )
827
828/*++
829
830Routine 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
837Arguments:
838
839 curThread - Thread who is holding lock
840
841 pLock - Lock whose m_ThreadTableEntry is to be released
842
843Returns:
844
845
846Comments:
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{
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
936void
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
954
955 newTable = (PLIST_ENTRY) FxPoolAllocateWithTag(
956 FxDriverGlobals,
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
979void
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
1004void
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
unsigned char BOOLEAN
struct outqueuenode * head
Definition: adnsresfilter.c:66
WDFTYPE GetType(VOID)
Definition: fxobject.hpp:742
PVOID __inline GetObjectHandle(VOID)
Definition: fxobject.hpp:603
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
FxVerifierThreadTableEntry m_ThreadTableEntry
VOID Unlock(__in KIRQL PreviousIrql, __in BOOLEAN AtDpc)
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)
FxObject * m_ParentObject
void InitializeLockOrder(VOID)
VOID Lock(__out PKIRQL PreviousIrql, __in BOOLEAN AtDpc)
__inline VOID AcquireUnsafe()
Definition: mxpagedlockkm.h:78
__inline VOID ReleaseUnsafe()
static __inline MxThread MxGetCurrentThread()
Definition: mxgeneralkm.h:61
static __inline KIRQL MxGetCurrentIrql()
Definition: mxgeneralkm.h:86
static __inline VOID MxDelayExecutionThread(__in KPROCESSOR_MODE WaitMode, __in BOOLEAN Alertable, __in PLARGE_INTEGER Interval)
Definition: mxgeneralkm.h:209
#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
static int Hash(const char *)
Definition: reader.c:2257
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UCHAR KIRQL
Definition: env_spec_w32.h:591
KIRQL * PKIRQL
Definition: env_spec_w32.h:592
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
FxVerifierDbgBreakPoint(pFxDriverGlobals)
void FxPoolFree(__in_xcount(ptr is at an offset from AllocationStart) PVOID ptr)
Definition: wdfpool.cpp:361
FxSpinLock * pLock
#define FxVerifierBugCheck(FxDriverGlobals, Error,...)
Definition: fxverifier.h:58
void FxVerifierLockDestroy(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
FxVerifierOrderMapping FxVerifierCallbackOrderTable[]
void FxVerifierLockInitialize(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
FxVerifierOrderMapping FxVerifierOrderTable[]
#define FX_VERIFIER_LOCK_ENTRIES()
#define FX_LOCK_ORDER_UNKNOWN
#define VERIFIER_THREAD_HASHTABLE_SIZE
#define FX_VERIFIER_CALLBACKLOCK_ENTRIES()
GLuint index
Definition: glext.h:6031
GLfloat GLfloat p
Definition: glext.h:8902
uint32_t entry
Definition: isohybrid.c:63
#define ASSERT(a)
Definition: mode.c:44
ObjectType
Definition: metafile.c:81
#define KernelMode
Definition: asm.h:34
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
unsigned short USHORT
Definition: pedump.c:61
static unsigned __int64 next
Definition: rand_nt.c:6
#define TRACE_LEVEL_FATAL
Definition: storswtr.h:26
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxstump.hpp:98
FxVerifierLock * PerThreadDispatchLockList
FxVerifierLock * PerThreadPassiveLockList
PLIST_ENTRY ThreadTable
Definition: fxglobals.h:400
MxLock ThreadTableLock
Definition: fxglobals.h:398
Definition: typedefs.h:120
struct _LIST_ENTRY * PLIST_ENTRY
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
LONGLONG QuadPart
Definition: typedefs.h:114
@ WDF_RECURSIVE_LOCK
Definition: wdfbugcodes.h:59
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:127