3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ex/resource.c
6 * PURPOSE: Resource synchronization construct
14 * Usage of ERESOURCE members is not documented.
15 * From names of members and functionnalities, we can assume :
17 * OwnerTable = list of threads who have shared access(if more than one)
18 * ActiveCount = number of threads who have access to the resource
19 * Flag = bits : ResourceOwnedExclusive=0x80
20 * ResourceNeverExclusive=0x10
21 * ResourceReleaseByOtherThread=0x20
22 * ResourceDisableBoost=0x08
23 * SharedWaiters = semaphore, used to manage wait list of shared waiters.
24 * ExclusiveWaiters = event, used to manage wait list of exclusive waiters.
25 * OwnerThreads[0]= thread who have exclusive access
26 * OwnerThreads[1]= if only one thread own the resource
27 * thread who have shared access
30 * and TableSize = number of entries in the owner table
31 * NumberOfExclusiveWaiters = number of threads waiting for exclusive access.
32 * NumberOfSharedWaiters = number of threads waiting for exclusive access.
36 #define ResourceOwnedExclusive 0x80
37 #define ResourceDisableBoost 0x08
39 /* INCLUDES *****************************************************************/
43 #include <internal/debug.h>
45 /* GLOBALS *******************************************************************/
47 #define TAG_OWNER_TABLE TAG('R', 'O', 'W', 'N')
48 #define TAG_EXCLUSIVE_LOCK TAG('E', 'R', 'E', 'L')
49 #define TAG_SHARED_SEM TAG('E', 'R', 'S', 'S')
51 /* FUNCTIONS *****************************************************************/
56 ExTryToAcquireResourceExclusiveLite (
60 * FUNCTION: Attempts to require the resource for exclusive access
62 * Resource = Points to the resource of be acquired
63 * RETURNS: TRUE if the resource was acquired for the caller
64 * NOTES: Must be acquired at IRQL < DISPATCH_LEVEL
67 return(ExAcquireResourceExclusiveLite(Resource
,FALSE
));
70 #ifdef ExAcquireResourceExclusive
71 #undef ExAcquireResourceExclusive
79 ExAcquireResourceExclusive (
84 return(ExAcquireResourceExclusiveLite(Resource
,Wait
));
93 ExAcquireResourceExclusiveLite (
98 * FUNCTION: Acquires a resource exclusively for the calling thread
100 * Resource = Points to the resource to acquire
101 * Wait = Is set to TRUE if the caller should wait to acquire the
102 * resource if it can't be acquired immediately
103 * RETURNS: TRUE if the resource was acquired,
105 * NOTES: Must be called at IRQL < DISPATCH_LEVEL
110 DPRINT("ExAcquireResourceExclusiveLite(Resource %x, Wait %d)\n",
113 ASSERT_IRQL_LESS(DISPATCH_LEVEL
);
115 /* undefed for now, since cdfs must be fixed first */
117 /* At least regular kmode APC's must be disabled
118 * Note that this requirement is missing in old DDK's */
119 ASSERT(KeGetCurrentThread() == NULL
|| /* <-Early in the boot process the current thread is obseved to be NULL */
120 KeGetCurrentThread()->KernelApcDisable
||
121 KeGetCurrentIrql() == APC_LEVEL
);
124 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
126 /* resource already locked */
127 if((Resource
->Flag
& ResourceOwnedExclusive
)
128 && Resource
->OwnerThreads
[0].OwnerThread
== ExGetCurrentResourceThread())
130 /* it's ok : same lock for same thread */
131 Resource
->OwnerThreads
[0].OwnerCount
++;
132 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
133 DPRINT("ExAcquireResourceExclusiveLite() = TRUE\n");
137 if (Resource
->ActiveCount
&& !Wait
)
139 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
140 DPRINT("ExAcquireResourceExclusiveLite() = FALSE\n");
145 * This is slightly better than it looks because other exclusive
146 * threads who are waiting won't be woken up but there is a race
147 * with new threads trying to grab the resource so we must have
148 * the spinlock, still normally this loop will only be executed
150 * NOTE: We might want to set a timeout to detect deadlock
153 while (Resource
->ActiveCount
)
155 Resource
->NumberOfExclusiveWaiters
++;
156 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
157 KeWaitForSingleObject(Resource
->ExclusiveWaiters
,
162 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
163 Resource
->NumberOfExclusiveWaiters
--;
165 Resource
->Flag
|= ResourceOwnedExclusive
;
166 Resource
->ActiveCount
= 1;
167 Resource
->OwnerThreads
[0].OwnerThread
= ExGetCurrentResourceThread();
168 Resource
->OwnerThreads
[0].OwnerCount
= 1;
169 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
170 DPRINT("ExAcquireResourceExclusiveLite() = TRUE\n");
174 static BOOLEAN
EiRemoveSharedOwner(PERESOURCE Resource
,
175 ERESOURCE_THREAD ResourceThreadId
)
177 * FUNCTION: Removes the current thread from the shared owners of the resource
179 * Resource = Pointer to the resource for which the thread is to be
181 * NOTE: Must be called with the resource spinlock held
186 if (Resource
->OwnerThreads
[1].OwnerThread
== ResourceThreadId
)
188 Resource
->OwnerThreads
[1].OwnerCount
--;
189 if (Resource
->OwnerThreads
[1].OwnerCount
== 0)
191 Resource
->ActiveCount
--;
192 Resource
->OwnerThreads
[1].OwnerThread
= 0;
197 if (Resource
->OwnerThreads
[1].OwnerThread
)
199 /* Oh dear, the caller didn't own the resource after all */
203 for (i
=0; i
<Resource
->OwnerThreads
[1].TableSize
; i
++)
205 if (Resource
->OwnerTable
[i
].OwnerThread
== ResourceThreadId
)
207 Resource
->OwnerTable
[i
].OwnerCount
--;
208 if (Resource
->OwnerTable
[i
].OwnerCount
== 0)
210 Resource
->ActiveCount
--;
211 Resource
->OwnerTable
[i
].OwnerThread
= 0;
219 static BOOLEAN
EiAddSharedOwner(PERESOURCE Resource
)
221 * FUNCTION: Adds the current thread to the shared owners of the resource
223 * Resource = Pointer to the resource for which the thread is to be
225 * NOTE: Must be called with the resource spinlock held
228 ERESOURCE_THREAD CurrentThread
= ExGetCurrentResourceThread();
229 POWNER_ENTRY freeEntry
;
232 DPRINT("EiAddSharedOwner(Resource %x)\n", Resource
);
234 if (Resource
->ActiveCount
== 0)
236 /* no owner, it's easy */
237 Resource
->OwnerThreads
[1].OwnerThread
= ExGetCurrentResourceThread();
238 Resource
->OwnerThreads
[1].OwnerCount
= 1;
239 if (Resource
->OwnerTable
!= NULL
)
241 ExFreePool(Resource
->OwnerTable
);
243 Resource
->OwnerTable
= NULL
;
244 Resource
->ActiveCount
= 1;
245 DPRINT("EiAddSharedOwner() = TRUE\n");
250 * now, we must search if this thread has already acquired this resource
251 * then increase ownercount if found, else create new entry or reuse free
254 if (Resource
->OwnerTable
== NULL
)
256 DPRINT("Creating owner table\n");
258 /* allocate ownertable,memset to 0, initialize first entry */
259 Resource
->OwnerTable
=
260 ExAllocatePoolWithTag(NonPagedPool
, sizeof(OWNER_ENTRY
)*3,
262 if (Resource
->OwnerTable
== NULL
)
267 memset(Resource
->OwnerTable
,0,sizeof(OWNER_ENTRY
)*3);
268 memcpy(&Resource
->OwnerTable
[0], &Resource
->OwnerThreads
[1],
269 sizeof(OWNER_ENTRY
));
271 Resource
->OwnerThreads
[1].OwnerThread
= 0;
272 Resource
->OwnerThreads
[1].TableSize
= 3;
274 Resource
->OwnerTable
[1].OwnerThread
= CurrentThread
;
275 Resource
->OwnerTable
[1].OwnerCount
= 1;
276 Resource
->ActiveCount
++;
281 DPRINT("Search free entries\n");
283 DPRINT("Number of entries %d\n",
284 Resource
->OwnerThreads
[1].TableSize
);
287 for (i
=0; i
<Resource
->OwnerThreads
[1].TableSize
; i
++)
289 if (Resource
->OwnerTable
[i
].OwnerThread
== CurrentThread
)
291 DPRINT("Thread already owns resource\n");
292 Resource
->OwnerTable
[i
].OwnerCount
++;
295 if (Resource
->OwnerTable
[i
].OwnerThread
== 0)
297 freeEntry
= &Resource
->OwnerTable
[i
];
302 DPRINT("Found free entry %x\n", freeEntry
);
306 DPRINT("Allocating new entry\n");
308 /* reallocate ownertable with one more entry */
310 ExAllocatePoolWithTag(NonPagedPool
,
312 (Resource
->OwnerThreads
[1].TableSize
+1),
314 if (freeEntry
== NULL
)
319 memcpy(freeEntry
,Resource
->OwnerTable
,
320 sizeof(OWNER_ENTRY
)*(Resource
->OwnerThreads
[1].TableSize
));
321 ExFreePool(Resource
->OwnerTable
);
322 Resource
->OwnerTable
=freeEntry
;
323 freeEntry
=&Resource
->OwnerTable
[Resource
->OwnerThreads
[1].TableSize
];
324 Resource
->OwnerThreads
[1].TableSize
++;
326 DPRINT("Creating entry\n");
327 freeEntry
->OwnerThread
=ExGetCurrentResourceThread();
328 freeEntry
->OwnerCount
=1;
329 Resource
->ActiveCount
++;
338 ExAcquireResourceSharedLite (
343 * FUNCTION: Acquires the given resource for shared access by the calling
346 * Resource = Points to the resource to acquire
347 * Wait = Is set to TRUE if the caller should be put into wait state
348 * until the resource can be acquired if it cannot be acquired
350 * RETURNS: TRUE, if the resource is acquire
356 DPRINT("ExAcquireResourceSharedLite(Resource %x, Wait %d)\n",
359 ASSERT_IRQL_LESS(DISPATCH_LEVEL
);
361 /* undefed for now, since cdfs must be fixed first */
363 /* At least regular kmode APC's must be disabled
364 * Note that this requirement is missing in old DDK's
366 ASSERT(KeGetCurrentThread() == NULL
|| /* <-Early in the boot process the current thread is obseved to be NULL */
367 KeGetCurrentThread()->KernelApcDisable
||
368 KeGetCurrentIrql() == APC_LEVEL
);
371 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
373 /* first, resolve trivial cases */
374 if (Resource
->ActiveCount
== 0)
376 EiAddSharedOwner(Resource
);
377 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
378 DPRINT("ExAcquireResourceSharedLite() = TRUE\n");
382 if ((Resource
->Flag
& ResourceOwnedExclusive
)
383 && Resource
->OwnerThreads
[0].OwnerThread
==ExGetCurrentResourceThread())
385 /* exclusive, but by same thread : it's ok */
387 * NOTE: Is this correct? Seems the same as ExConvertExclusiveToShared
389 Resource
->OwnerThreads
[0].OwnerCount
++;
390 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
391 DPRINT("ExAcquireResourceSharedLite() = TRUE\n");
395 if ((Resource
->Flag
& ResourceOwnedExclusive
)
396 || Resource
->NumberOfExclusiveWaiters
)
398 /* exclusive by another thread , or thread waiting for exclusive */
401 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
402 DPRINT("ExAcquireResourceSharedLite() = FALSE\n");
407 Resource
->NumberOfSharedWaiters
++;
410 /* wait for the semaphore */
411 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
412 KeWaitForSingleObject(Resource
->SharedWaiters
,0, KernelMode
, FALSE
, NULL
);
413 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
414 /* the spin lock was released we must check again */
416 while ((Resource
->Flag
& ResourceOwnedExclusive
)
417 || Resource
->NumberOfExclusiveWaiters
);
418 Resource
->NumberOfSharedWaiters
--;
422 EiAddSharedOwner(Resource
);
423 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
424 DPRINT("ExAcquireResourceSharedLite() = TRUE\n");
433 ExConvertExclusiveToSharedLite (
437 * FUNCTION: Converts a given resource from acquired for exclusive access
438 * to acquire for shared access
440 * Resource = Points to the resource for which the access should be
442 * NOTES: Caller must be running at IRQL < DISPATCH_LEVEL
448 DPRINT("ExConvertExclusiveToSharedLite(Resource %x)\n", Resource
);
450 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
452 oldWaiters
= Resource
->NumberOfSharedWaiters
;
454 if (!(Resource
->Flag
& ResourceOwnedExclusive
))
456 /* Might not be what the caller expects, better bug check */
458 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
462 //transfer infos from entry 0 to entry 1 and erase entry 0
463 Resource
->OwnerThreads
[1].OwnerThread
=Resource
->OwnerThreads
[0].OwnerThread
;
464 Resource
->OwnerThreads
[1].OwnerCount
=Resource
->OwnerThreads
[0].OwnerCount
;
465 Resource
->OwnerThreads
[0].OwnerThread
=0;
466 Resource
->OwnerThreads
[0].OwnerCount
=0;
467 /* erase exclusive flag */
468 Resource
->Flag
&= (~ResourceOwnedExclusive
);
469 /* if no shared waiters, that's all */
472 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
475 /* else, awake the waiters */
476 KeReleaseSemaphore(Resource
->SharedWaiters
,0,oldWaiters
,0);
477 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
478 DPRINT("ExConvertExclusiveToSharedLite() finished\n");
486 ExDisableResourceBoostLite (
490 Resource
->Flag
|= ResourceDisableBoost
;
498 ExGetExclusiveWaiterCount (
502 return(Resource
->NumberOfExclusiveWaiters
);
510 ExAcquireSharedStarveExclusive (
515 * FUNCTION: Acquires a given resource for shared access without waiting
516 * for any pending attempts to acquire exclusive access to the
519 * Resource = Points to the resource to be acquired for shared access
520 * Wait = Is set to TRUE if the caller will wait until the resource
521 * becomes available when access can't be granted immediately
522 * RETURNS: TRUE if the requested access is granted. The routine returns
523 * FALSE if the input Wait is FALSE and shared access can't be
524 * granted immediately
529 DPRINT("ExAcquireSharedStarveExclusive(Resource %x, Wait %d)\n",
532 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
534 /* no owner, it's easy */
535 if (Resource
->ActiveCount
== 0)
537 Resource
->OwnerThreads
[1].OwnerThread
=ExGetCurrentResourceThread();
538 Resource
->OwnerThreads
[1].OwnerCount
=1;
539 Resource
->ActiveCount
=1;
540 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
541 DPRINT("ExAcquireSharedStarveExclusive() = TRUE\n");
545 if ((Resource
->Flag
& ResourceOwnedExclusive
)
546 && Resource
->OwnerThreads
[0].OwnerThread
==ExGetCurrentResourceThread())
548 /* exclusive, but by same thread : it's ok */
549 Resource
->OwnerThreads
[0].OwnerCount
++;
550 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
551 DPRINT("ExAcquireSharedStarveExclusive() = TRUE\n");
555 if (Resource
->Flag
& ResourceOwnedExclusive
)
557 /* exclusive by another thread */
560 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
561 DPRINT("ExAcquireSharedStarveExclusive() = FALSE\n");
566 Resource
->NumberOfSharedWaiters
++;
567 /* wait for the semaphore */
568 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
569 KeWaitForSingleObject(Resource
->SharedWaiters
,0,0,0,0);
570 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
571 Resource
->NumberOfSharedWaiters
--;
574 EiAddSharedOwner(Resource
);
575 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
576 DPRINT("ExAcquireSharedStarveExclusive() = TRUE\n");
585 ExAcquireSharedWaitForExclusive (
590 return(ExAcquireResourceSharedLite(Resource
,Wait
));
594 #ifdef ExDeleteResource
595 #undef ExDeleteResource
608 return(ExDeleteResourceLite(Resource
));
616 ExDeleteResourceLite (
620 DPRINT("ExDeleteResourceLite(Resource %x)\n", Resource
);
621 if (Resource
->OwnerTable
) ExFreePool(Resource
->OwnerTable
);
622 if (Resource
->SharedWaiters
) ExFreePool(Resource
->SharedWaiters
);
623 if (Resource
->ExclusiveWaiters
) ExFreePool(Resource
->ExclusiveWaiters
);
624 return(STATUS_SUCCESS
);;
632 ExGetSharedWaiterCount (
636 return(Resource
->NumberOfSharedWaiters
);
640 #ifdef ExInitializeResource
641 #undef ExInitializeResource
649 ExInitializeResource (
653 return(ExInitializeResourceLite(Resource
));
660 ExInitializeResourceLite (PERESOURCE Resource
)
662 DPRINT("ExInitializeResourceLite(Resource %x)\n", Resource
);
663 memset(Resource
,0,sizeof(ERESOURCE
));
664 Resource
->NumberOfSharedWaiters
= 0;
665 Resource
->NumberOfExclusiveWaiters
= 0;
666 KeInitializeSpinLock(&Resource
->SpinLock
);
668 Resource
->ExclusiveWaiters
=
669 ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_EXCLUSIVE_LOCK
);
670 KeInitializeEvent(Resource
->ExclusiveWaiters
,
671 SynchronizationEvent
,
673 Resource
->SharedWaiters
=
674 ExAllocatePoolWithTag(NonPagedPool
,sizeof(KSEMAPHORE
), TAG_SHARED_SEM
);
675 KeInitializeSemaphore(Resource
->SharedWaiters
,0,0x7fffffff);
676 Resource
->ActiveCount
= 0;
685 ExIsResourceAcquiredExclusiveLite (
689 * FUNCTION: Returns whether the current thread has exclusive access to
692 * Resource = Points to the resource to be queried
693 * RETURNS: TRUE if the caller has exclusive access to the resource,
697 return((Resource
->Flag
& ResourceOwnedExclusive
)
698 && Resource
->OwnerThreads
[0].OwnerThread
==ExGetCurrentResourceThread());
703 #ifdef ExIsResourceAcquiredSharedLite
704 #undef ExIsResourceAcquiredSharedLite
716 ExIsResourceAcquiredSharedLite(
717 IN PERESOURCE Resource
)
719 * FUNCTION: Returns whether the current thread has shared access to a given
722 * Resource = Points to the resource to be queried
723 * RETURNS: The number of times the caller has acquired shared access to the
728 if (Resource
->OwnerThreads
[0].OwnerThread
== ExGetCurrentResourceThread())
730 return (USHORT
)(Resource
->OwnerThreads
[0].OwnerCount
);
732 if (Resource
->OwnerThreads
[1].OwnerThread
== ExGetCurrentResourceThread())
734 return (USHORT
)(Resource
->OwnerThreads
[1].OwnerCount
);
736 if (!Resource
->OwnerThreads
[1].TableSize
)
740 for (i
=0; i
<Resource
->OwnerThreads
[1].TableSize
; i
++)
742 if (Resource
->OwnerTable
[i
].OwnerThread
==ExGetCurrentResourceThread())
744 return (USHORT
)Resource
->OwnerTable
[i
].OwnerCount
;
755 ExReinitializeResourceLite (
759 Resource
->NumberOfSharedWaiters
= 0;
760 Resource
->NumberOfExclusiveWaiters
= 0;
761 KeInitializeSpinLock(&Resource
->SpinLock
);
763 KeInitializeEvent(Resource
->ExclusiveWaiters
,SynchronizationEvent
,
765 KeInitializeSemaphore(Resource
->SharedWaiters
,0,0x7fffffff);
766 Resource
->ActiveCount
= 0;
767 if (Resource
->OwnerTable
)
769 ExFreePool(Resource
->OwnerTable
);
771 Resource
->OwnerThreads
[0].OwnerThread
=0;
772 Resource
->OwnerThreads
[0].OwnerCount
=0;
773 Resource
->OwnerThreads
[1].OwnerThread
=0;
774 Resource
->OwnerThreads
[1].OwnerCount
=0;
782 ExReleaseResourceLite (
786 ExReleaseResourceForThreadLite(Resource
,
787 ExGetCurrentResourceThread());
792 #ifdef ExReleaseResourceForThread
793 #undef ExReleaseResourceForThread
802 ExReleaseResourceForThread (
804 ERESOURCE_THREAD ResourceThreadId
807 ExReleaseResourceForThreadLite(Resource
,ResourceThreadId
);
816 ExReleaseResourceForThreadLite (
818 ERESOURCE_THREAD ResourceThreadId
821 * FUNCTION: Releases a resource for the given thread
823 * Resource = Points to the release to release
824 * ResourceThreadId = Identifies the thread that originally acquired
826 * NOTES: Must be running at IRQL < DISPATCH_LEVEL
827 * BUG: We don't support starving exclusive waiters
832 DPRINT("ExReleaseResourceForThreadLite(Resource %x, ResourceThreadId %x)\n",
833 Resource
, ResourceThreadId
);
835 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
837 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
839 if (Resource
->Flag
& ResourceOwnedExclusive
)
841 DPRINT("Releasing from exclusive access\n");
843 Resource
->OwnerThreads
[0].OwnerCount
--;
844 if (Resource
->OwnerThreads
[0].OwnerCount
> 0)
846 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
847 DPRINT("ExReleaseResourceForThreadLite() finished\n");
851 Resource
->OwnerThreads
[0].OwnerThread
= 0;
852 Resource
->ActiveCount
--;
853 Resource
->Flag
&=(~ResourceOwnedExclusive
);
854 ASSERT(Resource
->ActiveCount
== 0);
855 DPRINT("Resource->NumberOfExclusiveWaiters %d\n",
856 Resource
->NumberOfExclusiveWaiters
);
857 if (Resource
->NumberOfExclusiveWaiters
)
859 /* get resource to first exclusive waiter */
860 KeSetEvent(Resource
->ExclusiveWaiters
,
863 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
864 DPRINT("ExReleaseResourceForThreadLite() finished\n");
867 DPRINT("Resource->NumberOfSharedWaiters %d\n",
868 Resource
->NumberOfSharedWaiters
);
869 if (Resource
->NumberOfSharedWaiters
)
871 DPRINT("Releasing semaphore\n");
872 KeReleaseSemaphore(Resource
->SharedWaiters
,
874 Resource
->NumberOfSharedWaiters
,
877 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
878 DPRINT("ExReleaseResourceForThreadLite() finished\n");
882 EiRemoveSharedOwner(Resource
, ResourceThreadId
);
884 if (Resource
->ActiveCount
== 0)
886 if (Resource
->NumberOfExclusiveWaiters
)
888 /* get resource to first exclusive waiter */
889 KeSetEvent(Resource
->ExclusiveWaiters
,
895 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
896 DPRINT("ExReleaseResourceForThreadLite() finished\n");
905 ExSetResourceOwnerPointer (
906 IN PERESOURCE Resource
,
907 IN PVOID OwnerPointer
910 PKTHREAD CurrentThread
;
912 POWNER_ENTRY OwnerEntry
;
914 CurrentThread
= KeGetCurrentThread();
916 /* Lock the resource */
917 KeAcquireSpinLock(&Resource
->SpinLock
, &OldIrql
);
919 /* Check if it's exclusive */
920 if (Resource
->Flag
& ResourceOwnedExclusive
) {
922 /* If it's exclusive, set the first entry no matter what */
923 Resource
->OwnerThreads
[0].OwnerThread
= (ULONG_PTR
)OwnerPointer
;
927 /* Check both entries and see which one matches the current thread */
928 if (Resource
->OwnerThreads
[0].OwnerThread
== (ULONG_PTR
)CurrentThread
) {
930 Resource
->OwnerThreads
[0].OwnerThread
= (ULONG_PTR
)OwnerPointer
;
932 } else if (Resource
->OwnerThreads
[1].OwnerThread
== (ULONG_PTR
)CurrentThread
) {
934 Resource
->OwnerThreads
[1].OwnerThread
= (ULONG_PTR
)OwnerPointer
;
936 } else { /* None of the entries match, so we need to do a lookup */
938 /* Get the first Entry */
939 OwnerEntry
= Resource
->OwnerTable
;
941 /* Check if the Current Thread is in the Resource Table Entry */
942 if ((CurrentThread
->ResourceIndex
>= OwnerEntry
->TableSize
) ||
943 (OwnerEntry
[CurrentThread
->ResourceIndex
].OwnerThread
!= (ULONG_PTR
)CurrentThread
)) {
945 /* Loop until we find the current thread in an entry */
946 for (;OwnerEntry
->OwnerThread
== (ULONG_PTR
)CurrentThread
;OwnerEntry
++);
950 /* It's in the current RTE, so set it */
951 OwnerEntry
= &OwnerEntry
[CurrentThread
->ResourceIndex
];
954 /* Now that we went to the right entry, set the Owner Pointer */
955 OwnerEntry
->OwnerThread
= (ULONG_PTR
)OwnerPointer
;
959 /* Release the resource */
960 KeReleaseSpinLock(&Resource
->SpinLock
, OldIrql
);