3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ex/resource.c
6 * PURPOSE: Resource synchronization construct
8 * PROGRAMMERS: No programmer listed.
13 * Usage of ERESOURCE members is not documented.
14 * From names of members and functionnalities, we can assume :
16 * OwnerTable = list of threads who have shared access(if more than one)
17 * ActiveCount = number of threads who have access to the resource
18 * Flag = bits : ResourceOwnedExclusive=0x80
19 * ResourceNeverExclusive=0x10
20 * ResourceReleaseByOtherThread=0x20
21 * ResourceDisableBoost=0x08
22 * SharedWaiters = semaphore, used to manage wait list of shared waiters.
23 * ExclusiveWaiters = event, used to manage wait list of exclusive waiters.
24 * OwnerThreads[0]= thread who have exclusive access
25 * OwnerThreads[1]= if only one thread own the resource
26 * thread who have shared access
29 * and TableSize = number of entries in the owner table
30 * NumberOfExclusiveWaiters = number of threads waiting for exclusive access.
31 * NumberOfSharedWaiters = number of threads waiting for exclusive access.
35 #define ResourceOwnedExclusive 0x80
36 #define ResourceDisableBoost 0x08
38 /* INCLUDES *****************************************************************/
42 #include <internal/debug.h>
44 /* GLOBALS *******************************************************************/
46 #define TAG_OWNER_TABLE TAG('R', 'O', 'W', 'N')
47 #define TAG_EXCLUSIVE_LOCK TAG('E', 'R', 'E', 'L')
48 #define TAG_SHARED_SEM TAG('E', 'R', 'S', 'S')
50 /* FUNCTIONS *****************************************************************/
55 ExTryToAcquireResourceExclusiveLite (
59 * FUNCTION: Attempts to require the resource for exclusive access
61 * Resource = Points to the resource of be acquired
62 * RETURNS: TRUE if the resource was acquired for the caller
63 * NOTES: Must be acquired at IRQL < DISPATCH_LEVEL
66 return(ExAcquireResourceExclusiveLite(Resource
,FALSE
));
69 #ifdef ExAcquireResourceExclusive
70 #undef ExAcquireResourceExclusive
78 ExAcquireResourceExclusive (
83 return(ExAcquireResourceExclusiveLite(Resource
,Wait
));
92 ExAcquireResourceExclusiveLite (
97 * FUNCTION: Acquires a resource exclusively for the calling thread
99 * Resource = Points to the resource to acquire
100 * Wait = Is set to TRUE if the caller should wait to acquire the
101 * resource if it can't be acquired immediately
102 * RETURNS: TRUE if the resource was acquired,
104 * NOTES: Must be called at IRQL < DISPATCH_LEVEL
109 DPRINT("ExAcquireResourceExclusiveLite(Resource %x, Wait %d)\n",
112 ASSERT_IRQL_LESS(DISPATCH_LEVEL
);
114 /* undefed for now, since cdfs must be fixed first */
116 /* At least regular kmode APC's must be disabled
117 * Note that this requirement is missing in old DDK's */
118 ASSERT(KeGetCurrentThread() == NULL
|| /* <-Early in the boot process the current thread is obseved to be NULL */
119 KeGetCurrentThread()->KernelApcDisable
||
120 KeGetCurrentIrql() == APC_LEVEL
);
123 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
125 /* resource already locked */
126 if((Resource
->Flag
& ResourceOwnedExclusive
)
127 && Resource
->OwnerThreads
[0].OwnerThread
== ExGetCurrentResourceThread())
129 /* it's ok : same lock for same thread */
130 Resource
->OwnerThreads
[0].OwnerCount
++;
131 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
132 DPRINT("ExAcquireResourceExclusiveLite() = TRUE\n");
136 if (Resource
->ActiveCount
&& !Wait
)
138 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
139 DPRINT("ExAcquireResourceExclusiveLite() = FALSE\n");
144 * This is slightly better than it looks because other exclusive
145 * threads who are waiting won't be woken up but there is a race
146 * with new threads trying to grab the resource so we must have
147 * the spinlock, still normally this loop will only be executed
149 * NOTE: We might want to set a timeout to detect deadlock
152 while (Resource
->ActiveCount
)
154 Resource
->NumberOfExclusiveWaiters
++;
155 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
156 KeWaitForSingleObject(Resource
->ExclusiveWaiters
,
161 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
162 Resource
->NumberOfExclusiveWaiters
--;
164 Resource
->Flag
|= ResourceOwnedExclusive
;
165 Resource
->ActiveCount
= 1;
166 Resource
->OwnerThreads
[0].OwnerThread
= ExGetCurrentResourceThread();
167 Resource
->OwnerThreads
[0].OwnerCount
= 1;
168 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
169 DPRINT("ExAcquireResourceExclusiveLite() = TRUE\n");
173 static BOOLEAN
EiRemoveSharedOwner(PERESOURCE Resource
,
174 ERESOURCE_THREAD ResourceThreadId
)
176 * FUNCTION: Removes the current thread from the shared owners of the resource
178 * Resource = Pointer to the resource for which the thread is to be
180 * NOTE: Must be called with the resource spinlock held
185 if (Resource
->OwnerThreads
[1].OwnerThread
== ResourceThreadId
)
187 Resource
->OwnerThreads
[1].OwnerCount
--;
188 if (Resource
->OwnerThreads
[1].OwnerCount
== 0)
190 Resource
->ActiveCount
--;
191 Resource
->OwnerThreads
[1].OwnerThread
= 0;
196 if (Resource
->OwnerThreads
[1].OwnerThread
)
198 /* Oh dear, the caller didn't own the resource after all */
202 for (i
=0; i
<Resource
->OwnerThreads
[1].TableSize
; i
++)
204 if (Resource
->OwnerTable
[i
].OwnerThread
== ResourceThreadId
)
206 Resource
->OwnerTable
[i
].OwnerCount
--;
207 if (Resource
->OwnerTable
[i
].OwnerCount
== 0)
209 Resource
->ActiveCount
--;
210 Resource
->OwnerTable
[i
].OwnerThread
= 0;
218 static BOOLEAN
EiAddSharedOwner(PERESOURCE Resource
)
220 * FUNCTION: Adds the current thread to the shared owners of the resource
222 * Resource = Pointer to the resource for which the thread is to be
224 * NOTE: Must be called with the resource spinlock held
227 ERESOURCE_THREAD CurrentThread
= ExGetCurrentResourceThread();
228 POWNER_ENTRY freeEntry
;
231 DPRINT("EiAddSharedOwner(Resource %x)\n", Resource
);
233 if (Resource
->ActiveCount
== 0)
235 /* no owner, it's easy */
236 Resource
->OwnerThreads
[1].OwnerThread
= ExGetCurrentResourceThread();
237 Resource
->OwnerThreads
[1].OwnerCount
= 1;
238 if (Resource
->OwnerTable
!= NULL
)
240 ExFreePool(Resource
->OwnerTable
);
242 Resource
->OwnerTable
= NULL
;
243 Resource
->ActiveCount
= 1;
244 DPRINT("EiAddSharedOwner() = TRUE\n");
249 * now, we must search if this thread has already acquired this resource
250 * then increase ownercount if found, else create new entry or reuse free
253 if (Resource
->OwnerTable
== NULL
)
255 DPRINT("Creating owner table\n");
257 /* allocate ownertable,memset to 0, initialize first entry */
258 Resource
->OwnerTable
=
259 ExAllocatePoolWithTag(NonPagedPool
, sizeof(OWNER_ENTRY
)*3,
261 if (Resource
->OwnerTable
== NULL
)
266 memset(Resource
->OwnerTable
,0,sizeof(OWNER_ENTRY
)*3);
267 memcpy(&Resource
->OwnerTable
[0], &Resource
->OwnerThreads
[1],
268 sizeof(OWNER_ENTRY
));
270 Resource
->OwnerThreads
[1].OwnerThread
= 0;
271 Resource
->OwnerThreads
[1].TableSize
= 3;
273 Resource
->OwnerTable
[1].OwnerThread
= CurrentThread
;
274 Resource
->OwnerTable
[1].OwnerCount
= 1;
275 Resource
->ActiveCount
++;
280 DPRINT("Search free entries\n");
282 DPRINT("Number of entries %d\n",
283 Resource
->OwnerThreads
[1].TableSize
);
286 for (i
=0; i
<Resource
->OwnerThreads
[1].TableSize
; i
++)
288 if (Resource
->OwnerTable
[i
].OwnerThread
== CurrentThread
)
290 DPRINT("Thread already owns resource\n");
291 Resource
->OwnerTable
[i
].OwnerCount
++;
294 if (Resource
->OwnerTable
[i
].OwnerThread
== 0)
296 freeEntry
= &Resource
->OwnerTable
[i
];
301 DPRINT("Found free entry %x\n", freeEntry
);
305 DPRINT("Allocating new entry\n");
307 /* reallocate ownertable with one more entry */
309 ExAllocatePoolWithTag(NonPagedPool
,
311 (Resource
->OwnerThreads
[1].TableSize
+1),
313 if (freeEntry
== NULL
)
318 memcpy(freeEntry
,Resource
->OwnerTable
,
319 sizeof(OWNER_ENTRY
)*(Resource
->OwnerThreads
[1].TableSize
));
320 ExFreePool(Resource
->OwnerTable
);
321 Resource
->OwnerTable
=freeEntry
;
322 freeEntry
=&Resource
->OwnerTable
[Resource
->OwnerThreads
[1].TableSize
];
323 Resource
->OwnerThreads
[1].TableSize
++;
325 DPRINT("Creating entry\n");
326 freeEntry
->OwnerThread
=ExGetCurrentResourceThread();
327 freeEntry
->OwnerCount
=1;
328 Resource
->ActiveCount
++;
337 ExAcquireResourceSharedLite (
342 * FUNCTION: Acquires the given resource for shared access by the calling
345 * Resource = Points to the resource to acquire
346 * Wait = Is set to TRUE if the caller should be put into wait state
347 * until the resource can be acquired if it cannot be acquired
349 * RETURNS: TRUE, if the resource is acquire
355 DPRINT("ExAcquireResourceSharedLite(Resource %x, Wait %d)\n",
358 ASSERT_IRQL_LESS(DISPATCH_LEVEL
);
360 /* undefed for now, since cdfs must be fixed first */
362 /* At least regular kmode APC's must be disabled
363 * Note that this requirement is missing in old DDK's
365 ASSERT(KeGetCurrentThread() == NULL
|| /* <-Early in the boot process the current thread is obseved to be NULL */
366 KeGetCurrentThread()->KernelApcDisable
||
367 KeGetCurrentIrql() == APC_LEVEL
);
370 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
372 /* first, resolve trivial cases */
373 if (Resource
->ActiveCount
== 0)
375 EiAddSharedOwner(Resource
);
376 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
377 DPRINT("ExAcquireResourceSharedLite() = TRUE\n");
381 if ((Resource
->Flag
& ResourceOwnedExclusive
)
382 && Resource
->OwnerThreads
[0].OwnerThread
==ExGetCurrentResourceThread())
384 /* exclusive, but by same thread : it's ok */
386 * NOTE: Is this correct? Seems the same as ExConvertExclusiveToShared
388 Resource
->OwnerThreads
[0].OwnerCount
++;
389 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
390 DPRINT("ExAcquireResourceSharedLite() = TRUE\n");
394 if ((Resource
->Flag
& ResourceOwnedExclusive
)
395 || Resource
->NumberOfExclusiveWaiters
)
397 /* exclusive by another thread , or thread waiting for exclusive */
400 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
401 DPRINT("ExAcquireResourceSharedLite() = FALSE\n");
406 Resource
->NumberOfSharedWaiters
++;
409 /* wait for the semaphore */
410 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
411 KeWaitForSingleObject(Resource
->SharedWaiters
,0, KernelMode
, FALSE
, NULL
);
412 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
413 /* the spin lock was released we must check again */
415 while ((Resource
->Flag
& ResourceOwnedExclusive
)
416 || Resource
->NumberOfExclusiveWaiters
);
417 Resource
->NumberOfSharedWaiters
--;
421 EiAddSharedOwner(Resource
);
422 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
423 DPRINT("ExAcquireResourceSharedLite() = TRUE\n");
432 ExConvertExclusiveToSharedLite (
436 * FUNCTION: Converts a given resource from acquired for exclusive access
437 * to acquire for shared access
439 * Resource = Points to the resource for which the access should be
441 * NOTES: Caller must be running at IRQL < DISPATCH_LEVEL
447 DPRINT("ExConvertExclusiveToSharedLite(Resource %x)\n", Resource
);
449 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
451 oldWaiters
= Resource
->NumberOfSharedWaiters
;
453 if (!(Resource
->Flag
& ResourceOwnedExclusive
))
455 /* Might not be what the caller expects, better bug check */
457 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
461 //transfer infos from entry 0 to entry 1 and erase entry 0
462 Resource
->OwnerThreads
[1].OwnerThread
=Resource
->OwnerThreads
[0].OwnerThread
;
463 Resource
->OwnerThreads
[1].OwnerCount
=Resource
->OwnerThreads
[0].OwnerCount
;
464 Resource
->OwnerThreads
[0].OwnerThread
=0;
465 Resource
->OwnerThreads
[0].OwnerCount
=0;
466 /* erase exclusive flag */
467 Resource
->Flag
&= (~ResourceOwnedExclusive
);
468 /* if no shared waiters, that's all */
471 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
474 /* else, awake the waiters */
475 KeReleaseSemaphore(Resource
->SharedWaiters
,0,oldWaiters
,0);
476 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
477 DPRINT("ExConvertExclusiveToSharedLite() finished\n");
485 ExDisableResourceBoostLite (
489 Resource
->Flag
|= ResourceDisableBoost
;
497 ExGetExclusiveWaiterCount (
501 return(Resource
->NumberOfExclusiveWaiters
);
509 ExAcquireSharedStarveExclusive (
514 * FUNCTION: Acquires a given resource for shared access without waiting
515 * for any pending attempts to acquire exclusive access to the
518 * Resource = Points to the resource to be acquired for shared access
519 * Wait = Is set to TRUE if the caller will wait until the resource
520 * becomes available when access can't be granted immediately
521 * RETURNS: TRUE if the requested access is granted. The routine returns
522 * FALSE if the input Wait is FALSE and shared access can't be
523 * granted immediately
528 DPRINT("ExAcquireSharedStarveExclusive(Resource %x, Wait %d)\n",
531 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
533 /* no owner, it's easy */
534 if (Resource
->ActiveCount
== 0)
536 Resource
->OwnerThreads
[1].OwnerThread
=ExGetCurrentResourceThread();
537 Resource
->OwnerThreads
[1].OwnerCount
=1;
538 Resource
->ActiveCount
=1;
539 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
540 DPRINT("ExAcquireSharedStarveExclusive() = TRUE\n");
544 if ((Resource
->Flag
& ResourceOwnedExclusive
)
545 && Resource
->OwnerThreads
[0].OwnerThread
==ExGetCurrentResourceThread())
547 /* exclusive, but by same thread : it's ok */
548 Resource
->OwnerThreads
[0].OwnerCount
++;
549 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
550 DPRINT("ExAcquireSharedStarveExclusive() = TRUE\n");
554 if (Resource
->Flag
& ResourceOwnedExclusive
)
556 /* exclusive by another thread */
559 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
560 DPRINT("ExAcquireSharedStarveExclusive() = FALSE\n");
565 Resource
->NumberOfSharedWaiters
++;
566 /* wait for the semaphore */
567 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
568 KeWaitForSingleObject(Resource
->SharedWaiters
,0,0,0,0);
569 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
570 Resource
->NumberOfSharedWaiters
--;
573 EiAddSharedOwner(Resource
);
574 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
575 DPRINT("ExAcquireSharedStarveExclusive() = TRUE\n");
584 ExAcquireSharedWaitForExclusive (
589 return(ExAcquireResourceSharedLite(Resource
,Wait
));
593 #ifdef ExDeleteResource
594 #undef ExDeleteResource
607 return(ExDeleteResourceLite(Resource
));
615 ExDeleteResourceLite (
619 DPRINT("ExDeleteResourceLite(Resource %x)\n", Resource
);
620 if (Resource
->OwnerTable
) ExFreePool(Resource
->OwnerTable
);
621 if (Resource
->SharedWaiters
) ExFreePool(Resource
->SharedWaiters
);
622 if (Resource
->ExclusiveWaiters
) ExFreePool(Resource
->ExclusiveWaiters
);
623 return(STATUS_SUCCESS
);
631 ExGetSharedWaiterCount (
635 return(Resource
->NumberOfSharedWaiters
);
639 #ifdef ExInitializeResource
640 #undef ExInitializeResource
648 ExInitializeResource (
652 return(ExInitializeResourceLite(Resource
));
659 ExInitializeResourceLite (PERESOURCE Resource
)
661 DPRINT("ExInitializeResourceLite(Resource %x)\n", Resource
);
662 memset(Resource
,0,sizeof(ERESOURCE
));
663 Resource
->NumberOfSharedWaiters
= 0;
664 Resource
->NumberOfExclusiveWaiters
= 0;
665 KeInitializeSpinLock(&Resource
->SpinLock
);
667 Resource
->ExclusiveWaiters
=
668 ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_EXCLUSIVE_LOCK
);
669 KeInitializeEvent(Resource
->ExclusiveWaiters
,
670 SynchronizationEvent
,
672 Resource
->SharedWaiters
=
673 ExAllocatePoolWithTag(NonPagedPool
,sizeof(KSEMAPHORE
), TAG_SHARED_SEM
);
674 KeInitializeSemaphore(Resource
->SharedWaiters
,0,0x7fffffff);
675 Resource
->ActiveCount
= 0;
684 ExIsResourceAcquiredExclusiveLite (
688 * FUNCTION: Returns whether the current thread has exclusive access to
691 * Resource = Points to the resource to be queried
692 * RETURNS: TRUE if the caller has exclusive access to the resource,
696 return((Resource
->Flag
& ResourceOwnedExclusive
)
697 && Resource
->OwnerThreads
[0].OwnerThread
==ExGetCurrentResourceThread());
702 #ifdef ExIsResourceAcquiredSharedLite
703 #undef ExIsResourceAcquiredSharedLite
715 ExIsResourceAcquiredSharedLite(
716 IN PERESOURCE Resource
)
718 * FUNCTION: Returns whether the current thread has shared access to a given
721 * Resource = Points to the resource to be queried
722 * RETURNS: The number of times the caller has acquired shared access to the
727 if (Resource
->OwnerThreads
[0].OwnerThread
== ExGetCurrentResourceThread())
729 return (USHORT
)(Resource
->OwnerThreads
[0].OwnerCount
);
731 if (Resource
->OwnerThreads
[1].OwnerThread
== ExGetCurrentResourceThread())
733 return (USHORT
)(Resource
->OwnerThreads
[1].OwnerCount
);
735 if (!Resource
->OwnerThreads
[1].TableSize
)
739 for (i
=0; i
<Resource
->OwnerThreads
[1].TableSize
; i
++)
741 if (Resource
->OwnerTable
[i
].OwnerThread
==ExGetCurrentResourceThread())
743 return (USHORT
)Resource
->OwnerTable
[i
].OwnerCount
;
754 ExReinitializeResourceLite (
758 Resource
->NumberOfSharedWaiters
= 0;
759 Resource
->NumberOfExclusiveWaiters
= 0;
760 KeInitializeSpinLock(&Resource
->SpinLock
);
762 KeInitializeEvent(Resource
->ExclusiveWaiters
,SynchronizationEvent
,
764 KeInitializeSemaphore(Resource
->SharedWaiters
,0,0x7fffffff);
765 Resource
->ActiveCount
= 0;
766 if (Resource
->OwnerTable
)
768 ExFreePool(Resource
->OwnerTable
);
770 Resource
->OwnerThreads
[0].OwnerThread
=0;
771 Resource
->OwnerThreads
[0].OwnerCount
=0;
772 Resource
->OwnerThreads
[1].OwnerThread
=0;
773 Resource
->OwnerThreads
[1].OwnerCount
=0;
781 ExReleaseResourceLite (
785 ExReleaseResourceForThreadLite(Resource
,
786 ExGetCurrentResourceThread());
791 #ifdef ExReleaseResourceForThread
792 #undef ExReleaseResourceForThread
801 ExReleaseResourceForThread (
803 ERESOURCE_THREAD ResourceThreadId
806 ExReleaseResourceForThreadLite(Resource
,ResourceThreadId
);
815 ExReleaseResourceForThreadLite (
817 ERESOURCE_THREAD ResourceThreadId
820 * FUNCTION: Releases a resource for the given thread
822 * Resource = Points to the release to release
823 * ResourceThreadId = Identifies the thread that originally acquired
825 * NOTES: Must be running at IRQL < DISPATCH_LEVEL
826 * BUG: We don't support starving exclusive waiters
831 DPRINT("ExReleaseResourceForThreadLite(Resource %x, ResourceThreadId %x)\n",
832 Resource
, ResourceThreadId
);
834 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
836 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
838 if (Resource
->Flag
& ResourceOwnedExclusive
)
840 DPRINT("Releasing from exclusive access\n");
842 Resource
->OwnerThreads
[0].OwnerCount
--;
843 if (Resource
->OwnerThreads
[0].OwnerCount
> 0)
845 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
846 DPRINT("ExReleaseResourceForThreadLite() finished\n");
850 Resource
->OwnerThreads
[0].OwnerThread
= 0;
851 Resource
->ActiveCount
--;
852 Resource
->Flag
&=(~ResourceOwnedExclusive
);
853 ASSERT(Resource
->ActiveCount
== 0);
854 DPRINT("Resource->NumberOfExclusiveWaiters %d\n",
855 Resource
->NumberOfExclusiveWaiters
);
856 if (Resource
->NumberOfExclusiveWaiters
)
858 /* get resource to first exclusive waiter */
859 KeSetEvent(Resource
->ExclusiveWaiters
,
862 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
863 DPRINT("ExReleaseResourceForThreadLite() finished\n");
866 DPRINT("Resource->NumberOfSharedWaiters %d\n",
867 Resource
->NumberOfSharedWaiters
);
868 if (Resource
->NumberOfSharedWaiters
)
870 DPRINT("Releasing semaphore\n");
871 KeReleaseSemaphore(Resource
->SharedWaiters
,
873 Resource
->NumberOfSharedWaiters
,
876 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
877 DPRINT("ExReleaseResourceForThreadLite() finished\n");
881 EiRemoveSharedOwner(Resource
, ResourceThreadId
);
883 if (Resource
->ActiveCount
== 0)
885 if (Resource
->NumberOfExclusiveWaiters
)
887 /* get resource to first exclusive waiter */
888 KeSetEvent(Resource
->ExclusiveWaiters
,
894 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
895 DPRINT("ExReleaseResourceForThreadLite() finished\n");
904 ExSetResourceOwnerPointer (
905 IN PERESOURCE Resource
,
906 IN PVOID OwnerPointer
909 PKTHREAD CurrentThread
;
911 POWNER_ENTRY OwnerEntry
;
913 CurrentThread
= KeGetCurrentThread();
915 /* Lock the resource */
916 KeAcquireSpinLock(&Resource
->SpinLock
, &OldIrql
);
918 /* Check if it's exclusive */
919 if (Resource
->Flag
& ResourceOwnedExclusive
) {
921 /* If it's exclusive, set the first entry no matter what */
922 Resource
->OwnerThreads
[0].OwnerThread
= (ULONG_PTR
)OwnerPointer
;
926 /* Check both entries and see which one matches the current thread */
927 if (Resource
->OwnerThreads
[0].OwnerThread
== (ULONG_PTR
)CurrentThread
) {
929 Resource
->OwnerThreads
[0].OwnerThread
= (ULONG_PTR
)OwnerPointer
;
931 } else if (Resource
->OwnerThreads
[1].OwnerThread
== (ULONG_PTR
)CurrentThread
) {
933 Resource
->OwnerThreads
[1].OwnerThread
= (ULONG_PTR
)OwnerPointer
;
935 } else { /* None of the entries match, so we need to do a lookup */
937 /* Get the first Entry */
938 OwnerEntry
= Resource
->OwnerTable
;
940 /* Check if the Current Thread is in the Resource Table Entry */
941 if ((CurrentThread
->ResourceIndex
>= OwnerEntry
->TableSize
) ||
942 (OwnerEntry
[CurrentThread
->ResourceIndex
].OwnerThread
!= (ULONG_PTR
)CurrentThread
)) {
944 /* Loop until we find the current thread in an entry */
945 for (;OwnerEntry
->OwnerThread
== (ULONG_PTR
)CurrentThread
;OwnerEntry
++);
949 /* It's in the current RTE, so set it */
950 OwnerEntry
= &OwnerEntry
[CurrentThread
->ResourceIndex
];
953 /* Now that we went to the right entry, set the Owner Pointer */
954 OwnerEntry
->OwnerThread
= (ULONG_PTR
)OwnerPointer
;
958 /* Release the resource */
959 KeReleaseSpinLock(&Resource
->SpinLock
, OldIrql
);