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 ResourceDisableBoost 0x08
37 /* INCLUDES *****************************************************************/
41 #include <internal/debug.h>
43 /* FUNCTIONS *****************************************************************/
48 ExTryToAcquireResourceExclusiveLite (
52 * FUNCTION: Attempts to require the resource for exclusive access
54 * Resource = Points to the resource of be acquired
55 * RETURNS: TRUE if the resource was acquired for the caller
56 * NOTES: Must be acquired at IRQL < DISPATCH_LEVEL
59 return(ExAcquireResourceExclusiveLite(Resource
,FALSE
));
62 #ifdef ExAcquireResourceExclusive
63 #undef ExAcquireResourceExclusive
71 ExAcquireResourceExclusive (
76 return(ExAcquireResourceExclusiveLite(Resource
,Wait
));
85 ExAcquireResourceExclusiveLite (
90 * FUNCTION: Acquires a resource exclusively for the calling thread
92 * Resource = Points to the resource to acquire
93 * Wait = Is set to TRUE if the caller should wait to acquire the
94 * resource if it can't be acquired immediately
95 * RETURNS: TRUE if the resource was acquired,
97 * NOTES: Must be called at IRQL < DISPATCH_LEVEL
102 DPRINT("ExAcquireResourceExclusiveLite(Resource 0x%p, Wait %d)\n",
105 ASSERT_IRQL_LESS(DISPATCH_LEVEL
);
107 /* undefed for now, since cdfs must be fixed first */
109 /* At least regular kmode APC's must be disabled
110 * Note that this requirement is missing in old DDK's */
111 ASSERT(KeGetCurrentThread() == NULL
|| /* <-Early in the boot process the current thread is obseved to be NULL */
112 KeGetCurrentThread()->KernelApcDisable
||
113 KeGetCurrentIrql() == APC_LEVEL
);
116 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
118 /* resource already locked */
119 if((Resource
->Flag
& ResourceOwnedExclusive
)
120 && Resource
->OwnerThreads
[0].OwnerThread
== ExGetCurrentResourceThread())
122 /* it's ok : same lock for same thread */
123 Resource
->OwnerThreads
[0].OwnerCount
++;
124 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
125 DPRINT("ExAcquireResourceExclusiveLite() = TRUE\n");
129 if (Resource
->ActiveCount
&& !Wait
)
131 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
132 DPRINT("ExAcquireResourceExclusiveLite() = FALSE\n");
137 * This is slightly better than it looks because other exclusive
138 * threads who are waiting won't be woken up but there is a race
139 * with new threads trying to grab the resource so we must have
140 * the spinlock, still normally this loop will only be executed
142 * NOTE: We might want to set a timeout to detect deadlock
145 while (Resource
->ActiveCount
)
147 Resource
->NumberOfExclusiveWaiters
++;
148 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
149 KeWaitForSingleObject(Resource
->ExclusiveWaiters
,
154 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
155 Resource
->NumberOfExclusiveWaiters
--;
157 Resource
->Flag
|= ResourceOwnedExclusive
;
158 Resource
->ActiveCount
= 1;
159 Resource
->OwnerThreads
[0].OwnerThread
= ExGetCurrentResourceThread();
160 Resource
->OwnerThreads
[0].OwnerCount
= 1;
161 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
162 DPRINT("ExAcquireResourceExclusiveLite() = TRUE\n");
166 static BOOLEAN
EiRemoveSharedOwner(PERESOURCE Resource
,
167 ERESOURCE_THREAD ResourceThreadId
)
169 * FUNCTION: Removes the current thread from the shared owners of the resource
171 * Resource = Pointer to the resource for which the thread is to be
173 * NOTE: Must be called with the resource spinlock held
178 if (Resource
->OwnerThreads
[1].OwnerThread
== ResourceThreadId
)
180 Resource
->OwnerThreads
[1].OwnerCount
--;
181 if (Resource
->OwnerThreads
[1].OwnerCount
== 0)
183 Resource
->ActiveCount
--;
184 Resource
->OwnerThreads
[1].OwnerThread
= 0;
189 if (Resource
->OwnerThreads
[1].OwnerThread
)
191 /* Oh dear, the caller didn't own the resource after all */
195 for (i
=0; i
<Resource
->OwnerThreads
[1].TableSize
; i
++)
197 if (Resource
->OwnerTable
[i
].OwnerThread
== ResourceThreadId
)
199 Resource
->OwnerTable
[i
].OwnerCount
--;
200 if (Resource
->OwnerTable
[i
].OwnerCount
== 0)
202 Resource
->ActiveCount
--;
203 Resource
->OwnerTable
[i
].OwnerThread
= 0;
211 static BOOLEAN
EiAddSharedOwner(PERESOURCE Resource
)
213 * FUNCTION: Adds the current thread to the shared owners of the resource
215 * Resource = Pointer to the resource for which the thread is to be
217 * NOTE: Must be called with the resource spinlock held
220 ERESOURCE_THREAD CurrentThread
= ExGetCurrentResourceThread();
221 POWNER_ENTRY freeEntry
;
224 DPRINT("EiAddSharedOwner(Resource 0x%p)\n", Resource
);
226 if (Resource
->ActiveCount
== 0)
228 /* no owner, it's easy */
229 Resource
->OwnerThreads
[1].OwnerThread
= ExGetCurrentResourceThread();
230 Resource
->OwnerThreads
[1].OwnerCount
= 1;
231 if (Resource
->OwnerTable
!= NULL
)
233 ExFreePool(Resource
->OwnerTable
);
235 Resource
->OwnerTable
= NULL
;
236 Resource
->ActiveCount
= 1;
237 DPRINT("EiAddSharedOwner() = TRUE\n");
242 * now, we must search if this thread has already acquired this resource
243 * then increase ownercount if found, else create new entry or reuse free
246 if (Resource
->OwnerTable
== NULL
)
248 DPRINT("Creating owner table\n");
250 /* allocate ownertable,memset to 0, initialize first entry */
251 Resource
->OwnerTable
=
252 ExAllocatePoolWithTag(NonPagedPool
, sizeof(OWNER_ENTRY
)*3,
254 if (Resource
->OwnerTable
== NULL
)
259 memset(Resource
->OwnerTable
,0,sizeof(OWNER_ENTRY
)*3);
260 memcpy(&Resource
->OwnerTable
[0], &Resource
->OwnerThreads
[1],
261 sizeof(OWNER_ENTRY
));
263 Resource
->OwnerThreads
[1].OwnerThread
= 0;
264 Resource
->OwnerThreads
[1].TableSize
= 3;
266 Resource
->OwnerTable
[1].OwnerThread
= CurrentThread
;
267 Resource
->OwnerTable
[1].OwnerCount
= 1;
268 Resource
->ActiveCount
++;
273 DPRINT("Search free entries\n");
275 DPRINT("Number of entries %d\n",
276 Resource
->OwnerThreads
[1].TableSize
);
279 for (i
=0; i
<Resource
->OwnerThreads
[1].TableSize
; i
++)
281 if (Resource
->OwnerTable
[i
].OwnerThread
== CurrentThread
)
283 DPRINT("Thread already owns resource\n");
284 Resource
->OwnerTable
[i
].OwnerCount
++;
287 if (Resource
->OwnerTable
[i
].OwnerThread
== 0)
289 freeEntry
= &Resource
->OwnerTable
[i
];
294 DPRINT("Found free entry 0x%p\n", freeEntry
);
298 DPRINT("Allocating new entry\n");
300 /* reallocate ownertable with one more entry */
302 ExAllocatePoolWithTag(NonPagedPool
,
304 (Resource
->OwnerThreads
[1].TableSize
+1),
306 if (freeEntry
== NULL
)
311 memcpy(freeEntry
,Resource
->OwnerTable
,
312 sizeof(OWNER_ENTRY
)*(Resource
->OwnerThreads
[1].TableSize
));
313 ExFreePool(Resource
->OwnerTable
);
314 Resource
->OwnerTable
=freeEntry
;
315 freeEntry
=&Resource
->OwnerTable
[Resource
->OwnerThreads
[1].TableSize
];
316 Resource
->OwnerThreads
[1].TableSize
++;
318 DPRINT("Creating entry\n");
319 freeEntry
->OwnerThread
=ExGetCurrentResourceThread();
320 freeEntry
->OwnerCount
=1;
321 Resource
->ActiveCount
++;
330 ExAcquireResourceSharedLite (
335 * FUNCTION: Acquires the given resource for shared access by the calling
338 * Resource = Points to the resource to acquire
339 * Wait = Is set to TRUE if the caller should be put into wait state
340 * until the resource can be acquired if it cannot be acquired
342 * RETURNS: TRUE, if the resource is acquire
348 DPRINT("ExAcquireResourceSharedLite(Resource 0x%p, Wait %d)\n",
351 ASSERT_IRQL_LESS(DISPATCH_LEVEL
);
353 /* undefed for now, since cdfs must be fixed first */
355 /* At least regular kmode APC's must be disabled
356 * Note that this requirement is missing in old DDK's
358 ASSERT(KeGetCurrentThread() == NULL
|| /* <-Early in the boot process the current thread is obseved to be NULL */
359 KeGetCurrentThread()->KernelApcDisable
||
360 KeGetCurrentIrql() == APC_LEVEL
);
363 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
365 /* first, resolve trivial cases */
366 if (Resource
->ActiveCount
== 0)
368 EiAddSharedOwner(Resource
);
369 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
370 DPRINT("ExAcquireResourceSharedLite() = TRUE\n");
374 if ((Resource
->Flag
& ResourceOwnedExclusive
)
375 && Resource
->OwnerThreads
[0].OwnerThread
==ExGetCurrentResourceThread())
377 /* exclusive, but by same thread : it's ok */
379 * NOTE: Is this correct? Seems the same as ExConvertExclusiveToShared
381 Resource
->OwnerThreads
[0].OwnerCount
++;
382 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
383 DPRINT("ExAcquireResourceSharedLite() = TRUE\n");
387 if ((Resource
->Flag
& ResourceOwnedExclusive
)
388 || Resource
->NumberOfExclusiveWaiters
)
390 /* exclusive by another thread , or thread waiting for exclusive */
393 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
394 DPRINT("ExAcquireResourceSharedLite() = FALSE\n");
399 Resource
->NumberOfSharedWaiters
++;
402 /* wait for the semaphore */
403 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
404 KeWaitForSingleObject(Resource
->SharedWaiters
,0, KernelMode
, FALSE
, NULL
);
405 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
406 /* the spin lock was released we must check again */
408 while ((Resource
->Flag
& ResourceOwnedExclusive
)
409 || Resource
->NumberOfExclusiveWaiters
);
410 Resource
->NumberOfSharedWaiters
--;
414 EiAddSharedOwner(Resource
);
415 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
416 DPRINT("ExAcquireResourceSharedLite() = TRUE\n");
425 ExConvertExclusiveToSharedLite (
429 * FUNCTION: Converts a given resource from acquired for exclusive access
430 * to acquire for shared access
432 * Resource = Points to the resource for which the access should be
434 * NOTES: Caller must be running at IRQL < DISPATCH_LEVEL
440 DPRINT("ExConvertExclusiveToSharedLite(Resource 0x%p)\n", Resource
);
442 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
444 oldWaiters
= Resource
->NumberOfSharedWaiters
;
446 if (!(Resource
->Flag
& ResourceOwnedExclusive
))
448 /* Might not be what the caller expects, better bug check */
450 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
454 //transfer infos from entry 0 to entry 1 and erase entry 0
455 Resource
->OwnerThreads
[1].OwnerThread
=Resource
->OwnerThreads
[0].OwnerThread
;
456 Resource
->OwnerThreads
[1].OwnerCount
=Resource
->OwnerThreads
[0].OwnerCount
;
457 Resource
->OwnerThreads
[0].OwnerThread
=0;
458 Resource
->OwnerThreads
[0].OwnerCount
=0;
459 /* erase exclusive flag */
460 Resource
->Flag
&= (~ResourceOwnedExclusive
);
461 /* if no shared waiters, that's all */
464 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
467 /* else, awake the waiters */
468 KeReleaseSemaphore(Resource
->SharedWaiters
,0,oldWaiters
,0);
469 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
470 DPRINT("ExConvertExclusiveToSharedLite() finished\n");
478 ExDisableResourceBoostLite (
482 Resource
->Flag
|= ResourceDisableBoost
;
490 ExGetExclusiveWaiterCount (
494 return(Resource
->NumberOfExclusiveWaiters
);
502 ExAcquireSharedStarveExclusive (
507 * FUNCTION: Acquires a given resource for shared access without waiting
508 * for any pending attempts to acquire exclusive access to the
511 * Resource = Points to the resource to be acquired for shared access
512 * Wait = Is set to TRUE if the caller will wait until the resource
513 * becomes available when access can't be granted immediately
514 * RETURNS: TRUE if the requested access is granted. The routine returns
515 * FALSE if the input Wait is FALSE and shared access can't be
516 * granted immediately
521 DPRINT("ExAcquireSharedStarveExclusive(Resource 0x%p, Wait %d)\n",
524 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
526 /* no owner, it's easy */
527 if (Resource
->ActiveCount
== 0)
529 Resource
->OwnerThreads
[1].OwnerThread
=ExGetCurrentResourceThread();
530 Resource
->OwnerThreads
[1].OwnerCount
=1;
531 Resource
->ActiveCount
=1;
532 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
533 DPRINT("ExAcquireSharedStarveExclusive() = TRUE\n");
537 if ((Resource
->Flag
& ResourceOwnedExclusive
)
538 && Resource
->OwnerThreads
[0].OwnerThread
==ExGetCurrentResourceThread())
540 /* exclusive, but by same thread : it's ok */
541 Resource
->OwnerThreads
[0].OwnerCount
++;
542 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
543 DPRINT("ExAcquireSharedStarveExclusive() = TRUE\n");
547 if (Resource
->Flag
& ResourceOwnedExclusive
)
549 /* exclusive by another thread */
552 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
553 DPRINT("ExAcquireSharedStarveExclusive() = FALSE\n");
558 Resource
->NumberOfSharedWaiters
++;
559 /* wait for the semaphore */
560 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
561 KeWaitForSingleObject(Resource
->SharedWaiters
,0,0,0,0);
562 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
563 Resource
->NumberOfSharedWaiters
--;
566 EiAddSharedOwner(Resource
);
567 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
568 DPRINT("ExAcquireSharedStarveExclusive() = TRUE\n");
577 ExAcquireSharedWaitForExclusive (
582 return(ExAcquireResourceSharedLite(Resource
,Wait
));
586 #ifdef ExDeleteResource
587 #undef ExDeleteResource
600 return(ExDeleteResourceLite(Resource
));
608 ExDeleteResourceLite (
612 DPRINT("ExDeleteResourceLite(Resource 0x%p)\n", Resource
);
613 if (Resource
->OwnerTable
) ExFreePool(Resource
->OwnerTable
);
614 if (Resource
->SharedWaiters
) ExFreePool(Resource
->SharedWaiters
);
615 if (Resource
->ExclusiveWaiters
) ExFreePool(Resource
->ExclusiveWaiters
);
616 return(STATUS_SUCCESS
);
624 ExGetSharedWaiterCount (
628 return(Resource
->NumberOfSharedWaiters
);
632 #ifdef ExInitializeResource
633 #undef ExInitializeResource
641 ExInitializeResource (
645 return(ExInitializeResourceLite(Resource
));
652 ExInitializeResourceLite (PERESOURCE Resource
)
654 DPRINT("ExInitializeResourceLite(Resource 0x%p)\n", Resource
);
655 memset(Resource
,0,sizeof(ERESOURCE
));
656 Resource
->NumberOfSharedWaiters
= 0;
657 Resource
->NumberOfExclusiveWaiters
= 0;
658 KeInitializeSpinLock(&Resource
->SpinLock
);
660 Resource
->ExclusiveWaiters
=
661 ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_EXCLUSIVE_LOCK
);
662 KeInitializeEvent(Resource
->ExclusiveWaiters
,
663 SynchronizationEvent
,
665 Resource
->SharedWaiters
=
666 ExAllocatePoolWithTag(NonPagedPool
,sizeof(KSEMAPHORE
), TAG_SHARED_SEM
);
667 KeInitializeSemaphore(Resource
->SharedWaiters
,0,0x7fffffff);
668 Resource
->ActiveCount
= 0;
677 ExIsResourceAcquiredExclusiveLite (
681 * FUNCTION: Returns whether the current thread has exclusive access to
684 * Resource = Points to the resource to be queried
685 * RETURNS: TRUE if the caller has exclusive access to the resource,
689 return((Resource
->Flag
& ResourceOwnedExclusive
)
690 && Resource
->OwnerThreads
[0].OwnerThread
==ExGetCurrentResourceThread());
695 #ifdef ExIsResourceAcquiredSharedLite
696 #undef ExIsResourceAcquiredSharedLite
708 ExIsResourceAcquiredSharedLite(
709 IN PERESOURCE Resource
)
711 * FUNCTION: Returns whether the current thread has shared access to a given
714 * Resource = Points to the resource to be queried
715 * RETURNS: The number of times the caller has acquired shared access to the
720 if (Resource
->OwnerThreads
[0].OwnerThread
== ExGetCurrentResourceThread())
722 return (USHORT
)(Resource
->OwnerThreads
[0].OwnerCount
);
724 if (Resource
->OwnerThreads
[1].OwnerThread
== ExGetCurrentResourceThread())
726 return (USHORT
)(Resource
->OwnerThreads
[1].OwnerCount
);
728 if (!Resource
->OwnerThreads
[1].TableSize
)
732 for (i
=0; i
<Resource
->OwnerThreads
[1].TableSize
; i
++)
734 if (Resource
->OwnerTable
[i
].OwnerThread
==ExGetCurrentResourceThread())
736 return (USHORT
)Resource
->OwnerTable
[i
].OwnerCount
;
747 ExReinitializeResourceLite (
751 Resource
->NumberOfSharedWaiters
= 0;
752 Resource
->NumberOfExclusiveWaiters
= 0;
753 KeInitializeSpinLock(&Resource
->SpinLock
);
755 KeInitializeEvent(Resource
->ExclusiveWaiters
,SynchronizationEvent
,
757 KeInitializeSemaphore(Resource
->SharedWaiters
,0,0x7fffffff);
758 Resource
->ActiveCount
= 0;
759 if (Resource
->OwnerTable
)
761 ExFreePool(Resource
->OwnerTable
);
763 Resource
->OwnerThreads
[0].OwnerThread
=0;
764 Resource
->OwnerThreads
[0].OwnerCount
=0;
765 Resource
->OwnerThreads
[1].OwnerThread
=0;
766 Resource
->OwnerThreads
[1].OwnerCount
=0;
774 ExReleaseResourceLite (
778 ExReleaseResourceForThreadLite(Resource
,
779 ExGetCurrentResourceThread());
784 #ifdef ExReleaseResourceForThread
785 #undef ExReleaseResourceForThread
794 ExReleaseResourceForThread (
796 ERESOURCE_THREAD ResourceThreadId
799 ExReleaseResourceForThreadLite(Resource
,ResourceThreadId
);
808 ExReleaseResourceForThreadLite (
810 ERESOURCE_THREAD ResourceThreadId
813 * FUNCTION: Releases a resource for the given thread
815 * Resource = Points to the release to release
816 * ResourceThreadId = Identifies the thread that originally acquired
818 * NOTES: Must be running at IRQL < DISPATCH_LEVEL
819 * BUG: We don't support starving exclusive waiters
824 DPRINT("ExReleaseResourceForThreadLite(Resource 0x%p, ResourceThreadId 0x%p)\n",
825 Resource
, ResourceThreadId
);
827 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
829 KeAcquireSpinLock(&Resource
->SpinLock
, &oldIrql
);
831 if (Resource
->Flag
& ResourceOwnedExclusive
)
833 DPRINT("Releasing from exclusive access\n");
835 Resource
->OwnerThreads
[0].OwnerCount
--;
836 if (Resource
->OwnerThreads
[0].OwnerCount
> 0)
838 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
839 DPRINT("ExReleaseResourceForThreadLite() finished\n");
843 Resource
->OwnerThreads
[0].OwnerThread
= 0;
844 Resource
->ActiveCount
--;
845 Resource
->Flag
&=(~ResourceOwnedExclusive
);
846 ASSERT(Resource
->ActiveCount
== 0);
847 DPRINT("Resource->NumberOfExclusiveWaiters %d\n",
848 Resource
->NumberOfExclusiveWaiters
);
849 if (Resource
->NumberOfExclusiveWaiters
)
851 /* get resource to first exclusive waiter */
852 KeSetEvent(Resource
->ExclusiveWaiters
,
855 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
856 DPRINT("ExReleaseResourceForThreadLite() finished\n");
859 DPRINT("Resource->NumberOfSharedWaiters %d\n",
860 Resource
->NumberOfSharedWaiters
);
861 if (Resource
->NumberOfSharedWaiters
)
863 DPRINT("Releasing semaphore\n");
864 KeReleaseSemaphore(Resource
->SharedWaiters
,
866 Resource
->NumberOfSharedWaiters
,
869 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
870 DPRINT("ExReleaseResourceForThreadLite() finished\n");
874 EiRemoveSharedOwner(Resource
, ResourceThreadId
);
876 if (Resource
->ActiveCount
== 0)
878 if (Resource
->NumberOfExclusiveWaiters
)
880 /* get resource to first exclusive waiter */
881 KeSetEvent(Resource
->ExclusiveWaiters
,
887 KeReleaseSpinLock(&Resource
->SpinLock
, oldIrql
);
888 DPRINT("ExReleaseResourceForThreadLite() finished\n");
897 ExSetResourceOwnerPointer (
898 IN PERESOURCE Resource
,
899 IN PVOID OwnerPointer
902 PKTHREAD CurrentThread
;
904 POWNER_ENTRY OwnerEntry
;
906 CurrentThread
= KeGetCurrentThread();
908 /* Lock the resource */
909 KeAcquireSpinLock(&Resource
->SpinLock
, &OldIrql
);
911 /* Check if it's exclusive */
912 if (Resource
->Flag
& ResourceOwnedExclusive
) {
914 /* If it's exclusive, set the first entry no matter what */
915 Resource
->OwnerThreads
[0].OwnerThread
= (ULONG_PTR
)OwnerPointer
;
919 /* Check both entries and see which one matches the current thread */
920 if (Resource
->OwnerThreads
[0].OwnerThread
== (ULONG_PTR
)CurrentThread
) {
922 Resource
->OwnerThreads
[0].OwnerThread
= (ULONG_PTR
)OwnerPointer
;
924 } else if (Resource
->OwnerThreads
[1].OwnerThread
== (ULONG_PTR
)CurrentThread
) {
926 Resource
->OwnerThreads
[1].OwnerThread
= (ULONG_PTR
)OwnerPointer
;
928 } else { /* None of the entries match, so we need to do a lookup */
930 /* Get the first Entry */
931 OwnerEntry
= Resource
->OwnerTable
;
933 /* Check if the Current Thread is in the Resource Table Entry */
934 if ((CurrentThread
->ResourceIndex
>= OwnerEntry
->TableSize
) ||
935 (OwnerEntry
[CurrentThread
->ResourceIndex
].OwnerThread
!= (ULONG_PTR
)CurrentThread
)) {
937 /* Loop until we find the current thread in an entry */
938 for (;OwnerEntry
->OwnerThread
== (ULONG_PTR
)CurrentThread
;OwnerEntry
++);
942 /* It's in the current RTE, so set it */
943 OwnerEntry
= &OwnerEntry
[CurrentThread
->ResourceIndex
];
946 /* Now that we went to the right entry, set the Owner Pointer */
947 OwnerEntry
->OwnerThread
= (ULONG_PTR
)OwnerPointer
;
951 /* Release the resource */
952 KeReleaseSpinLock(&Resource
->SpinLock
, OldIrql
);