ReactOS 0.4.15-dev-6054-gbddd8b0
resource.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ex/resource.c
5 * PURPOSE: Executive Resource Implementation
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9/* INCLUDES *****************************************************************/
10
11#include <ntoskrnl.h>
12#define NDEBUG
13#include <debug.h>
14
15/* Macros for reading resource flags */
16#define IsExclusiveWaiting(r) (r->NumberOfExclusiveWaiters > 0)
17#define IsSharedWaiting(r) (r->NumberOfSharedWaiters > 0)
18#define IsOwnedExclusive(r) (r->Flag & ResourceOwnedExclusive)
19#define IsBoostAllowed(r) (!(r->Flag & ResourceHasDisabledPriorityBoost))
20
21#if (!(defined(CONFIG_SMP)) && !(DBG))
22
24VOID
27{
30
31 /* Simply disable interrupts */
32 _disable();
33}
34
36VOID
39{
42
43 /* Simply enable interrupts */
44 _enable();
45}
46
47#else
48
50VOID
53{
54 /* Acquire the lock */
56}
57
59VOID
62{
64
65 /* Release the lock */
67}
68#endif
69
70/* DATA***********************************************************************/
71
72LARGE_INTEGER ExShortTime = {{-100000, -1}};
78
79/* PRIVATE FUNCTIONS *********************************************************/
80
81#if DBG
82/*++
83 * @name ExpVerifyResource
84 *
85 * The ExpVerifyResource routine verifies the correctness of an ERESOURCE
86 *
87 * @param Resource
88 * Pointer to the resource being verified.
89 *
90 * @return None.
91 *
92 * @remarks Only present on DBG builds.
93 *
94 *--*/
95VOID
98{
99 /* Verify the resource data */
100 ASSERT((((ULONG_PTR)Resource) & (sizeof(ULONG_PTR) - 1)) == 0);
101 ASSERT(!Resource->SharedWaiters ||
102 Resource->SharedWaiters->Header.Type == SemaphoreObject);
103 ASSERT(!Resource->SharedWaiters ||
104 Resource->SharedWaiters->Header.Size == (sizeof(KSEMAPHORE) / sizeof(ULONG)));
105 ASSERT(!Resource->ExclusiveWaiters ||
106 Resource->ExclusiveWaiters->Header.Type == SynchronizationEvent);
107 ASSERT(!Resource->ExclusiveWaiters ||
108 Resource->ExclusiveWaiters->Header.Size == (sizeof(KEVENT) / sizeof(ULONG)));
109}
110
111/*++
112 * @name ExpCheckForApcsDisabled
113 *
114 * The ExpCheckForApcsDisabled routine checks if Kernel APCs are still
115 * enabled when they should be disabled, and optionally breakpoints.
116 *
117 * @param Irql
118 * Specifies the IRQL during the acquire attempt.
119 *
120 * @param Resource
121 * Pointer to the resource being checked.
122 *
123 * @param Thread
124 * Pointer to the thread being checked.
125 *
126 * @return None.
127 *
128 * @remarks Only present on DBG builds. Depends on ExResourceStrict value.
129 *
130 *--*/
131VOID
132NTAPI
136{
137 /* Check if we should care and check if we should break */
138 if ((ExResourceStrict) &&
139 (Irql < APC_LEVEL) &&
141 !(Thread->CombinedApcDisable))
142 {
143 /* Bad! */
144 DPRINT1("EX: resource: APCs still enabled before resource %p acquire/release "
145 "!!!\n", Resource);
147 }
148}
149#else
150#define ExpVerifyResource(r)
151#define ExpCheckForApcsDisabled(b,r,t)
152#endif
153
154/*++
155 * @name ExpResourceInitialization
156 *
157 * The ExpResourceInitialization routine initializes resources for use.
158 *
159 * @param None.
160 *
161 * @return None.
162 *
163 * @remarks This routine should only be called once, during system startup.
164 *
165 *--*/
166CODE_SEG("INIT")
167VOID
168NTAPI
170{
171 /* Setup the timeout */
172 ExpTimeout.QuadPart = Int32x32To64(4, -10000000);
175}
176
177/*++
178 * @name ExpAllocateExclusiveWaiterEvent
179 *
180 * The ExpAllocateExclusiveWaiterEvent routine creates the event that will
181 * be used by exclusive waiters on the resource.
182 *
183 * @param Resource
184 * Pointer to the resource.
185 *
186 * @param LockHandle
187 * Pointer to in-stack queued spinlock.
188 *
189 * @return None.
190 *
191 * @remarks The pointer to the event must be atomically set.
192 *
193 *--*/
194VOID
195NTAPI
198{
200
201 /* Release the lock */
203
204 /* Loop as long as we keep running out of memory */
205 do
206 {
207 /* Allocate the event */
209 sizeof(KEVENT),
211 if (Event)
212 {
213 /* Initialize it */
215
216 /* Set it */
217 if (InterlockedCompareExchangePointer((PVOID*)&Resource->ExclusiveWaiters,
218 Event,
219 NULL))
220 {
221 /* Someone already set it, free our event */
222 DPRINT1("WARNING: Handling race condition\n");
224 }
225
226 break;
227 }
228
229 /* Wait a bit before trying again */
231 } while (TRUE);
232
233 /* Re-acquire the lock */
235}
236
237/*++
238 * @name ExpAllocateSharedWaiterSemaphore
239 *
240 * The ExpAllocateSharedWaiterSemaphore routine creates the semaphore that
241 * will be used by shared waiters on the resource.
242 *
243 * @param Resource
244 * Pointer to the resource.
245 *
246 * @param LockHandle
247 * Pointer to in-stack queued spinlock.
248 *
249 * @return None.
250 *
251 * @remarks The pointer to the semaphore must be atomically set.
252 *
253 *--*/
254VOID
255NTAPI
258{
259 PKSEMAPHORE Semaphore;
260
261 /* Release the lock */
263
264 /* Loop as long as we keep running out of memory */
265 do
266 {
267 /* Allocate the semaphore */
269 sizeof(KSEMAPHORE),
271 if (Semaphore)
272 {
273 /* Initialize it */
274 KeInitializeSemaphore(Semaphore, 0, MAXLONG);
275
276 /* Set it */
278 Semaphore,
279 NULL))
280 {
281 /* Someone already set it, free our semaphore */
282 DPRINT1("WARNING: Handling race condition\n");
284 }
285
286 break;
287 }
288
289 /* Wait a bit before trying again */
291 } while (TRUE);
292
293 /* Re-acquire the lock */
295}
296
297/*++
298 * @name ExpExpandResourceOwnerTable
299 *
300 * The ExpExpandResourceOwnerTable routine expands the owner table of the
301 * specified resource.
302 *
303 * @param Resource
304 * Pointer to the resource.
305 *
306 * @param LockHandle
307 * Pointer to in-stack queued spinlock.
308 *
309 * @return None.
310 *
311 * @remarks None.
312 *
313 *--*/
314VOID
315NTAPI
318{
321 ULONG NewSize, OldSize;
322
323 /* Get the owner table */
324 Owner = Resource->OwnerTable;
325 if (!Owner)
326 {
327 /* Start with the default size of 3 */
328 OldSize = 0;
329 NewSize = 3;
330 }
331 else
332 {
333 /* Add 4 more entries */
334 OldSize = Owner->TableSize;
335 NewSize = OldSize + 4;
336 }
337
338 /* Release the lock */
340
341 /* Allocate memory for the table */
343 NewSize * sizeof(OWNER_ENTRY),
345
346 /* Zero the table */
347 RtlZeroMemory(Table + OldSize,
348 (NewSize - OldSize) * sizeof(OWNER_ENTRY));
349
350 /* Lock the resource */
352
353 /* Make sure nothing has changed */
354 if ((Owner != Resource->OwnerTable) ||
355 ((Owner) && (OldSize != Owner->TableSize)))
356 {
357 /* Resource changed while we weren't holding the lock; bail out */
360 }
361 else
362 {
363 /* Copy the table */
364 if (Owner) RtlCopyMemory(Table, Owner, OldSize * sizeof(OWNER_ENTRY));
365
366 /* Acquire dispatcher lock to prevent thread boosting */
368
369 /* Set the new table data */
370 Table->TableSize = NewSize;
371 Resource->OwnerTable = Table;
372
373 /* Release dispatcher lock */
375
376 /* Sanity check */
378
379 /* Release lock */
381
382 /* Free the old table */
384
385 /* Set the resource index */
386 if (!OldSize) OldSize = 1;
387 }
388
389 /* Set the resource index */
390 KeGetCurrentThread()->ResourceIndex = (UCHAR)OldSize;
391
392 /* Lock the resource again */
394}
395
396/*++
397 * @name ExpFindFreeEntry
398 *
399 * The ExpFindFreeEntry routine locates an empty owner entry in the
400 * specified resource. If none was found, then the owner table is
401 * expanded.
402 *
403 * @param Resource
404 * Pointer to the resource.
405 *
406 * @param LockHandle
407 * Pointer to in-stack queued spinlock.
408 *
409 * @return Pointer to an empty OWNER_ENTRY structure.
410 *
411 * @remarks None.
412 *
413 *--*/
418{
420
421 /* Sanity check */
422 ASSERT(LockHandle != 0);
423 ASSERT(Resource->OwnerEntry.OwnerThread != 0);
424
425 /* Get the current table pointer */
426 Owner = Resource->OwnerTable;
427 if (Owner)
428 {
429 /* Set the limit, move to the next owner and loop owner entries */
430 Limit = &Owner[Owner->TableSize];
431 Owner++;
432 while (Owner->OwnerThread)
433 {
434 /* Move to the next one */
435 Owner++;
436
437 /* Check if the entry is free */
438 if (Owner == Limit) goto Expand;
439 }
440
441 /* Update the resource entry */
442 KeGetCurrentThread()->ResourceIndex = (UCHAR)(Owner - Resource->OwnerTable);
443 }
444 else
445 {
446Expand:
447 /* No free entry, expand the table */
449 Owner = NULL;
450 }
451
452 /* Return the entry found */
453 return Owner;
454}
455
456/*++
457 * @name ExpFindEntryForThread
458 *
459 * The ExpFindEntryForThread routine locates the owner entry associated with
460 * the specified thread in the given resource. If none was found, then the
461 * owner table is expanded.
462 *
463 * @param Resource
464 * Pointer to the resource.
465 *
466 * @param Thread
467 * Pointer to the thread to find.
468 *
469 * @param LockHandle
470 * Pointer to in-stack queued spinlock.
471 *
472 * @return Pointer to an empty OWNER_ENTRY structure.
473 *
474 * @remarks None.
475 *
476 *--*/
482 IN BOOLEAN FirstEntryInelligible)
483{
484 POWNER_ENTRY FreeEntry, Owner, Limit;
485
486 /* Start by looking in the static array */
487 Owner = &Resource->OwnerEntry;
488 if (Owner->OwnerThread == Thread) return Owner;
489
490 /* Check if this is a free entry */
491 if ((FirstEntryInelligible) || (Owner->OwnerThread))
492 {
493 /* No free entry */
494 FreeEntry = NULL;
495 }
496 else
497 {
498 /* Use the first entry as our free entry */
499 FreeEntry = Owner;
500 }
501
502 /* Get the current table pointer */
503 Owner = Resource->OwnerTable;
504 if (Owner)
505 {
506 /* Set the limit, move to the next owner and loop owner entries */
507 Limit = &Owner[Owner->TableSize];
508 Owner++;
509 while (Owner->OwnerThread != Thread)
510 {
511 /* Check if we don't have a free entry */
512 if (!FreeEntry)
513 {
514 /* Check if this entry is free */
515 if (!Owner->OwnerThread)
516 {
517 /* Save it as our free entry */
518 FreeEntry = Owner;
519 }
520 }
521
522 /* Move to the next one */
523 Owner++;
524
525 /* Check if the entry is free */
526 if (Owner == Limit) goto Expand;
527 }
528
529 /* Update the resource entry */
530 KeGetCurrentThread()->ResourceIndex = (UCHAR)(Owner - Resource->OwnerTable);
531 return Owner;
532 }
533 else
534 {
535Expand:
536 /* Check if it's OK to do an expansion */
537 if (!LockHandle) return NULL;
538
539 /* If we found a free entry by now, return it */
540 if (FreeEntry)
541 {
542 /* Set the resource index */
543 KeGetCurrentThread()->ResourceIndex = (UCHAR)(FreeEntry - Resource->OwnerTable);
544 return FreeEntry;
545 }
546
547 /* No free entry, expand the table */
549 return NULL;
550 }
551}
552
553/*++
554 * @name ExpBoostOwnerThread
555 *
556 * The ExpBoostOwnerThread routine increases the priority of a waiting
557 * thread in an attempt to fight a possible deadlock.
558 *
559 * @param Thread
560 * Pointer to the current thread.
561 *
562 * @param OwnerThread
563 * Pointer to thread that owns the resource.
564 *
565 * @return None.
566 *
567 * @remarks None.
568 *
569 *--*/
570VOID
573 IN PKTHREAD OwnerThread)
574{
575 /* Make sure the owner thread is a pointer, not an ID */
576 if (!((ULONG_PTR)OwnerThread & 0x3))
577 {
578 /* Check if we can actually boost it */
579 if ((OwnerThread->Priority < Thread->Priority) &&
580 (OwnerThread->Priority < 14))
581 {
582 /* Acquire the thread lock */
584
585 /* Set the new priority */
586 OwnerThread->PriorityDecrement += 14 - OwnerThread->Priority;
587
588 /* Update quantum */
589 OwnerThread->Quantum = OwnerThread->QuantumReset;
590
591 /* Update the kernel state */
592 KiSetPriorityThread(OwnerThread, 14);
593
594 /* Release the thread lock */
596 }
597 }
598}
599
600/*++
601 * @name ExpWaitForResource
602 *
603 * The ExpWaitForResource routine performs a wait on the specified resource.
604 *
605 * @param Resource
606 * Pointer to the resource to wait on.
607 *
608 * @param OwnerThread
609 * Pointer to object (exclusive event or shared semaphore) to wait on.
610 *
611 * @return None.
612 *
613 * @remarks None.
614 *
615 *--*/
616VOID
620{
621 ULONG i;
622 ULONG Size;
624 ULONG WaitCount = 0;
627 PKTHREAD Thread, OwnerThread;
628#if DBG
630#endif
631
632 /* Increase contention count and use a 5 second timeout */
633 Resource->ContentionCount++;
634 Timeout.QuadPart = 500 * -10000;
635 for (;;)
636 {
637 /* Wait for ownership */
641 FALSE,
642 &Timeout);
643 if (Status != STATUS_TIMEOUT) break;
644
645 /* Increase wait count */
646 WaitCount++;
648
649 /* Check if we've exceeded the limit */
650 if (WaitCount > ExpResourceTimeoutCount)
651 {
652 /* Reset wait count */
653 WaitCount = 0;
654#if DBG
655 /* Lock the resource */
657
658 /* Dump debug information */
659 DPRINT1("Resource @ %p\n", Resource);
660 DPRINT1(" ActiveEntries = %04lx Flags = %s%s%s\n",
661 Resource->ActiveEntries,
662 IsOwnedExclusive(Resource) ? "IsOwnedExclusive " : "",
663 IsSharedWaiting(Resource) ? "SharedWaiter " : "",
664 IsExclusiveWaiting(Resource) ? "ExclusiveWaiter " : "");
665 DPRINT1(" NumberOfExclusiveWaiters = %04lx\n",
666 Resource->NumberOfExclusiveWaiters);
667 DPRINT1(" Thread = %08lx, Count = %02x\n",
668 Resource->OwnerEntry.OwnerThread,
669 Resource->OwnerEntry.OwnerCount);
670
671 /* Dump out the table too */
672 Owner = Resource->OwnerTable;
673 if (Owner)
674 {
675 /* Loop every entry */
676 Size = Owner->TableSize;
677 for (i = 1; i < Size; i++)
678 {
679 /* Print the data */
680 Owner++;
681 DPRINT1(" Thread = %08lx, Count = %02x\n",
682 Owner->OwnerThread,
683 Owner->OwnerCount);
684 }
685 }
686
687 /* Break */
689 DPRINT1("EX - Rewaiting\n");
691#endif
692 }
693
694 /* Check if we can boost */
696 {
697 /* Get the current kernel thread and lock the dispatcher */
699 Thread->WaitIrql = KiAcquireDispatcherLock();
700 Thread->WaitNext = TRUE;
701
702 /* Get the owner thread and boost it */
703 OwnerThread = (PKTHREAD)Resource->OwnerEntry.OwnerThread;
704 if (OwnerThread) ExpBoostOwnerThread(Thread, OwnerThread);
705
706 /* If it's a shared resource */
708 {
709 /* Get the table */
710 Owner = Resource->OwnerTable;
711 if (Owner)
712 {
713 /* Loop every entry */
714 Size = Owner->TableSize;
715 for (i = 1; i < Size; i++)
716 {
717 /* Move to next entry */
718 Owner++;
719
720 /* Get the thread */
721 OwnerThread = (PKTHREAD)Owner->OwnerThread;
722
723 /* Boost it */
724 if (OwnerThread) ExpBoostOwnerThread(Thread, OwnerThread);
725 }
726 }
727 }
728 }
729 }
730}
731
732/* FUNCTIONS *****************************************************************/
733
734/*++
735 * @name ExAcquireResourceExclusiveLite
736 * @implemented NT4
737 *
738 * The ExAcquireResourceExclusiveLite routine acquires the given resource
739 * for exclusive access by the calling thread.
740 *
741 * @param Resource
742 * Pointer to the resource to acquire.
743 *
744 * @param Wait
745 * Specifies the routine's behavior whenever the resource cannot be
746 * acquired immediately.
747 *
748 * @return TRUE if the resource is acquired. FALSE if the input Wait is FALSE
749 * and exclusive access cannot be granted immediately.
750 *
751 * @remarks The caller can release the resource by calling either
752 * ExReleaseResourceLite or ExReleaseResourceForThreadLite.
753 *
754 * Normal kernel APC delivery must be disabled before calling this
755 * routine. Disable normal kernel APC delivery by calling
756 * KeEnterCriticalRegion. Delivery must remain disabled until the
757 * resource is released, at which point it can be reenabled by calling
758 * KeLeaveCriticalRegion.
759 *
760 * For better performance, call ExTryToAcquireResourceExclusiveLite,
761 * rather than calling ExAcquireResourceExclusiveLite with Wait set
762 * to FALSE.
763 *
764 * Callers of ExAcquireResourceExclusiveLite must be running at IRQL <
765 * DISPATCH_LEVEL.
766 *
767 *--*/
769NTAPI
772{
776
777 /* Sanity check */
778 ASSERT((Resource->Flag & ResourceNeverExclusive) == 0);
779
780 /* Get the thread */
782
783 /* Sanity check and validation */
786
787 /* Acquire the lock */
790
791 /* Check if there is a shared owner or exclusive owner */
792TryAcquire:
793 if (Resource->ActiveEntries)
794 {
795 /* Check if it's exclusively owned, and we own it */
796 if ((IsOwnedExclusive(Resource)) &&
797 (Resource->OwnerEntry.OwnerThread == Thread))
798 {
799 /* Increase the owning count */
800 Resource->OwnerEntry.OwnerCount++;
801 Success = TRUE;
802 }
803 else
804 {
805 /*
806 * If the caller doesn't want us to wait, we can't acquire the
807 * resource because someone else then us owns it. If we can wait,
808 * then we'll wait.
809 */
810 if (!Wait)
811 {
812 Success = FALSE;
813 }
814 else
815 {
816 /* Check if it has exclusive waiters */
817 if (!Resource->ExclusiveWaiters)
818 {
819 /* It doesn't, allocate the event and try acquiring again */
821 goto TryAcquire;
822 }
823
824 /* Has exclusive waiters, wait on it */
825 Resource->NumberOfExclusiveWaiters++;
827 ExpWaitForResource(Resource, Resource->ExclusiveWaiters);
828
829 /* Set owner and return success */
830 Resource->OwnerEntry.OwnerThread = ExGetCurrentResourceThread();
831 return TRUE;
832 }
833 }
834 }
835 else
836 {
837 /* Nobody owns it, so let's! */
838 ASSERT(Resource->ActiveEntries == 0);
839 ASSERT(Resource->ActiveCount == 0);
841 Resource->ActiveEntries = 1;
842 Resource->ActiveCount = 1;
843 Resource->OwnerEntry.OwnerThread = Thread;
844 Resource->OwnerEntry.OwnerCount = 1;
845 Success = TRUE;
846 }
847
848 /* Release the lock and return */
850 return Success;
851}
852
853/*++
854 * @name ExAcquireResourceSharedLite
855 * @implemented NT4
856 *
857 * The ExAcquireResourceSharedLite routine acquires the given resource
858 * for shared access by the calling thread.
859 *
860 * @param Resource
861 * Pointer to the resource to acquire.
862 *
863 * @param Wait
864 * Specifies the routine's behavior whenever the resource cannot be
865 * acquired immediately.
866 *
867 * @return TRUE if the resource is acquired. FALSE if the input Wait is FALSE
868 * and exclusive access cannot be granted immediately.
869 *
870 * @remarks The caller can release the resource by calling either
871 * ExReleaseResourceLite or ExReleaseResourceForThreadLite.
872 *
873 * Normal kernel APC delivery must be disabled before calling this
874 * routine. Disable normal kernel APC delivery by calling
875 * KeEnterCriticalRegion. Delivery must remain disabled until the
876 * resource is released, at which point it can be reenabled by calling
877 * KeLeaveCriticalRegion.
878 *
879 * Callers of ExAcquireResourceExclusiveLite must be running at IRQL <
880 * DISPATCH_LEVEL.
881 *
882 *--*/
884NTAPI
887{
891 BOOLEAN FirstEntryBusy;
892
893 /* Get the thread */
895
896 /* Sanity check and validation */
899
900 /* Acquire the lock */
903
904 /* Check how many active entries we've got */
905 while (Resource->ActiveEntries != 0)
906 {
907 /* Check if it's exclusively owned */
909 {
910 /* Check if we own it */
911 if (Resource->OwnerEntry.OwnerThread == Thread)
912 {
913 /* Increase the owning count */
914 Resource->OwnerEntry.OwnerCount++;
915
916 /* Release the lock and return */
918 return TRUE;
919 }
920
921 /* Find a free entry */
923 if (!Owner) continue;
924 }
925 else
926 {
927 /* Resource is shared, find who owns it */
928 FirstEntryBusy = IsExclusiveWaiting(Resource);
930 Thread,
931 &LockHandle,
932 FirstEntryBusy);
933 if (!Owner) continue;
934
935 /* Is it us? */
936 if (Owner->OwnerThread == Thread)
937 {
938 /* Increase acquire count and return */
939 Owner->OwnerCount++;
940 ASSERT(Owner->OwnerCount != 0);
941
942 /* Release the lock and return */
944 return TRUE;
945 }
946
947 /* Try to find if there are exclusive waiters */
948 if (!FirstEntryBusy)
949 {
950 /* There are none, so acquire it */
951 Owner->OwnerThread = Thread;
952 Owner->OwnerCount = 1;
953
954 /* Check how many active entries we had */
955 if (Resource->ActiveEntries == 0)
956 {
957 /* Set initial counts */
958 ASSERT(Resource->ActiveCount == 0);
959 Resource->ActiveEntries = 1;
960 Resource->ActiveCount = 1;
961 }
962 else
963 {
964 /* Increase active entries */
965 ASSERT(Resource->ActiveCount == 1);
966 Resource->ActiveEntries++;
967 }
968
969 /* Release the lock and return */
971 return TRUE;
972 }
973 }
974
975 /* If we got here, then we need to wait. Are we allowed? */
976 if (!Wait)
977 {
978 /* Release the lock and return */
980 return FALSE;
981 }
982
983 /* Check if we have a shared waiters semaphore */
984 if (!Resource->SharedWaiters)
985 {
986 /* Allocate it and try another acquire */
988 }
989 else
990 {
991 /* We have shared waiters, wait for it */
992 break;
993 }
994 }
995
996 /* Did we get here because we don't have active entries? */
997 if (Resource->ActiveEntries == 0)
998 {
999 /* Acquire it */
1000 ASSERT(Resource->ActiveEntries == 0);
1001 ASSERT(Resource->ActiveCount == 0);
1002 Resource->ActiveEntries = 1;
1003 Resource->ActiveCount = 1;
1004 Resource->OwnerEntry.OwnerThread = Thread;
1005 Resource->OwnerEntry.OwnerCount = 1;
1006
1007 /* Release the lock and return */
1009 return TRUE;
1010 }
1011
1012 /* Now wait for the resource */
1013 Owner->OwnerThread = Thread;
1014 Owner->OwnerCount = 1;
1015 Resource->NumberOfSharedWaiters++;
1016
1017 /* Release the lock and return */
1019 ExpWaitForResource(Resource, Resource->SharedWaiters);
1020 return TRUE;
1021}
1022
1023/*++
1024 * @name ExAcquireSharedStarveExclusive
1025 * @implemented NT4
1026 *
1027 * The ExAcquireSharedStarveExclusive routine acquires the given resource
1028 * shared access without waiting for any pending attempts to acquire
1029 * exclusive access to the same resource.
1030 *
1031 * @param Resource
1032 * Pointer to the resource to acquire.
1033 *
1034 * @param Wait
1035 * Specifies the routine's behavior whenever the resource cannot be
1036 * acquired immediately.
1037 *
1038 * @return TRUE if the resource is acquired. FALSE if the input Wait is FALSE
1039 * and exclusive access cannot be granted immediately.
1040 *
1041 * @remarks The caller can release the resource by calling either
1042 * ExReleaseResourceLite or ExReleaseResourceForThreadLite.
1043 *
1044 * Normal kernel APC delivery must be disabled before calling this
1045 * routine. Disable normal kernel APC delivery by calling
1046 * KeEnterCriticalRegion. Delivery must remain disabled until the
1047 * resource is released, at which point it can be reenabled by calling
1048 * KeLeaveCriticalRegion.
1049 *
1050 * Callers of ExAcquireSharedStarveExclusive usually need quick access
1051 * to a shared resource in order to save an exclusive accessor from
1052 * doing redundant work. For example, a file system might call this
1053 * routine to modify a cached resource, such as a BCB pinned in the
1054 * cache, before the Cache Manager can acquire exclusive access to the
1055 * resource and write the cache out to disk.
1056 *
1057 * Callers of ExAcquireResourceExclusiveLite must be running at IRQL <
1058 * DISPATCH_LEVEL.
1059 *
1060 *--*/
1061BOOLEAN
1062NTAPI
1064 IN BOOLEAN Wait)
1065{
1069
1070 /* Get the thread */
1072
1073 /* Sanity check and validation */
1076
1077 /* Acquire the lock */
1079
1080 /* See if anyone owns it */
1081TryAcquire:
1082 if (Resource->ActiveEntries == 0)
1083 {
1084 /* Nobody owns it, so let's take control */
1085 ASSERT(Resource->ActiveEntries == 0);
1086 ASSERT(Resource->ActiveCount == 0);
1087 Resource->ActiveCount = 1;
1088 Resource->ActiveEntries = 1;
1089 Resource->OwnerEntry.OwnerThread = Thread;
1090 Resource->OwnerEntry.OwnerCount = 1;
1091
1092 /* Release the lock and return */
1094 return TRUE;
1095 }
1096
1097 /* Check if it's exclusively owned */
1099 {
1100 /* Check if we own it */
1101 if (Resource->OwnerEntry.OwnerThread == Thread)
1102 {
1103 /* Increase the owning count */
1104 Resource->OwnerEntry.OwnerCount++;
1105
1106 /* Release the lock and return */
1108 return TRUE;
1109 }
1110
1111 /* Find a free entry */
1113 if (!Owner) goto TryAcquire;
1114 }
1115 else
1116 {
1117 /* Resource is shared, find who owns it */
1119 if (!Owner) goto TryAcquire;
1120
1121 /* Is it us? */
1122 if (Owner->OwnerThread == Thread)
1123 {
1124 /* Increase acquire count and return */
1125 Owner->OwnerCount++;
1126 ASSERT(Owner->OwnerCount != 0);
1127
1128 /* Release the lock and return */
1130 return TRUE;
1131 }
1132
1133 /* Acquire it */
1134 Owner->OwnerThread = Thread;
1135 Owner->OwnerCount = 1;
1136
1137 /* Check how many active entries we had */
1138 if (Resource->ActiveEntries == 0)
1139 {
1140 /* Set initial counts */
1141 ASSERT(Resource->ActiveCount == 0);
1142 Resource->ActiveEntries = 1;
1143 Resource->ActiveCount = 1;
1144 }
1145 else
1146 {
1147 /* Increase active entries */
1148 ASSERT(Resource->ActiveCount == 1);
1149 Resource->ActiveEntries++;
1150 }
1151
1152 /* Release the lock and return */
1154 return TRUE;
1155 }
1156
1157 /* If we got here, then we need to wait. Are we allowed? */
1158 if (!Wait)
1159 {
1160 /* Release the lock and return */
1162 return FALSE;
1163 }
1164
1165 /* Check if we have a shared waiters semaphore */
1166 if (!Resource->SharedWaiters)
1167 {
1168 /* Allocate it and try another acquire */
1170 goto TryAcquire;
1171 }
1172
1173 /* Now wait for the resource */
1174 Owner->OwnerThread = Thread;
1175 Owner->OwnerCount = 1;
1176 Resource->NumberOfSharedWaiters++;
1177
1178 /* Release the lock and return */
1180 ExpWaitForResource(Resource, Resource->SharedWaiters);
1181 return TRUE;
1182}
1183
1184/*++
1185 * @name ExAcquireSharedWaitForExclusive
1186 * @implemented NT4
1187 *
1188 * The ExAcquireSharedWaitForExclusive routine acquires the given resource
1189 * for shared access if shared access can be granted and there are no
1190 * exclusive waiters.
1191 *
1192 * @param Resource
1193 * Pointer to the resource to acquire.
1194 *
1195 * @param Wait
1196 * Specifies the routine's behavior whenever the resource cannot be
1197 * acquired immediately.
1198 *
1199 * @return TRUE if the resource is acquired. FALSE if the input Wait is FALSE
1200 * and exclusive access cannot be granted immediately.
1201 *
1202 * @remarks The caller can release the resource by calling either
1203 * ExReleaseResourceLite or ExReleaseResourceForThreadLite.
1204 *
1205 * Normal kernel APC delivery must be disabled before calling this
1206 * routine. Disable normal kernel APC delivery by calling
1207 * KeEnterCriticalRegion. Delivery must remain disabled until the
1208 * resource is released, at which point it can be reenabled by calling
1209 * KeLeaveCriticalRegion.
1210 *
1211 * Callers of ExAcquireResourceExclusiveLite must be running at IRQL <
1212 * DISPATCH_LEVEL.
1213 *
1214 *--*/
1215BOOLEAN
1216NTAPI
1218 IN BOOLEAN Wait)
1219{
1223
1224 /* Get the thread */
1226
1227 /* Sanity check and validation */
1230
1231 /* Acquire the lock */
1233
1234 /* See if nobody owns us */
1235TryAcquire:
1236 if (!Resource->ActiveEntries)
1237 {
1238 /* Nobody owns it, so let's take control */
1239 ASSERT(Resource->ActiveEntries == 0);
1240 ASSERT(Resource->ActiveCount == 0);
1241 Resource->ActiveCount = 1;
1242 Resource->ActiveEntries = 1;
1243 Resource->OwnerEntry.OwnerThread = Thread;
1244 Resource->OwnerEntry.OwnerCount = 1;
1245
1246 /* Release the lock and return */
1248 return TRUE;
1249 }
1250
1251 /* Check if it's exclusively owned */
1253 {
1254 /* Check if we own it */
1255 if (Resource->OwnerEntry.OwnerThread == Thread)
1256 {
1257 /* Increase the owning count */
1258 Resource->OwnerEntry.OwnerCount++;
1259
1260 /* Release the lock and return */
1262 return TRUE;
1263 }
1264
1265 /* Find a free entry */
1267 if (!Owner) goto TryAcquire;
1268 }
1269 else
1270 {
1271 /* Try to find if there are exclusive waiters */
1273 {
1274 /* We have to wait for the exclusive waiter to be done */
1275 if (!Wait)
1276 {
1277 /* So bail out if we're not allowed */
1279 return FALSE;
1280 }
1281
1282 /* Check if we have a shared waiters semaphore */
1283 if (!Resource->SharedWaiters)
1284 {
1285 /* Allocate one and try again */
1287 goto TryAcquire;
1288 }
1289
1290 /* Now wait for the resource */
1291 Resource->NumberOfSharedWaiters++;
1293 ExpWaitForResource(Resource, Resource->SharedWaiters);
1294
1295 /* Get the lock back */
1297
1298 /* Find who owns it now */
1300
1301 /* Sanity checks */
1303 ASSERT(Resource->ActiveEntries > 0);
1304 ASSERT(Owner->OwnerThread != Thread);
1305
1306 /* Take control */
1307 Owner->OwnerThread = Thread;
1308 Owner->OwnerCount = 1;
1309
1310 /* Release the lock and return */
1312 return TRUE;
1313 }
1314 else
1315 {
1316 /* Resource is shared, find who owns it */
1318 if (!Owner) goto TryAcquire;
1319
1320 /* Is it us? */
1321 if (Owner->OwnerThread == Thread)
1322 {
1323 /* Increase acquire count and return */
1324 Owner->OwnerCount++;
1325 ASSERT(Owner->OwnerCount != 0);
1326
1327 /* Release the lock and return */
1329 return TRUE;
1330 }
1331
1332 /* No exclusive waiters, so acquire it */
1333 Owner->OwnerThread = Thread;
1334 Owner->OwnerCount = 1;
1335
1336 /* Check how many active entries we had */
1337 if (Resource->ActiveEntries == 0)
1338 {
1339 /* Set initial counts */
1340 ASSERT(Resource->ActiveCount == 0);
1341 Resource->ActiveEntries = 1;
1342 Resource->ActiveCount = 1;
1343 }
1344 else
1345 {
1346 /* Increase active entries */
1347 ASSERT(Resource->ActiveCount == 1);
1348 Resource->ActiveEntries++;
1349 }
1350
1351 /* Release the lock and return */
1353 return TRUE;
1354 }
1355 }
1356
1357 /* We have to wait for the exclusive waiter to be done */
1358 if (!Wait)
1359 {
1360 /* So bail out if we're not allowed */
1362 return FALSE;
1363 }
1364
1365 /* Check if we have a shared waiters semaphore */
1366 if (!Resource->SharedWaiters)
1367 {
1368 /* Allocate one and try again */
1370 goto TryAcquire;
1371 }
1372
1373 /* Take control */
1374 Owner->OwnerThread = Thread;
1375 Owner->OwnerCount = 1;
1376 Resource->NumberOfSharedWaiters++;
1377
1378 /* Release the lock and return */
1380 ExpWaitForResource(Resource, Resource->SharedWaiters);
1381 return TRUE;
1382}
1383
1384/*++
1385 * @name ExConvertExclusiveToSharedLite
1386 * @implemented NT4
1387 *
1388 * The ExConvertExclusiveToSharedLite routine converts an exclusively
1389 * acquired resource into a resource that can be acquired shared.
1390 *
1391 * @param Resource
1392 * Pointer to the resource to convert.
1393 *
1394 * @return None.
1395 *
1396 * @remarks Callers of ExConvertExclusiveToSharedLite must be running at IRQL <
1397 * DISPATCH_LEVEL.
1398 *
1399 *--*/
1400VOID
1401NTAPI
1403{
1404 ULONG OldWaiters;
1406
1407 /* Sanity checks */
1411 ASSERT(Resource->OwnerEntry.OwnerThread == (ERESOURCE_THREAD)PsGetCurrentThread());
1412
1413 /* Lock the resource */
1415
1416 /* Erase the exclusive flag */
1417 Resource->Flag &= ~ResourceOwnedExclusive;
1418
1419 /* Check if we have shared waiters */
1421 {
1422 /* Make the waiters active owners */
1423 OldWaiters = Resource->NumberOfSharedWaiters;
1424 Resource->ActiveEntries += OldWaiters;
1425 Resource->NumberOfSharedWaiters = 0;
1426
1427 /* Release lock and wake the waiters */
1429 KeReleaseSemaphore(Resource->SharedWaiters, 0, OldWaiters, FALSE);
1430 }
1431 else
1432 {
1433 /* Release lock */
1435 }
1436}
1437
1438/*++
1439 * @name ExDeleteResourceLite
1440 * @implemented NT4
1441 *
1442 * The ExConvertExclusiveToSharedLite routine deletes a given resource
1443 * from the systemís resource list.
1444 *
1445 * @param Resource
1446 * Pointer to the resource to delete.
1447 *
1448 * @return STATUS_SUCCESS if the resource was deleted.
1449 *
1450 * @remarks Callers of ExDeleteResourceLite must be running at IRQL <
1451 * DISPATCH_LEVEL.
1452 *
1453 *--*/
1455NTAPI
1457{
1459
1460 /* Sanity checks */
1465
1466 /* Lock the resource */
1468
1469 /* Remove the resource */
1470 RemoveEntryList(&Resource->SystemResourcesList);
1471
1472 /* Release the lock */
1474
1475 /* Free every structure */
1476 if (Resource->OwnerTable) ExFreePoolWithTag(Resource->OwnerTable, TAG_RESOURCE_TABLE);
1477 if (Resource->SharedWaiters) ExFreePoolWithTag(Resource->SharedWaiters, TAG_RESOURCE_SEMAPHORE);
1478 if (Resource->ExclusiveWaiters) ExFreePoolWithTag(Resource->ExclusiveWaiters, TAG_RESOURCE_EVENT);
1479
1480 /* Return success */
1481 return STATUS_SUCCESS;
1482}
1483
1484/*++
1485 * @name ExDisableResourceBoostLite
1486 * @implemented NT4
1487 *
1488 * The ExDisableResourceBoostLite routine disables thread boosting for
1489 * the given resource.
1490 *
1491 * @param Resource
1492 * Pointer to the resource whose thread boosting will be disabled.
1493 *
1494 * @return None.
1495 *
1496 * @remarks None.
1497 *
1498 *--*/
1499VOID
1500NTAPI
1502{
1504
1505 /* Sanity check */
1507
1508 /* Lock the resource */
1510
1511 /* Remove the flag */
1513
1514 /* Release the lock */
1516}
1517
1518/*++
1519 * @name ExGetExclusiveWaiterCount
1520 * @implemented NT4
1521 *
1522 * The ExGetExclusiveWaiterCount routine returns the number of exclusive
1523 * waiters for the given resource.
1524 *
1525 * @param Resource
1526 * Pointer to the resource to check.
1527 *
1528 * @return The number of exclusive waiters.
1529 *
1530 * @remarks None.
1531 *
1532 *--*/
1533ULONG
1534NTAPI
1536{
1537 /* Return the count */
1538 return Resource->NumberOfExclusiveWaiters;
1539}
1540
1541/*++
1542 * @name ExGetSharedWaiterCount
1543 * @implemented NT4
1544 *
1545 * The ExGetSharedWaiterCount routine returns the number of shared
1546 * waiters for the given resource.
1547 *
1548 * @param Resource
1549 * Pointer to the resource to check.
1550 *
1551 * @return The number of shared waiters.
1552 *
1553 * @remarks None.
1554 *
1555 *--*/
1556ULONG
1557NTAPI
1559{
1560 /* Return the count */
1561 return Resource->NumberOfSharedWaiters;
1562}
1563
1564/*++
1565 * @name ExInitializeResourceLite
1566 * @implemented NT4
1567 *
1568 * The ExInitializeResourceLite routine initializes a resource variable.
1569 *
1570 * @param Resource
1571 * Pointer to the resource to check.
1572 *
1573 * @return STATUS_SUCCESS.
1574 *
1575 * @remarks The storage for ERESOURCE must not be allocated from paged pool.
1576 *
1577 * The storage must be 8-byte aligned.
1578 *
1579 *--*/
1581NTAPI
1583{
1585
1586 /* Clear the structure */
1588
1589 /* Initialize the lock */
1590 KeInitializeSpinLock(&Resource->SpinLock);
1591
1592 /* Add it into the system list */
1594 InsertTailList(&ExpSystemResourcesList, &Resource->SystemResourcesList);
1596
1597 /* Return success */
1598 return STATUS_SUCCESS;
1599}
1600
1601/*++
1602 * @name ExIsResourceAcquiredExclusiveLite
1603 * @implemented NT4
1604 *
1605 * The ExIsResourceAcquiredExclusiveLite routine returns whether the
1606 * current thread has exclusive access to a given resource.
1607 *
1608 * @param Resource
1609 * Pointer to the resource to check.
1610 *
1611 * @return TRUE if the caller already has exclusive access to the given resource.
1612 *
1613 * @remarks Callers of ExIsResourceAcquiredExclusiveLite must be running at
1614 * IRQL <= DISPATCH_LEVEL.
1615 *
1616 *--*/
1617BOOLEAN
1618NTAPI
1620{
1621 BOOLEAN IsAcquired = FALSE;
1622
1623 /* Sanity check */
1625
1626 /* Check if it's exclusively acquired */
1627 if ((IsOwnedExclusive(Resource)) &&
1628 (Resource->OwnerEntry.OwnerThread == ExGetCurrentResourceThread()))
1629 {
1630 /* It is acquired */
1631 IsAcquired = TRUE;
1632 }
1633
1634 /* Return if it's acquired */
1635 return IsAcquired;
1636}
1637
1638/*++
1639 * @name ExIsResourceAcquiredSharedLite
1640 * @implemented NT4
1641 *
1642 * The ExIsResourceAcquiredSharedLite routine returns whether the
1643 * current thread has has access (either shared or exclusive) to a
1644 * given resource.
1645 *
1646 * @param Resource
1647 * Pointer to the resource to check.
1648 *
1649 * @return Number of times the caller has acquired the given resource for
1650 * shared or exclusive access.
1651 *
1652 * @remarks Callers of ExIsResourceAcquiredExclusiveLite must be running at
1653 * IRQL <= DISPATCH_LEVEL.
1654 *
1655 *--*/
1656ULONG
1657NTAPI
1659{
1661 ULONG i, Size;
1662 ULONG Count = 0;
1665
1666 /* Sanity check */
1668
1669 /* Check if nobody owns us */
1670 if (!Resource->ActiveEntries) return 0;
1671
1672 /* Get the thread */
1674
1675 /* Check if we are in the thread list */
1676 if (Resource->OwnerEntry.OwnerThread == Thread)
1677 {
1678 /* Found it, return count */
1679 Count = Resource->OwnerEntry.OwnerCount;
1680 }
1681 else
1682 {
1683 /* We can't own an exclusive resource at this point */
1684 if (IsOwnedExclusive(Resource)) return 0;
1685
1686 /* Lock the resource */
1688
1689 /* Not in the list, do a full table look up */
1690 Owner = Resource->OwnerTable;
1691 if (Owner)
1692 {
1693 /* Get the resource index */
1694 i = ((PKTHREAD)Thread)->ResourceIndex;
1695 Size = Owner->TableSize;
1696
1697 /* Check if the index is valid and check if we don't match */
1698 if ((i >= Size) || (Owner[i].OwnerThread != Thread))
1699 {
1700 /* Sh*t! We need to do a full search */
1701 for (i = 1; i < Size; i++)
1702 {
1703 /* Move to next owner */
1704 Owner++;
1705
1706 /* Try to find a match */
1707 if (Owner->OwnerThread == Thread)
1708 {
1709 /* Finally! */
1710 Count = Owner->OwnerCount;
1711 break;
1712 }
1713 }
1714 }
1715 else
1716 {
1717 /* We found the match directlry */
1718 Count = Owner[i].OwnerCount;
1719 }
1720 }
1721
1722 /* Release the lock */
1724 }
1725
1726 /* Return count */
1727 return Count;
1728}
1729
1730/*++
1731 * @name ExReinitializeResourceLite
1732 * @implemented NT4
1733 *
1734 * The ExReinitializeResourceLite routine routine reinitializes
1735 * an existing resource variable.
1736 *
1737 * @param Resource
1738 * Pointer to the resource to be reinitialized.
1739 *
1740 * @return STATUS_SUCCESS.
1741 *
1742 * @remarks With a single call to ExReinitializeResource, a driver writer can
1743 * replace three calls: one to ExDeleteResourceLite, another to
1744 * ExAllocatePool, and a third to ExInitializeResourceLite. As
1745 * contention for a resource variable increases, memory is dynamically
1746 * allocated and attached to the resource in order to track this
1747 * contention. As an optimization, ExReinitializeResourceLite retains
1748 * and zeroes this previously allocated memory.
1749 *
1750 * Callers of ExReinitializeResourceLite must be running at
1751 * IRQL <= DISPATCH_LEVEL.
1752 *
1753 *--*/
1755NTAPI
1757{
1758 PKEVENT Event;
1759 PKSEMAPHORE Semaphore;
1760 ULONG i, Size;
1762
1763 /* Get the owner table */
1764 Owner = Resource->OwnerTable;
1765 if (Owner)
1766 {
1767 /* Get the size and loop it */
1768 Size = Owner->TableSize;
1769 for (i = 0; i < Size; i++)
1770 {
1771 /* Zero the table */
1772 Owner[i].OwnerThread = 0;
1773 Owner[i].OwnerCount = 0;
1774 }
1775 }
1776
1777 /* Zero the flags and count */
1778 Resource->Flag = 0;
1779 Resource->ActiveCount = 0;
1780 Resource->ActiveEntries = 0;
1781
1782 /* Reset the semaphore */
1783 Semaphore = Resource->SharedWaiters;
1784 if (Semaphore) KeInitializeSemaphore(Semaphore, 0, MAXLONG);
1785
1786 /* Reset the event */
1787 Event = Resource->ExclusiveWaiters;
1789
1790 /* Clear the resource data */
1791 Resource->OwnerEntry.OwnerThread = 0;
1792 Resource->OwnerEntry.OwnerCount = 0;
1793 Resource->ContentionCount = 0;
1794 Resource->NumberOfSharedWaiters = 0;
1795 Resource->NumberOfExclusiveWaiters = 0;
1796 return STATUS_SUCCESS;
1797}
1798
1799/*++
1800 * @name ExReleaseResourceLite
1801 * @implemented NT4
1802 *
1803 * The ExReleaseResourceLite routine routine releases
1804 * a specified executive resource owned by the current thread.
1805 *
1806 * @param Resource
1807 * Pointer to the resource to be released.
1808 *
1809 * @return None.
1810 *
1811 * @remarks Callers of ExReleaseResourceLite must be running at
1812 * IRQL <= DISPATCH_LEVEL.
1813 *
1814 *--*/
1815VOID
1818{
1819 /* Just call the For-Thread function */
1821}
1822
1823/*++
1824 * @name ExReleaseResourceForThreadLite
1825 * @implemented NT4
1826 *
1827 * The ExReleaseResourceForThreadLite routine routine releases
1828 * the input resource of the indicated thread.
1829 *
1830 * @param Resource
1831 * Pointer to the resource to be released.
1832 *
1833 * @param Thread
1834 * Identifies the thread that originally acquired the resource.
1835 *
1836 * @return None.
1837 *
1838 * @remarks Callers of ExReleaseResourceForThreadLite must be running at
1839 * IRQL <= DISPATCH_LEVEL.
1840 *
1841 *--*/
1842VOID
1843NTAPI
1846{
1847 ULONG i;
1848 ULONG Count;
1851 ASSERT(Thread != 0);
1852
1853 /* Get the thread and lock the resource */
1855
1856 /* Sanity checks */
1859
1860 /* Check if it's exclusively owned */
1862 {
1863 /* Decrement owner count and check if we're done */
1864 ASSERT(Resource->OwnerEntry.OwnerThread == Thread);
1865 if (--Resource->OwnerEntry.OwnerCount)
1866 {
1867 /* Done, release lock! */
1869 return;
1870 }
1871
1872 /* Clear the owner */
1873 Resource->OwnerEntry.OwnerThread = 0;
1874
1875 /* Decrement the number of active entries */
1876 ASSERT(Resource->ActiveEntries == 1);
1877 Resource->ActiveEntries--;
1878
1879 /* Check if there are shared waiters */
1881 {
1882 /* Remove the exclusive flag */
1883 Resource->Flag &= ~ResourceOwnedExclusive;
1884
1885 /* Give ownage to another thread */
1886 Count = Resource->NumberOfSharedWaiters;
1887 Resource->ActiveEntries = Count;
1888 Resource->NumberOfSharedWaiters = 0;
1889
1890 /* Release lock and let someone else have it */
1891 ASSERT(Resource->ActiveCount == 1);
1893 KeReleaseSemaphore(Resource->SharedWaiters, 0, Count, FALSE);
1894 return;
1895 }
1896 else if (IsExclusiveWaiting(Resource))
1897 {
1898 /* Give exclusive access */
1899 Resource->OwnerEntry.OwnerThread = 1;
1900 Resource->OwnerEntry.OwnerCount = 1;
1901 Resource->ActiveEntries = 1;
1902 Resource->NumberOfExclusiveWaiters--;
1903
1904 /* Release the lock and give it away */
1905 ASSERT(Resource->ActiveCount == 1);
1907 KeSetEventBoostPriority(Resource->ExclusiveWaiters,
1908 (PKTHREAD*)&Resource->OwnerEntry.OwnerThread);
1909 return;
1910 }
1911
1912 /* Remove the exclusive flag */
1913 Resource->Flag &= ~ResourceOwnedExclusive;
1914 Resource->ActiveCount = 0;
1915 }
1916 else
1917 {
1918 /* Check if we are in the thread list */
1919 if (Resource->OwnerEntry.OwnerThread == Thread)
1920 {
1921 /* Found it, get owner */
1922 Owner = &Resource->OwnerEntry;
1923 }
1924 else
1925 {
1926 /* Assume no valid index */
1927 i = 1;
1928
1929 /* If we got a valid pointer, try to get the resource index */
1930 if (!((ULONG)Thread & 3)) i = ((PKTHREAD)Thread)->ResourceIndex;
1931
1932 /* Do a table lookup */
1933 Owner = Resource->OwnerTable;
1934 ASSERT(Owner != NULL);
1935
1936 /* Check if we're out of the size and don't match */
1937 if ((i >= Owner->TableSize) || (Owner[i].OwnerThread != Thread))
1938 {
1939 /* Get the last entry */
1940 Limit = &Owner[Owner->TableSize];
1941 for (;;)
1942 {
1943 /* Move to the next entry */
1944 Owner++;
1945
1946 /* Make sure we're not out of bounds */
1947 if (Owner >= Limit)
1948 {
1949 /* Bugcheck, nobody owns us */
1950 KeBugCheckEx(RESOURCE_NOT_OWNED,
1953 (ULONG_PTR)Resource->OwnerTable,
1954 (ULONG_PTR)3);
1955 }
1956
1957 /* Check for a match */
1958 if (Owner->OwnerThread == Thread) break;
1959 }
1960 }
1961 else
1962 {
1963 /* Get the entry directly */
1964 Owner = &Owner[i];
1965 }
1966 }
1967
1968 /* Sanity checks */
1969 ASSERT(Owner->OwnerThread == Thread);
1970 ASSERT(Owner->OwnerCount > 0);
1971
1972 /* Check if we are the last owner */
1973 if (--Owner->OwnerCount)
1974 {
1975 /* There are other owners, release lock */
1977 return;
1978 }
1979
1980 /* Clear owner */
1981 Owner->OwnerThread = 0;
1982
1983 /* See if the resource isn't being owned anymore */
1984 ASSERT(Resource->ActiveEntries > 0);
1985 if (!(--Resource->ActiveEntries))
1986 {
1987 /* Check if there's an exclusive waiter */
1989 {
1990 /* Give exclusive access */
1992 Resource->OwnerEntry.OwnerThread = 1;
1993 Resource->OwnerEntry.OwnerCount = 1;
1994 Resource->ActiveEntries = 1;
1995 Resource->NumberOfExclusiveWaiters--;
1996
1997 /* Release the lock and give it away */
1998 ASSERT(Resource->ActiveCount == 1);
2000 KeSetEventBoostPriority(Resource->ExclusiveWaiters,
2001 (PKTHREAD*)&Resource->OwnerEntry.OwnerThread);
2002 return;
2003 }
2004
2005 /* Clear the active count */
2006 Resource->ActiveCount = 0;
2007 }
2008 }
2009
2010 /* Release lock */
2012}
2013
2014/*++
2015 * @name ExSetResourceOwnerPointer
2016 * @implemented NT4
2017 *
2018 * The ExSetResourceOwnerPointer routine routine sets the owner thread
2019 * thread pointer for an executive resource.
2020 *
2021 * @param Resource
2022 * Pointer to the resource whose owner to change.
2023 *
2024 * @param OwnerPointer
2025 * Pointer to an owner thread pointer of type ERESOURCE_THREAD.
2026 *
2027 * @return None.
2028 *
2029 * @remarks ExSetResourceOwnerPointer, used in conjunction with
2030 * ExReleaseResourceForThreadLite, provides a means for one thread
2031 * (acting as an resource manager thread) to acquire and release
2032 * resources for use by another thread (acting as a resource user
2033 * thread).
2034 *
2035 * After calling ExSetResourceOwnerPointer for a specific resource,
2036 * the only other routine that can be called for that resource is
2037 * ExReleaseResourceForThreadLite.
2038 *
2039 * Callers of ExSetResourceOwnerPointer must be running at
2040 * IRQL <= DISPATCH_LEVEL.
2041 *
2042 *--*/
2043VOID
2044NTAPI
2047{
2050 POWNER_ENTRY Owner, ThisOwner;
2051
2052 /* Sanity check */
2053 ASSERT((OwnerPointer != 0) && (((ULONG_PTR)OwnerPointer & 3) == 3));
2054
2055 /* Get the thread */
2057
2058 /* Sanity check */
2060
2061 /* Lock the resource */
2063
2064 /* Check if it's exclusive */
2066 {
2067 /* If it's exclusive, set the first entry no matter what */
2068 ASSERT(Resource->OwnerEntry.OwnerThread == Thread);
2069 ASSERT(Resource->OwnerEntry.OwnerCount > 0);
2070 Resource->OwnerEntry.OwnerThread = (ULONG_PTR)OwnerPointer;
2071 }
2072 else
2073 {
2074 /* Set the thread in both entries */
2075 ThisOwner = ExpFindEntryForThread(Resource,
2077 0,
2078 FALSE);
2080 if (!Owner)
2081 {
2082 /* Nobody owns it, crash */
2083 KeBugCheckEx(RESOURCE_NOT_OWNED,
2085 Thread,
2086 (ULONG_PTR)Resource->OwnerTable,
2087 3);
2088 }
2089
2090 /* Set if we are the owner */
2091 if (ThisOwner)
2092 {
2093 /* Update data */
2094 ThisOwner->OwnerCount += Owner->OwnerCount;
2095 Owner->OwnerCount = 0;
2096 Owner->OwnerThread = 0;
2097 ASSERT(Resource->ActiveEntries >= 2);
2098 Resource->ActiveEntries--;
2099 }
2100 else
2101 {
2102 /* Update the owner entry instead */
2103 Owner->OwnerThread = (ERESOURCE_THREAD)OwnerPointer;
2104 }
2105 }
2106
2107 /* Release the resource */
2109}
2110
2111/*++
2112 * @name ExTryToAcquireResourceExclusiveLite
2113 * @implemented NT4
2114 *
2115 * The ExTryToAcquireResourceExclusiveLite routine routine attemps to
2116 * acquire the given resource for exclusive access.
2117 *
2118 * @param Resource
2119 * Pointer to the resource to be acquired.
2120 *
2121 * @return TRUE if the given resource has been acquired for the caller.
2122 *
2123 * @remarks Callers of ExTryToAcquireResourceExclusiveLite must be running at
2124 * IRQL < DISPATCH_LEVEL.
2125 *
2126 *--*/
2127BOOLEAN
2128NTAPI
2130{
2133 BOOLEAN Acquired = FALSE;
2134
2135 /* Sanity check */
2136 ASSERT((Resource->Flag & ResourceNeverExclusive) == 0);
2137
2138 /* Get the thread */
2140
2141 /* Sanity check and validation */
2144
2145 /* Acquire the lock */
2147
2148 /* Check if there is an owner */
2149 if (!Resource->ActiveCount)
2150 {
2151 /* No owner, give exclusive access */
2153 Resource->OwnerEntry.OwnerThread = Thread;
2154 Resource->OwnerEntry.OwnerCount = 1;
2155 Resource->ActiveCount = 1;
2156 Resource->ActiveEntries = 1;
2157 Acquired = TRUE;
2158 }
2159 else if ((IsOwnedExclusive(Resource)) &&
2160 (Resource->OwnerEntry.OwnerThread == Thread))
2161 {
2162 /* Do a recursive acquire */
2163 Resource->OwnerEntry.OwnerCount++;
2164 Acquired = TRUE;
2165 }
2166
2167 /* Release the resource */
2169 return Acquired;
2170}
2171
2172/*++
2173 * @name ExEnterCriticalRegionAndAcquireResourceExclusive
2174 * @implemented NT5.1
2175 *
2176 * The ExEnterCriticalRegionAndAcquireResourceExclusive enters a critical
2177 * region and then exclusively acquires a resource.
2178 *
2179 * @param Resource
2180 * Pointer to the resource to acquire.
2181 *
2182 * @return Pointer to the Win32K thread pointer of the current thread.
2183 *
2184 * @remarks See ExAcquireResourceExclusiveLite.
2185 *
2186 *--*/
2187PVOID
2188NTAPI
2190{
2191 /* Enter critical region */
2193
2194 /* Acquire the resource */
2196
2197 /* Return the Win32 Thread */
2198 return KeGetCurrentThread()->Win32Thread;
2199}
2200
2201/*++
2202 * @name ExEnterCriticalRegionAndAcquireResourceShared
2203 * @implemented NT5.2
2204 *
2205 * The ExEnterCriticalRegionAndAcquireResourceShared routine
2206 * enters a critical region and then acquires a resource shared.
2207 *
2208 * @param Resource
2209 * Pointer to the resource to acquire.
2210 *
2211 * @return Pointer to the Win32K thread pointer of the current thread.
2212 *
2213 * @remarks See ExAcquireResourceSharedLite.
2214 *
2215 *--*/
2216PVOID
2217NTAPI
2219{
2220 /* Enter critical region */
2222
2223 /* Acquire the resource */
2225
2226 /* Return the Win32 Thread */
2227 return KeGetCurrentThread()->Win32Thread;
2228}
2229
2230/*++
2231 * @name ExEnterCriticalRegionAndAcquireSharedWaitForExclusive
2232 * @implemented NT5.2
2233 *
2234 * The ExEnterCriticalRegionAndAcquireSharedWaitForExclusive routine
2235 * enters a critical region and then acquires a resource shared if
2236 * shared access can be granted and there are no exclusive waiters.
2237 * It then acquires the resource exclusively.
2238 *
2239 * @param Resource
2240 * Pointer to the resource to acquire.
2241 *
2242 * @return Pointer to the Win32K thread pointer of the current thread.
2243 *
2244 * @remarks See ExAcquireSharedWaitForExclusive.
2245 *
2246 *--*/
2247PVOID
2248NTAPI
2250{
2251 /* Enter critical region */
2253
2254 /* Acquire the resource */
2256
2257 /* Return the Win32 Thread */
2258 return KeGetCurrentThread()->Win32Thread;
2259}
2260
2261/*++
2262 * @name ExReleaseResourceAndLeaveCriticalRegion
2263 * @implemented NT5.1
2264 *
2265 * The ExReleaseResourceAndLeaveCriticalRegion release a resource and
2266 * then leaves a critical region.
2267 *
2268 * @param Resource
2269 * Pointer to the resource to release.
2270 *
2271 * @return None
2272 *
2273 * @remarks See ExReleaseResourceLite.
2274 *
2275 *--*/
2276VOID
2279{
2280 /* Release the resource */
2282
2283 /* Leave critical region */
2285}
unsigned char BOOLEAN
static VOID NTAPI SystemThread(_In_ PVOID Context)
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
_Acquires_exclusive_lock_ Resource _Acquires_shared_lock_ Resource _Inout_ PERESOURCE Resource
Definition: cdprocs.h:843
_Out_ PKIRQL Irql
Definition: csq.h:179
#define ResourceOwnedExclusive
Definition: dldetect.h:32
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
BOOLEAN NTAPI KeIsExecutingDpc(VOID)
Definition: dpc.c:947
#define ULONG_PTR
Definition: config.h:101
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define ExReleaseResourceForThreadLite(res, thrdID)
Definition: env_spec_w32.h:635
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define ExGetCurrentResourceThread()
Definition: env_spec_w32.h:633
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define ExConvertExclusiveToSharedLite(res)
Definition: env_spec_w32.h:652
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
ERESOURCE * PERESOURCE
Definition: env_spec_w32.h:595
#define ExDeleteResourceLite(res)
Definition: env_spec_w32.h:647
#define NonPagedPool
Definition: env_spec_w32.h:307
ULONG ERESOURCE
Definition: env_spec_w32.h:594
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeDelayExecutionThread(mode, foo, t)
Definition: env_spec_w32.h:484
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
@ Success
Definition: eventcreate.c:712
VOID NTAPI KeSetEventBoostPriority(IN PKEVENT Event, IN PKTHREAD *WaitingThread OPTIONAL)
Definition: eventobj.c:229
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
Status
Definition: gdiplustypes.h:25
ASMGENDATA Table[]
Definition: genincdata.c:61
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
VOID FASTCALL KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:130
VOID FASTCALL KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:166
#define KeGetCurrentThread
Definition: hal.h:55
NTSYSAPI void WINAPI DbgBreakPoint(void)
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
void __cdecl _disable(void)
Definition: intrin_arm.h:365
void __cdecl _enable(void)
Definition: intrin_arm.h:373
static CODE_SEG("PAGE")
Definition: isapnp.c:1482
FORCEINLINE VOID KiReleaseDispatcherLock(IN KIRQL OldIrql)
Definition: ke_x.h:157
FORCEINLINE VOID KiAcquireThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:240
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
FORCEINLINE VOID KiReleaseThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:250
FORCEINLINE KIRQL KiAcquireDispatcherLock(VOID)
Definition: ke_x.h:149
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define KernelMode
Definition: asm.h:34
#define ResourceHasDisabledPriorityBoost
Definition: extypes.h:169
@ SemaphoreObject
Definition: ketypes.h:444
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ SaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ OwnerSize PSID Owner
Definition: rtlfuncs.h:1597
int Count
Definition: noreturn.cpp:7
struct _KTHREAD * PKTHREAD
Definition: nt_native.h:28
#define FASTCALL
Definition: nt_native.h:50
#define Int32x32To64(a, b)
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
@ SynchronizationEvent
FORCEINLINE VOID ExReleaseResourceLock(IN PERESOURCE Resource, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: resource.c:37
BOOLEAN ExResourceStrict
Definition: resource.c:77
VOID NTAPI ExSetResourceOwnerPointer(IN PERESOURCE Resource, IN PVOID OwnerPointer)
Definition: resource.c:2045
VOID NTAPI ExpExpandResourceOwnerTable(IN PERESOURCE Resource, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: resource.c:316
KSPIN_LOCK ExpResourceSpinLock
Definition: resource.c:75
#define ExpCheckForApcsDisabled(b, r, t)
Definition: resource.c:151
VOID NTAPI ExpResourceInitialization(VOID)
Definition: resource.c:169
LARGE_INTEGER ExpTimeout
Definition: resource.c:73
NTSTATUS NTAPI ExInitializeResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1582
BOOLEAN NTAPI ExAcquireSharedWaitForExclusive(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:1217
VOID NTAPI ExDisableResourceBoostLite(IN PERESOURCE Resource)
Definition: resource.c:1501
NTSTATUS NTAPI ExReinitializeResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1756
VOID NTAPI ExpAllocateExclusiveWaiterEvent(IN PERESOURCE Resource, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: resource.c:196
#define ExpVerifyResource(r)
Definition: resource.c:150
FORCEINLINE VOID ExAcquireResourceLock(IN PERESOURCE Resource, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: resource.c:25
PVOID NTAPI ExEnterCriticalRegionAndAcquireSharedWaitForExclusive(IN PERESOURCE Resource)
Definition: resource.c:2249
BOOLEAN NTAPI ExTryToAcquireResourceExclusiveLite(IN PERESOURCE Resource)
Definition: resource.c:2129
VOID NTAPI ExpAllocateSharedWaiterSemaphore(IN PERESOURCE Resource, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: resource.c:256
BOOLEAN NTAPI ExAcquireSharedStarveExclusive(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:1063
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
BOOLEAN NTAPI ExIsResourceAcquiredExclusiveLite(IN PERESOURCE Resource)
Definition: resource.c:1619
#define IsSharedWaiting(r)
Definition: resource.c:17
LIST_ENTRY ExpSystemResourcesList
Definition: resource.c:76
ULONG ExpResourceTimeoutCount
Definition: resource.c:74
ULONG NTAPI ExIsResourceAcquiredSharedLite(IN PERESOURCE Resource)
Definition: resource.c:1658
#define IsExclusiveWaiting(r)
Definition: resource.c:16
#define IsBoostAllowed(r)
Definition: resource.c:19
PVOID NTAPI ExEnterCriticalRegionAndAcquireResourceShared(IN PERESOURCE Resource)
Definition: resource.c:2218
VOID FASTCALL ExpBoostOwnerThread(IN PKTHREAD Thread, IN PKTHREAD OwnerThread)
Definition: resource.c:572
ULONG NTAPI ExGetSharedWaiterCount(IN PERESOURCE Resource)
Definition: resource.c:1558
ULONG NTAPI ExGetExclusiveWaiterCount(IN PERESOURCE Resource)
Definition: resource.c:1535
POWNER_ENTRY FASTCALL ExpFindEntryForThread(IN PERESOURCE Resource, IN ERESOURCE_THREAD Thread, IN PKLOCK_QUEUE_HANDLE LockHandle, IN BOOLEAN FirstEntryInelligible)
Definition: resource.c:479
PVOID NTAPI ExEnterCriticalRegionAndAcquireResourceExclusive(IN PERESOURCE Resource)
Definition: resource.c:2189
VOID FASTCALL ExReleaseResourceAndLeaveCriticalRegion(IN PERESOURCE Resource)
Definition: resource.c:2278
#define IsOwnedExclusive(r)
Definition: resource.c:18
POWNER_ENTRY FASTCALL ExpFindFreeEntry(IN PERESOURCE Resource, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: resource.c:416
LARGE_INTEGER ExShortTime
Definition: resource.c:72
VOID FASTCALL ExpWaitForResource(IN PERESOURCE Resource, IN PVOID Object)
Definition: resource.c:618
VOID FASTCALL KiSetPriorityThread(IN PKTHREAD Thread, IN KPRIORITY Priority)
Definition: thrdschd.c:511
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
static ULONG Timeout
Definition: ping.c:61
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
VOID NTAPI KeInitializeSemaphore(IN PKSEMAPHORE Semaphore, IN LONG Count, IN LONG Limit)
Definition: semphobj.c:22
LONG NTAPI KeReleaseSemaphore(IN PKSEMAPHORE Semaphore, IN KPRIORITY Increment, IN LONG Adjustment, IN BOOLEAN Wait)
Definition: semphobj.c:54
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: typedefs.h:120
Definition: extypes.h:210
ULONG OwnerCount
Definition: extypes.h:216
#define TAG_RESOURCE_TABLE
Definition: tag.h:23
#define TAG_RESOURCE_EVENT
Definition: tag.h:24
#define TAG_RESOURCE_SEMAPHORE
Definition: tag.h:25
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define MAXLONG
Definition: umtypes.h:116
LONGLONG QuadPart
Definition: typedefs.h:114
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
#define FORCEINLINE
Definition: wdftypes.h:67
_In_ PVOID OwnerPointer
Definition: exfuncs.h:1070
#define ResourceNeverExclusive
Definition: extypes.h:245
ULONG_PTR ERESOURCE_THREAD
Definition: extypes.h:208
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
*LockHandle LockHandle _Out_ PKLOCK_QUEUE_HANDLE LockHandle
Definition: kefuncs.h:731
_In_ LONG _In_ LONG Limit
Definition: kefuncs.h:318
@ WrResource
Definition: ketypes.h:430
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3287
unsigned char UCHAR
Definition: xmlstorage.h:181