Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

resource.c File Reference

#include "exp.h"
#include "nturtl.h"

Go to the source code of this file.

Defines

#define IsExclusiveWaiting(a)   ((a)->NumberOfExclusiveWaiters != 0)
#define IsSharedWaiting(a)   ((a)->NumberOfSharedWaiters != 0)
#define IsOwnedExclusive(a)   (((a)->Flag & ResourceOwnedExclusive) != 0)
#define IsBoostAllowed(a)   (((a)->Flag & DisablePriorityBoost) == 0)
#define DisablePriorityBoost   0x08
#define ASSERT_RESOURCE(_Resource)
#define ExpIncrementCounter(Member)

Functions

VOID FASTCALL ExpWaitForResource (IN PERESOURCE Resource, IN PVOID Object)
POWNER_ENTRY FASTCALL ExpFindCurrentThread (IN PERESOURCE Resource, IN ERESOURCE_THREAD CurrentThread)
BOOLEAN ExpResourceInitialization (VOID)
NTSTATUS ExInitializeResourceLite (IN PERESOURCE Resource)
NTSTATUS ExReinitializeResourceLite (IN PERESOURCE Resource)
VOID ExDisableResourceBoostLite (IN PERESOURCE Resource)
BOOLEAN FASTCALL ExpAcquireResourceExclusiveLite (IN PERESOURCE Resource, IN KIRQL OldIrql)
BOOLEAN ExAcquireResourceExclusiveLite (IN PERESOURCE Resource, IN BOOLEAN Wait)
BOOLEAN ExTryToAcquireResourceExclusiveLite (IN PERESOURCE Resource)
BOOLEAN ExAcquireResourceSharedLite (IN PERESOURCE Resource, IN BOOLEAN Wait)
BOOLEAN ExAcquireSharedStarveExclusive (IN PERESOURCE Resource, IN BOOLEAN Wait)
BOOLEAN ExAcquireSharedWaitForExclusive (IN PERESOURCE Resource, IN BOOLEAN Wait)
VOID FASTCALL ExReleaseResourceLite (IN PERESOURCE Resource)
VOID ExReleaseResourceForThreadLite (IN PERESOURCE Resource, IN ERESOURCE_THREAD CurrentThread)
VOID ExSetResourceOwnerPointer (IN PERESOURCE Resource, IN PVOID OwnerPointer)
VOID ExConvertExclusiveToSharedLite (IN PERESOURCE Resource)
NTSTATUS ExDeleteResourceLite (IN PERESOURCE Resource)
ULONG ExGetExclusiveWaiterCount (IN PERESOURCE Resource)
ULONG ExGetSharedWaiterCount (IN PERESOURCE Resource)
BOOLEAN ExIsResourceAcquiredExclusiveLite (IN PERESOURCE Resource)
ULONG ExIsResourceAcquiredSharedLite (IN PERESOURCE Resource)
NTSTATUS ExQuerySystemLockInformation (OUT PRTL_PROCESS_LOCKS LockInformation, IN ULONG LockInformationLength, OUT PULONG ReturnLength OPTIONAL)
VOID FASTCALL ExpBoostOwnerThread (IN PKTHREAD CurrentThread, IN PKTHREAD OwnerThread)
PVOID ExpCheckForResource (IN PVOID p, IN ULONG Size)

Variables

LARGE_INTEGER ExpTimeout
ULONG ExpResourceTimeoutCount = 648000
KSPIN_LOCK ExpResourceSpinLock
LIST_ENTRY ExpSystemResourcesList


Define Documentation

#define ASSERT_RESOURCE _Resource   ) 
 

Definition at line 74 of file ex/resource.c.

#define DisablePriorityBoost   0x08
 

Definition at line 57 of file ex/resource.c.

#define ExpIncrementCounter Member   ) 
 

Definition at line 134 of file ex/resource.c.

Referenced by ExAcquireResourceExclusiveLite(), ExAcquireResourceSharedLite(), ExAcquireSharedStarveExclusive(), ExAcquireSharedWaitForExclusive(), ExpFindCurrentThread(), and ExTryToAcquireResourceExclusiveLite().

#define IsBoostAllowed  )     (((a)->Flag & DisablePriorityBoost) == 0)
 

Definition at line 51 of file ex/resource.c.

#define IsExclusiveWaiting  )     ((a)->NumberOfExclusiveWaiters != 0)
 

Definition at line 48 of file ex/resource.c.

#define IsOwnedExclusive  )     (((a)->Flag & ResourceOwnedExclusive) != 0)
 

Definition at line 50 of file ex/resource.c.

#define IsSharedWaiting  )     ((a)->NumberOfSharedWaiters != 0)
 

Definition at line 49 of file ex/resource.c.

Referenced by ExConvertExclusiveToSharedLite(), ExDeleteResourceLite(), ExpWaitForResource(), ExReleaseResourceForThreadLite(), and ExReleaseResourceLite().


Function Documentation

BOOLEAN ExAcquireResourceExclusiveLite IN PERESOURCE  Resource,
IN BOOLEAN  Wait
 

Definition at line 492 of file ex/resource.c.

References _ERESOURCE::ActiveCount, ASSERT, ASSERT_RESOURCE, ERESOURCE_THREAD, Event(), ExpAcquireResourceExclusiveLite(), ExpIncrementCounter, FALSE, _ERESOURCE::Flag, IsOwnedExclusive, _OWNER_ENTRY::OwnerCount, _OWNER_ENTRY::OwnerThread, _ERESOURCE::OwnerThreads, PsGetCurrentThread, Resource, ResourceNeverExclusive, ResourceOwnedExclusive, _ERESOURCE::SpinLock, and TRUE.

Referenced by ChangeAcquireResourceType(), EnterCrit(), ExpAcquireResourceExclusiveLite(), LeaveMouseCrit(), and VerifierExAcquireResourceExclusive().

00499 : 00500 00501 The routine acquires the specified resource for exclusive access. 00502 00503 N.B. This routine uses fast locking. 00504 00505 Arguments: 00506 00507 Resource - Supplies a pointer to the resource that is acquired 00508 for exclusive access. 00509 00510 Wait - A boolean value that specifies whether to wait for the 00511 resource to become available if access cannot be granted 00512 immediately. 00513 00514 Return Value: 00515 00516 BOOLEAN - TRUE if the resource is acquired and FALSE otherwise. 00517 00518 --*/ 00519 00520 { 00521 00522 ERESOURCE_THREAD CurrentThread; 00523 PKEVENT Event; 00524 KIRQL OldIrql = 0; 00525 BOOLEAN Result; 00526 00527 ASSERT((Resource->Flag & ResourceNeverExclusive) == 0); 00528 00529 // 00530 // Acquire exclusive access to the specified resource. 00531 // 00532 00533 CurrentThread = (ERESOURCE_THREAD)PsGetCurrentThread(); 00534 ExAcquireFastLock(&Resource->SpinLock, &OldIrql); 00535 00536 ASSERT(KeIsExecutingDpc() == FALSE); 00537 ASSERT_RESOURCE(Resource); 00538 00539 // 00540 // If the active count of the resource is zero, then there is neither 00541 // an exclusive owner nor a shared owner and access to the resource can 00542 // be immediately granted. Otherwise, there is either a shared owner or 00543 // an exclusive owner. 00544 // 00545 00546 ExpIncrementCounter(ExclusiveAcquire); 00547 if (Resource->ActiveCount != 0) { 00548 00549 // 00550 // The resource is either owned exclusive or shared. 00551 // 00552 // If the resource is owned exclusive and the current thread is the 00553 // owner, then increment the recursion count. 00554 // 00555 00556 if (IsOwnedExclusive(Resource) && 00557 (Resource->OwnerThreads[0].OwnerThread == CurrentThread)) { 00558 Resource->OwnerThreads[0].OwnerCount += 1; 00559 Result = TRUE; 00560 00561 } else { 00562 00563 // 00564 // The resource is either owned exclusive by some other thread, 00565 // or owned shared. 00566 // 00567 // If wait is not specified, then return that the resource was 00568 // not acquired. Otherwise, wait for exclusive access to the 00569 // resource to be granted. 00570 // 00571 00572 if (Wait == FALSE) { 00573 Result = FALSE; 00574 00575 } else { 00576 return ExpAcquireResourceExclusiveLite(Resource, OldIrql); 00577 } 00578 } 00579 00580 } else { 00581 00582 // 00583 // The resource is not owned. 00584 // 00585 00586 Resource->Flag |= ResourceOwnedExclusive; 00587 Resource->OwnerThreads[0].OwnerThread = CurrentThread; 00588 Resource->OwnerThreads[0].OwnerCount = 1; 00589 Resource->ActiveCount = 1; 00590 Result = TRUE; 00591 } 00592 00593 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 00594 return Result; 00595 }

BOOLEAN ExAcquireResourceSharedLite IN PERESOURCE  Resource,
IN BOOLEAN  Wait
 

Definition at line 762 of file ex/resource.c.

References _ERESOURCE::ActiveCount, ASSERT, ASSERT_RESOURCE, ERESOURCE_THREAD, ExAllocatePoolWithTag, ExpFindCurrentThread(), ExpIncrementCounter, ExpWaitForResource(), FALSE, IsExclusiveWaiting, IsOwnedExclusive, KeInitializeSemaphore(), NonPagedPoolMustSucceed, NULL, _ERESOURCE::NumberOfSharedWaiters, _OWNER_ENTRY::OwnerCount, _OWNER_ENTRY::OwnerThread, _ERESOURCE::OwnerThreads, PsGetCurrentThread, Resource, _ERESOURCE::SharedWaiters, _ERESOURCE::SpinLock, and TRUE.

Referenced by EnterSharedCrit().

00769 : 00770 00771 The routine acquires the specified resource for shared access. 00772 00773 Arguments: 00774 00775 Resource - Supplies a pointer to the resource that is acquired 00776 for shared access. 00777 00778 Wait - A boolean value that specifies whether to wait for the 00779 resource to become available if access cannot be granted 00780 immediately. 00781 00782 Return Value: 00783 00784 BOOLEAN - TRUE if the resource is acquired and FALSE otherwise 00785 00786 --*/ 00787 00788 { 00789 00790 ERESOURCE_THREAD CurrentThread; 00791 KIRQL OldIrql; 00792 POWNER_ENTRY OwnerEntry; 00793 PKSEMAPHORE Semaphore; 00794 00795 // 00796 // Acquire exclusive access to the specified resource. 00797 // 00798 00799 CurrentThread = (ERESOURCE_THREAD)PsGetCurrentThread(); 00800 ExAcquireSpinLock(&Resource->SpinLock, &OldIrql); 00801 00802 ASSERT(KeIsExecutingDpc() == FALSE); 00803 ASSERT_RESOURCE(Resource); 00804 00805 ExpIncrementCounter(SharedSecondLevel); 00806 00807 // 00808 // If the active count of the resource is zero, then there is neither 00809 // an exclusive owner nor a shared owner and access to the resource can 00810 // be immediately granted. 00811 // 00812 00813 if (Resource->ActiveCount == 0) { 00814 Resource->OwnerThreads[1].OwnerThread = CurrentThread; 00815 Resource->OwnerThreads[1].OwnerCount = 1; 00816 Resource->ActiveCount = 1; 00817 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 00818 return TRUE; 00819 } 00820 00821 // 00822 // The resource is either owned exclusive or shared. 00823 // 00824 // If the resource is owned exclusive and the current thread is the 00825 // owner, then treat the shared request as an exclusive request and 00826 // increment the recursion count. Otherwise, it is owned shared. 00827 // 00828 00829 if (IsOwnedExclusive(Resource)) { 00830 if (Resource->OwnerThreads[0].OwnerThread == CurrentThread) { 00831 Resource->OwnerThreads[0].OwnerCount += 1; 00832 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 00833 return TRUE; 00834 } 00835 00836 // 00837 // Find an empty entry in the thread array. 00838 // 00839 00840 OwnerEntry = ExpFindCurrentThread(Resource, 0); 00841 00842 } else { 00843 00844 // 00845 // The resource is owned shared. 00846 // 00847 // If the current thread already has acquired the resource for 00848 // shared access, then increment the recursion count. Otherwise 00849 // grant shared access if there are no exclusive waiters. 00850 // 00851 00852 OwnerEntry = ExpFindCurrentThread(Resource, CurrentThread); 00853 if (OwnerEntry->OwnerThread == CurrentThread) { 00854 OwnerEntry->OwnerCount += 1; 00855 00856 ASSERT(OwnerEntry->OwnerCount != 0); 00857 00858 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 00859 return TRUE; 00860 } 00861 00862 // 00863 // If there are no exclusive waiters, then grant shared access 00864 // to the resource. Otherwise, wait for the resource to become 00865 // available. 00866 // 00867 00868 if (IsExclusiveWaiting(Resource) == FALSE) { 00869 OwnerEntry->OwnerThread = CurrentThread; 00870 OwnerEntry->OwnerCount = 1; 00871 Resource->ActiveCount += 1; 00872 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 00873 return TRUE; 00874 } 00875 } 00876 00877 // 00878 // The resource is either owned exclusive by some other thread, or 00879 // owned shared by some other threads, but there is an exclusive 00880 // waiter and the current thread does not already have shared access 00881 // to the resource. 00882 // 00883 // If wait is not specified, then return that the resource was 00884 // not acquired. 00885 // 00886 00887 if (Wait == FALSE) { 00888 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 00889 return FALSE; 00890 } 00891 00892 // 00893 // If the shared wait semaphore has not yet been allocated, then allocate 00894 // and initialize it. 00895 // 00896 00897 if (Resource->SharedWaiters == NULL) { 00898 Semaphore = ExAllocatePoolWithTag(NonPagedPoolMustSucceed, 00899 sizeof(KSEMAPHORE), 00900 'eSeR'); 00901 00902 KeInitializeSemaphore(Semaphore, 0, MAXLONG); 00903 Resource->SharedWaiters = Semaphore; 00904 } 00905 00906 // 00907 // Wait for shared access to the resource to be granted and increment 00908 // the recursion count. 00909 // 00910 00911 OwnerEntry->OwnerThread = CurrentThread; 00912 OwnerEntry->OwnerCount = 1; 00913 Resource->NumberOfSharedWaiters += 1; 00914 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 00915 ExpWaitForResource(Resource, Resource->SharedWaiters); 00916 return TRUE; 00917 }

BOOLEAN ExAcquireSharedStarveExclusive IN PERESOURCE  Resource,
IN BOOLEAN  Wait
 

Definition at line 1014 of file ex/resource.c.

References _ERESOURCE::ActiveCount, ASSERT, ASSERT_RESOURCE, ERESOURCE_THREAD, ExAllocatePoolWithTag, ExpFindCurrentThread(), ExpIncrementCounter, ExpWaitForResource(), FALSE, IsOwnedExclusive, KeInitializeSemaphore(), NonPagedPoolMustSucceed, NULL, _ERESOURCE::NumberOfSharedWaiters, _OWNER_ENTRY::OwnerCount, _OWNER_ENTRY::OwnerThread, _ERESOURCE::OwnerThreads, PsGetCurrentThread, Resource, _ERESOURCE::SharedWaiters, _ERESOURCE::SpinLock, and TRUE.

Referenced by CcPinFileData(), CcPinMappedData(), and UdfAcquireResource().

01020 : 01021 01022 This routine acquires the specified resource for shared access and 01023 does not wait for any pending exclusive owners. 01024 01025 Arguments: 01026 01027 Resource - Supplies a pointer to the resource that is acquired 01028 for shared access. 01029 01030 Wait - A boolean value that specifies whether to wait for the 01031 resource to become available if access cannot be granted 01032 immediately. 01033 01034 Return Value: 01035 01036 BOOLEAN - TRUE if the resource is acquired and FALSE otherwise 01037 01038 --*/ 01039 01040 { 01041 01042 ERESOURCE_THREAD CurrentThread; 01043 KIRQL OldIrql; 01044 POWNER_ENTRY OwnerEntry; 01045 PKSEMAPHORE Semaphore; 01046 01047 // 01048 // Acquire exclusive access to the specified resource. 01049 // 01050 01051 CurrentThread = (ERESOURCE_THREAD)PsGetCurrentThread(); 01052 ExAcquireSpinLock(&Resource->SpinLock, &OldIrql); 01053 01054 ASSERT(KeIsExecutingDpc() == FALSE); 01055 ASSERT_RESOURCE(Resource); 01056 01057 ExpIncrementCounter(StarveSecondLevel); 01058 01059 // 01060 // If the active count of the resource is zero, then there is neither 01061 // an exclusive owner nor a shared owner and access to the resource can 01062 // be immediately granted. 01063 // 01064 01065 if (Resource->ActiveCount == 0) { 01066 Resource->OwnerThreads[1].OwnerThread = CurrentThread; 01067 Resource->OwnerThreads[1].OwnerCount = 1; 01068 Resource->ActiveCount = 1; 01069 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 01070 return TRUE; 01071 } 01072 01073 // 01074 // The resource is either owned exclusive or shared. 01075 // 01076 // If the resource is owned exclusive and the current thread is the 01077 // owner, then treat the shared request as an exclusive request and 01078 // increment the recursion count. Otherwise, it is owned shared. 01079 // 01080 01081 if (IsOwnedExclusive(Resource)) { 01082 if (Resource->OwnerThreads[0].OwnerThread == CurrentThread) { 01083 Resource->OwnerThreads[0].OwnerCount += 1; 01084 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 01085 return TRUE; 01086 } 01087 01088 // 01089 // Find an empty entry in the thread array. 01090 // 01091 01092 OwnerEntry = ExpFindCurrentThread(Resource, 0); 01093 01094 } else { 01095 01096 // 01097 // The resource is owned shared. 01098 // 01099 // If the current thread already has acquired the resource for 01100 // shared access, then increment the recursion count. Otherwise 01101 // grant shared access to the current thread 01102 // 01103 01104 OwnerEntry = ExpFindCurrentThread(Resource, CurrentThread); 01105 if (OwnerEntry->OwnerThread == CurrentThread) { 01106 OwnerEntry->OwnerCount += 1; 01107 01108 ASSERT(OwnerEntry->OwnerCount != 0); 01109 01110 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 01111 return TRUE; 01112 } 01113 01114 // 01115 // Grant the current thread shared access to the resource. 01116 // 01117 01118 OwnerEntry->OwnerThread = CurrentThread; 01119 OwnerEntry->OwnerCount = 1; 01120 Resource->ActiveCount += 1; 01121 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 01122 return TRUE; 01123 } 01124 01125 // 01126 // The resource is owned exclusive by some other thread. 01127 // 01128 // If wait is not specified, then return that the resource was 01129 // not acquired. 01130 // 01131 01132 if (Wait == FALSE) { 01133 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 01134 return FALSE; 01135 } 01136 01137 // 01138 // If the shared wait semaphore has not yet been allocated, then allocate 01139 // and initialize it. 01140 // 01141 01142 if (Resource->SharedWaiters == NULL) { 01143 Semaphore = ExAllocatePoolWithTag(NonPagedPoolMustSucceed, 01144 sizeof(KSEMAPHORE), 01145 'eSeR'); 01146 01147 KeInitializeSemaphore(Semaphore, 0, MAXLONG); 01148 Resource->SharedWaiters = Semaphore; 01149 } 01150 01151 // 01152 // Wait for shared access to the resource to be granted and increment 01153 // the recursion count. 01154 // 01155 01156 OwnerEntry->OwnerThread = CurrentThread; 01157 OwnerEntry->OwnerCount = 1; 01158 Resource->NumberOfSharedWaiters += 1; 01159 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 01160 ExpWaitForResource(Resource, Resource->SharedWaiters); 01161 return TRUE; 01162 }

BOOLEAN ExAcquireSharedWaitForExclusive IN PERESOURCE  Resource,
IN BOOLEAN  Wait
 

Definition at line 1165 of file ex/resource.c.

References _ERESOURCE::ActiveCount, ASSERT, ASSERT_RESOURCE, ERESOURCE_THREAD, ExAllocatePoolWithTag, ExpFindCurrentThread(), ExpIncrementCounter, ExpWaitForResource(), FALSE, IsExclusiveWaiting, IsOwnedExclusive, KeInitializeSemaphore(), NonPagedPoolMustSucceed, NULL, _ERESOURCE::NumberOfSharedWaiters, _OWNER_ENTRY::OwnerCount, _OWNER_ENTRY::OwnerThread, _ERESOURCE::OwnerThreads, PsGetCurrentThread, Resource, _ERESOURCE::SharedWaiters, _ERESOURCE::SpinLock, and TRUE.

Referenced by FsRtlAcquireFileForModWrite().

01171 : 01172 01173 This routine acquires the specified resource for shared access, but 01174 waits for any pending exclusive owners. 01175 01176 Arguments: 01177 01178 Resource - Supplies a pointer to the resource that is acquired 01179 for shared access. 01180 01181 Wait - A boolean value that specifies whether to wait for the 01182 resource to become available if access cannot be granted 01183 immediately. 01184 01185 Return Value: 01186 01187 BOOLEAN - TRUE if the resource is acquired and FALSE otherwise 01188 01189 --*/ 01190 01191 { 01192 01193 ERESOURCE_THREAD CurrentThread; 01194 KIRQL OldIrql; 01195 POWNER_ENTRY OwnerEntry; 01196 PKSEMAPHORE Semaphore; 01197 01198 // 01199 // Acquire exclusive access to the specified resource. 01200 // 01201 01202 CurrentThread = (ERESOURCE_THREAD)PsGetCurrentThread(); 01203 ExAcquireSpinLock(&Resource->SpinLock, &OldIrql); 01204 01205 ASSERT(KeIsExecutingDpc() == FALSE); 01206 ASSERT_RESOURCE(Resource); 01207 01208 ExpIncrementCounter(WaitForExclusive); 01209 01210 // 01211 // If the active count of the resource is zero, then there is neither 01212 // an exclusive owner nor a shared owner and access to the resource can 01213 // be immediately granted. 01214 // 01215 01216 if (Resource->ActiveCount == 0) { 01217 Resource->OwnerThreads[1].OwnerThread = CurrentThread; 01218 Resource->OwnerThreads[1].OwnerCount = 1; 01219 Resource->ActiveCount = 1; 01220 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 01221 return TRUE; 01222 } 01223 01224 // 01225 // The resource is either owned exclusive or shared. 01226 // 01227 // If the resource is owned exclusive and the current thread is the 01228 // owner, then treat the shared request as an exclusive request and 01229 // increment the recursion count. Otherwise, it is owned shared. 01230 // 01231 01232 if (IsOwnedExclusive(Resource)) { 01233 if (Resource->OwnerThreads[0].OwnerThread == CurrentThread) { 01234 Resource->OwnerThreads[0].OwnerCount += 1; 01235 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 01236 return TRUE; 01237 } 01238 01239 // 01240 // Find an empty entry in the thread array. 01241 // 01242 01243 OwnerEntry = ExpFindCurrentThread(Resource, 0); 01244 01245 } else { 01246 01247 // 01248 // The resource is owned shared. 01249 // 01250 // If there is an exclusive waiter, then wait for the exclusive 01251 // waiter to gain access to the resource, then acquire the resource 01252 // shared without regard to exclusive waiters. Otherwise, if the 01253 // current thread already has acquired the resource for shared access, 01254 // then increment the recursion count. Otherwise grant shared access 01255 // to the current thread 01256 // 01257 01258 if (IsExclusiveWaiting(Resource)) { 01259 01260 // 01261 // The resource is shared, but there is an exclusive waiter. 01262 // 01263 // If wait is not specified, then return that the resource was 01264 // not acquired. 01265 // 01266 01267 if (Wait == FALSE) { 01268 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 01269 return FALSE; 01270 } 01271 01272 // 01273 // If the shared wait semaphore has not yet been allocated, then 01274 // allocate and initialize it. 01275 // 01276 01277 if (Resource->SharedWaiters == NULL) { 01278 Semaphore = ExAllocatePoolWithTag(NonPagedPoolMustSucceed, 01279 sizeof(KSEMAPHORE), 01280 'eSeR'); 01281 01282 KeInitializeSemaphore(Semaphore, 0, MAXLONG); 01283 Resource->SharedWaiters = Semaphore; 01284 } 01285 01286 // 01287 // Increment the number of shared waiters and wait for shared 01288 // access to the resource to be granted to some other set of 01289 // threads, and then acquire the resource shared without regard 01290 // to exclusive access. 01291 // 01292 // N.B. The resource is left in a state such that the calling 01293 // thread does not have a reference in the owner table 01294 // for the requested access even though the active count 01295 // is incremented when control is returned. However, the 01296 // resource is owned shared at this point, so an owner 01297 // entry can simply be allocated and the owner count set 01298 // to one. 01299 // 01300 01301 Resource->NumberOfSharedWaiters += 1; 01302 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 01303 ExpWaitForResource(Resource, Resource->SharedWaiters); 01304 01305 // 01306 // Reacquire the resource spin lock, allocate an owner entry, 01307 // and initialize the owner count to one. The active count 01308 // was already incremented when shared access was granted. 01309 // 01310 01311 ExAcquireSpinLock(&Resource->SpinLock, &OldIrql); 01312 01313 ASSERT(IsOwnedExclusive(Resource) == FALSE); 01314 ASSERT(Resource->ActiveCount > 0); 01315 01316 OwnerEntry = ExpFindCurrentThread(Resource, CurrentThread); 01317 01318 ASSERT(OwnerEntry->OwnerThread != CurrentThread); 01319 01320 OwnerEntry->OwnerThread = CurrentThread; 01321 OwnerEntry->OwnerCount = 1; 01322 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 01323 return TRUE; 01324 01325 } else { 01326 OwnerEntry = ExpFindCurrentThread(Resource, CurrentThread); 01327 if (OwnerEntry->OwnerThread == CurrentThread) { 01328 OwnerEntry->OwnerCount += 1; 01329 01330 ASSERT(OwnerEntry->OwnerCount != 0); 01331 01332 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 01333 return TRUE; 01334 } 01335 01336 // 01337 // Grant the current thread shared access to the resource. 01338 // 01339 01340 OwnerEntry->OwnerThread = CurrentThread; 01341 OwnerEntry->OwnerCount = 1; 01342 Resource->ActiveCount += 1; 01343 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 01344 return TRUE; 01345 } 01346 } 01347 01348 // 01349 // The resource is owned exclusive by some other thread. 01350 // 01351 // If wait is not specified, then return that the resource was 01352 // not acquired. 01353 // 01354 01355 if (Wait == FALSE) { 01356 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 01357 return FALSE; 01358 } 01359 01360 // 01361 // If the shared wait semaphore has not yet been allocated, then allocate 01362 // and initialize it. 01363 // 01364 01365 if (Resource->SharedWaiters == NULL) { 01366 Semaphore = ExAllocatePoolWithTag(NonPagedPoolMustSucceed, 01367 sizeof(KSEMAPHORE), 01368 'eSeR'); 01369 01370 KeInitializeSemaphore(Semaphore, 0, MAXLONG); 01371 Resource->SharedWaiters = Semaphore; 01372 } 01373 01374 // 01375 // Wait for shared access to the resource to be granted and increment 01376 // the recursion count. 01377 // 01378 01379 OwnerEntry->OwnerThread = CurrentThread; 01380 OwnerEntry->OwnerCount = 1; 01381 Resource->NumberOfSharedWaiters += 1; 01382 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 01383 ExpWaitForResource(Resource, Resource->SharedWaiters); 01384 return TRUE; 01385 }

VOID ExConvertExclusiveToSharedLite IN PERESOURCE  Resource  ) 
 

Definition at line 1942 of file ex/resource.c.

References _ERESOURCE::ActiveCount, ASSERT, ASSERT_RESOURCE, ERESOURCE_THREAD, FALSE, _ERESOURCE::Flag, IsOwnedExclusive, IsSharedWaiting, KeReleaseSemaphore(), _ERESOURCE::NumberOfSharedWaiters, _OWNER_ENTRY::OwnerThread, _ERESOURCE::OwnerThreads, PsGetCurrentThread, Resource, ResourceOwnedExclusive, _ERESOURCE::SharedWaiters, SHORT, and _ERESOURCE::SpinLock.

01948 : 01949 01950 This routine converts the specified resource from acquired for exclusive 01951 access to acquired for shared access. 01952 01953 N.B. This routine uses fast locking. 01954 01955 Arguments: 01956 01957 Resource - Supplies a pointer to the resource to acquire for shared access. it 01958 01959 Return Value: 01960 01961 None. 01962 01963 --*/ 01964 01965 { 01966 01967 ULONG Number; 01968 KIRQL OldIrql; 01969 01970 // 01971 // Acquire exclusive access to the specified resource. 01972 // 01973 01974 ExAcquireFastLock(&Resource->SpinLock, &OldIrql); 01975 01976 ASSERT(KeIsExecutingDpc() == FALSE); 01977 ASSERT_RESOURCE(Resource); 01978 ASSERT(IsOwnedExclusive(Resource)); 01979 ASSERT(Resource->OwnerThreads[0].OwnerThread == (ERESOURCE_THREAD)PsGetCurrentThread()); 01980 01981 // 01982 // Convert the granted access from exclusive to shared. 01983 // 01984 01985 Resource->Flag &= ~ResourceOwnedExclusive; 01986 01987 // 01988 // If there are any shared waiters, then grant them shared access. 01989 // 01990 01991 if (IsSharedWaiting(Resource)) { 01992 Number = Resource->NumberOfSharedWaiters; 01993 Resource->ActiveCount += (SHORT)Number; 01994 Resource->NumberOfSharedWaiters = 0; 01995 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 01996 KeReleaseSemaphore(Resource->SharedWaiters, 0, Number, FALSE); 01997 return; 01998 } 01999 02000 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 02001 return; 02002 }

NTSTATUS ExDeleteResourceLite IN PERESOURCE  Resource  ) 
 

Definition at line 2005 of file ex/resource.c.

References _RESOURCE_PERFORMANCE_DATA::ActiveResourceCount, _ERESOURCE::Address, _RESOURCE_HASH_ENTRY::Address, ASSERT, ASSERT_RESOURCE, _RESOURCE_HASH_ENTRY::ContentionCount, _ERESOURCE::ContentionCount, ExAllocatePoolWithTag, _ERESOURCE::ExclusiveWaiters, ExFreePool(), ExpResourceSpinLock, FALSE, _RESOURCE_PERFORMANCE_DATA::HashTable, IsExclusiveWaiting, IsSharedWaiting, _RESOURCE_HASH_ENTRY::ListEntry, NonPagedPool, NULL, _RESOURCE_HASH_ENTRY::Number, _ERESOURCE::OwnerTable, PRESOURCE_HASH_ENTRY, Resource, RESOURCE_HASH_ENTRY, RESOURCE_HASH_TABLE_SIZE, _ERESOURCE::SharedWaiters, and _ERESOURCE::SystemResourcesList.

02011 : 02012 02013 This routine deallocates any pool allocated to support the specified 02014 resource. 02015 02016 02017 Arguments: 02018 02019 Resource - Supplies a pointer to the resource whose allocated pool 02020 is freed. 02021 02022 Return Value: 02023 02024 STATUS_SUCCESS. 02025 02026 --*/ 02027 02028 { 02029 02030 PRESOURCE_HASH_ENTRY HashEntry; 02031 ULONG Hash; 02032 PRESOURCE_HASH_ENTRY MatchEntry; 02033 PLIST_ENTRY NextEntry; 02034 KIRQL OldIrql; 02035 02036 ASSERT(IsSharedWaiting(Resource) == FALSE); 02037 ASSERT(IsExclusiveWaiting(Resource) == FALSE); 02038 02039 // 02040 // Acquire the executive resource spinlock and remove the resource from 02041 // the system resource list. 02042 // 02043 02044 ExAcquireSpinLock(&ExpResourceSpinLock, &OldIrql); 02045 02046 ASSERT(KeIsExecutingDpc() == FALSE); 02047 ASSERT_RESOURCE(Resource); 02048 02049 RemoveEntryList(&Resource->SystemResourcesList); 02050 02051 #if defined(_COLLECT_RESOURCE_DATA_) 02052 02053 // 02054 // Lookup resource initialization address in resource hash table. If 02055 // the address does not exist in the table, then create a new entry. 02056 // 02057 02058 Hash = (ULONG)Resource->Address; 02059 Hash = ((Hash > 24) ^ (Hash > 16) ^ (Hash > 8) ^ (Hash)) & (RESOURCE_HASH_TABLE_SIZE - 1); 02060 MatchEntry = NULL; 02061 NextEntry = ExpResourcePerformanceData.HashTable[Hash].Flink; 02062 while (NextEntry != &ExpResourcePerformanceData.HashTable[Hash]) { 02063 HashEntry = CONTAINING_RECORD(NextEntry, 02064 RESOURCE_HASH_ENTRY, 02065 ListEntry); 02066 02067 if (HashEntry->Address == Resource->Address) { 02068 MatchEntry = HashEntry; 02069 break; 02070 } 02071 02072 NextEntry = NextEntry->Flink; 02073 } 02074 02075 // 02076 // If a matching initialization address was found, then update the call 02077 // site statistics. Otherwise, allocate a new hash entry and initialize 02078 // call site statistics. 02079 // 02080 02081 if (MatchEntry != NULL) { 02082 MatchEntry->ContentionCount += Resource->ContentionCount; 02083 MatchEntry->Number += 1; 02084 02085 } else { 02086 MatchEntry = ExAllocatePoolWithTag(NonPagedPool, 02087 sizeof(RESOURCE_HASH_ENTRY), 02088 'vEpR'); 02089 02090 if (MatchEntry != NULL) { 02091 MatchEntry->Address = Resource->Address; 02092 MatchEntry->ContentionCount = Resource->ContentionCount; 02093 MatchEntry->Number = 1; 02094 InsertTailList(&ExpResourcePerformanceData.HashTable[Hash], 02095 &MatchEntry->ListEntry); 02096 } 02097 } 02098 02099 ExpResourcePerformanceData.ActiveResourceCount -= 1; 02100 02101 #endif 02102 02103 ExReleaseSpinLock(&ExpResourceSpinLock, OldIrql); 02104 02105 // 02106 // If an owner table was allocated, then free it to pool. 02107 // 02108 02109 if (Resource->OwnerTable != NULL) { 02110 ExFreePool(Resource->OwnerTable); 02111 } 02112 02113 // 02114 // If a semaphore was allocated, then free it to pool. 02115 // 02116 02117 if (Resource->SharedWaiters) { 02118 ExFreePool(Resource->SharedWaiters); 02119 } 02120 02121 // 02122 // If an event was allocated, then free it to pool. 02123 // 02124 02125 if (Resource->ExclusiveWaiters) { 02126 ExFreePool(Resource->ExclusiveWaiters); 02127 } 02128 02129 return STATUS_SUCCESS; 02130 }

VOID ExDisableResourceBoostLite IN PERESOURCE  Resource  ) 
 

Definition at line 370 of file ex/resource.c.

References ASSERT_RESOURCE, DisablePriorityBoost, _ERESOURCE::Flag, Resource, and _ERESOURCE::SpinLock.

00376 : 00377 00378 This routine disables priority inversion boosting for the specified 00379 resource. 00380 00381 Arguments: 00382 00383 Resource - Supplies a pointer to the resource for which priority 00384 boosting is disabled. 00385 00386 Return Value: 00387 00388 None. 00389 00390 --*/ 00391 00392 { 00393 00394 KIRQL OldIrql; 00395 00396 // 00397 // Disable priority boosts for the specified resource. 00398 // 00399 00400 ExAcquireFastLock(&Resource->SpinLock, &OldIrql); 00401 00402 ASSERT_RESOURCE(Resource); 00403 00404 Resource->Flag |= DisablePriorityBoost; 00405 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 00406 }

ULONG ExGetExclusiveWaiterCount IN PERESOURCE  Resource  ) 
 

Definition at line 2133 of file ex/resource.c.

References _ERESOURCE::NumberOfExclusiveWaiters, and Resource.

Referenced by MNAnimate().

02139 : 02140 02141 This routine returns the exclusive waiter count. 02142 02143 02144 Arguments: 02145 02146 Resource - Supplies a pointer to and executive resource. 02147 02148 Return Value: 02149 02150 The current number of exclusive waiters is returned as the function 02151 value. 02152 02153 --*/ 02154 02155 { 02156 return Resource->NumberOfExclusiveWaiters; 02157 }

ULONG ExGetSharedWaiterCount IN PERESOURCE  Resource  ) 
 

Definition at line 2160 of file ex/resource.c.

References _ERESOURCE::NumberOfSharedWaiters, and Resource.

Referenced by MNAnimate().

02166 : 02167 02168 This routine returns the shared waiter count. 02169 02170 02171 Arguments: 02172 02173 Resource - Supplies a pointer to and executive resource. 02174 02175 Return Value: 02176 02177 The current number of shared waiters is returned as the function 02178 value. 02179 02180 --*/ 02181 02182 { 02183 return Resource->NumberOfSharedWaiters; 02184 }

NTSTATUS ExInitializeResourceLite IN PERESOURCE  Resource  ) 
 

Definition at line 209 of file ex/resource.c.

References _RESOURCE_PERFORMANCE_DATA::ActiveResourceCount, _ERESOURCE::Address, ASSERT, _ERESOURCE::CreatorBackTraceIndex, ExInterlockedInsertTailList(), ExpResourceSpinLock, ExpSystemResourcesList, KeInitializeSpinLock(), MmDeterminePoolType(), NonPagedPool, NtGlobalFlag, Resource, RtlGetCallersAddress(), _ERESOURCE::SpinLock, _ERESOURCE::SystemResourcesList, and _RESOURCE_PERFORMANCE_DATA::TotalResourceCount.

Referenced by InitCreateUserCrit(), ObCreateObjectType(), and ObInitSystem().

00215 : 00216 00217 This routine initializes the specified resource. 00218 00219 Arguments: 00220 00221 Resource - Supplies a pointer to the resource to initialize. 00222 00223 Return Value: 00224 00225 STATUS_SUCCESS. 00226 00227 --*/ 00228 00229 { 00230 00231 PVOID CallersCaller; 00232 00233 ASSERT(MmDeterminePoolType(Resource) == NonPagedPool); 00234 00235 // 00236 // Initialize the specified resource. 00237 // 00238 // N.B. All fields are initialized to zero (NULL pointers) except 00239 // the list entry and spinlock. 00240 // 00241 00242 RtlZeroMemory(Resource, sizeof(ERESOURCE)); 00243 KeInitializeSpinLock(&Resource->SpinLock); 00244 00245 #if i386 && !FPO 00246 if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) { 00247 Resource->CreatorBackTraceIndex = RtlLogStackBackTrace(); 00248 } 00249 else { 00250 Resource->CreatorBackTraceIndex = 0; 00251 } 00252 #endif // i386 && !FPO 00253 ExInterlockedInsertTailList(&ExpSystemResourcesList, 00254 &Resource->SystemResourcesList, 00255 &ExpResourceSpinLock); 00256 00257 // 00258 // Initialize performance data entry for the resource. 00259 // 00260 00261 #if defined(_COLLECT_RESOURCE_DATA_) 00262 00263 RtlGetCallersAddress(&Resource->Address, &CallersCaller); 00264 ExpResourcePerformanceData.TotalResourceCount += 1; 00265 ExpResourcePerformanceData.ActiveResourceCount += 1; 00266 00267 #endif 00268 00269 return STATUS_SUCCESS; 00270 }

BOOLEAN ExIsResourceAcquiredExclusiveLite IN PERESOURCE  Resource  ) 
 

Definition at line 2187 of file ex/resource.c.

References ASSERT_RESOURCE, ERESOURCE_THREAD, FALSE, IsOwnedExclusive, _OWNER_ENTRY::OwnerThread, _ERESOURCE::OwnerThreads, PsGetCurrentThread, Resource, _ERESOURCE::SpinLock, and TRUE.

Referenced by RequestDeviceChange(), StartDeviceRead(), UpdateJob(), UserIsUserCritSecIn(), UserJobCallout(), and xxxUserFindHandleForObject().

02193 : 02194 02195 This routine determines if a resource is acquired exclusive by the 02196 calling thread. 02197 02198 Arguments: 02199 02200 Resource - Supplies a pointer the resource to query. 02201 02202 Return Value: 02203 02204 If the current thread has acquired the resource exclusive, a value of 02205 TRUE is returned. Otherwise, a value of FALSE is returned. 02206 02207 --*/ 02208 02209 { 02210 02211 ERESOURCE_THREAD CurrentThread; 02212 KIRQL OldIrql; 02213 BOOLEAN Result; 02214 02215 // 02216 // Acquire exclusive access to the specified resource. 02217 // 02218 02219 CurrentThread = (ERESOURCE_THREAD)PsGetCurrentThread(); 02220 ExAcquireFastLock(&Resource->SpinLock, &OldIrql); 02221 02222 ASSERT_RESOURCE(Resource); 02223 02224 // 02225 // If the resource is owned exclusive and the current thread is the 02226 // owner, then set the return value of TRUE. Otherwise, set the return 02227 // value to FALSE. 02228 // 02229 02230 Result = FALSE; 02231 if ((IsOwnedExclusive(Resource)) && 02232 (Resource->OwnerThreads[0].OwnerThread == CurrentThread)) { 02233 Result = TRUE; 02234 } 02235 02236 // 02237 // Release exclusive access to the specified resource. 02238 // 02239 02240 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 02241 return Result; 02242 }

ULONG ExIsResourceAcquiredSharedLite IN PERESOURCE  Resource  ) 
 

Definition at line 2245 of file ex/resource.c.

References ASSERT_RESOURCE, ERESOURCE_THREAD, Index, NULL, _OWNER_ENTRY::OwnerCount, _ERESOURCE::OwnerTable, _OWNER_ENTRY::OwnerThread, _ERESOURCE::OwnerThreads, PsGetCurrentThread, Resource, _ERESOURCE::SpinLock, and _OWNER_ENTRY::TableSize.

Referenced by UserIsUserCritSecIn(), and xxxUserFindHandleForObject().

02251 : 02252 02253 This routine determines if a resource is acquired either shared or 02254 exclusive by the calling thread. 02255 02256 Arguments: 02257 02258 Resource - Supplies a pointer to the resource to query. 02259 02260 Return Value: 02261 02262 If the current thread has not acquired the resource a value of zero 02263 is returned. Otherwise, the thread's acquire count is returned. 02264 02265 --*/ 02266 02267 { 02268 02269 ERESOURCE_THREAD CurrentThread; 02270 ULONG Index; 02271 ULONG Number; 02272 KIRQL OldIrql; 02273 POWNER_ENTRY OwnerEntry; 02274 ULONG Result; 02275 02276 // 02277 // Acquire exclusive access to the specified resource. 02278 // 02279 02280 CurrentThread = (ERESOURCE_THREAD)PsGetCurrentThread(); 02281 ExAcquireFastLock(&Resource->SpinLock, &OldIrql); 02282 02283 ASSERT_RESOURCE(Resource); 02284 02285 // 02286 // Find the current thread in the thread array and return the count. 02287 // 02288 // N.B. If the thread is not found a value of zero will be returned. 02289 // 02290 02291 if (Resource->OwnerThreads[0].OwnerThread == CurrentThread) { 02292 Result = Resource->OwnerThreads[0].OwnerCount; 02293 02294 } else if (Resource->OwnerThreads[1].OwnerThread == CurrentThread) { 02295 Result = Resource->OwnerThreads[1].OwnerCount; 02296 02297 } else { 02298 02299 // 02300 // If the resource hint is not within range or the resource table 02301 // entry does not match the current thread, then search the owner 02302 // table for a match. 02303 // 02304 02305 OwnerEntry = Resource->OwnerTable; 02306 Result = 0; 02307 if (OwnerEntry != NULL) { 02308 Index = ((PKTHREAD)(CurrentThread))->ResourceIndex; 02309 Number = OwnerEntry->TableSize; 02310 if ((Index >= Number) || 02311 (OwnerEntry[Index].OwnerThread != CurrentThread)) { 02312 for (Index = 1; Index < Number; Index += 1) { 02313 OwnerEntry += 1; 02314 if (OwnerEntry->OwnerThread == CurrentThread) { 02315 Result = OwnerEntry->OwnerCount; 02316 break; 02317 } 02318 } 02319 02320 } else { 02321 Result = OwnerEntry[Index].OwnerCount; 02322 } 02323 } 02324 } 02325 02326 // 02327 // Release exclusive access to the specified resource. 02328 // 02329 02330 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 02331 return Result; 02332 }

BOOLEAN FASTCALL ExpAcquireResourceExclusiveLite IN PERESOURCE  Resource,
IN KIRQL  OldIrql
 

Definition at line 410 of file ex/resource.c.

References ERESOURCE_THREAD, Event(), ExAcquireResourceExclusiveLite(), ExAllocatePoolWithTag, _ERESOURCE::ExclusiveWaiters, ExpWaitForResource(), FALSE, KeInitializeEvent, NonPagedPoolMustSucceed, NULL, _ERESOURCE::NumberOfExclusiveWaiters, _OWNER_ENTRY::OwnerThread, _ERESOURCE::OwnerThreads, PsGetCurrentThread, Resource, _ERESOURCE::SpinLock, and TRUE.

Referenced by ExAcquireResourceExclusiveLite().

00417 : 00418 00419 This routine acquires the specified resource for exclusive access. 00420 00421 N.B. This routine uses fast locking. 00422 00423 N.B. This routine is called with the fast lock for the resource 00424 held. 00425 00426 Arguments: 00427 00428 Resource - Supplies a pointer to the resource that is acquired 00429 for exclusive access. 00430 00431 OldIrql - Supplies the previous IRQL. 00432 00433 Return Value: 00434 00435 BOOLEAN - TRUE if the resource is acquired and FALSE otherwise. 00436 00437 --*/ 00438 00439 { 00440 00441 PKEVENT Event; 00442 00443 // 00444 // If the exclusive wait event has not yet been allocated, then the 00445 // long path code must be taken. 00446 // 00447 00448 if (Resource->ExclusiveWaiters == NULL) { 00449 00450 // 00451 // Allocate an exclusive wait event. 00452 // 00453 // N.B. This path is not optimal, but is only ever executed once 00454 // per resource. 00455 // 00456 00457 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 00458 ExAcquireSpinLock(&Resource->SpinLock, &OldIrql); 00459 if (Resource->ExclusiveWaiters == NULL) { 00460 Event = ExAllocatePoolWithTag(NonPagedPoolMustSucceed, 00461 sizeof(KEVENT), 00462 'vEeR'); 00463 00464 KeInitializeEvent(Event, SynchronizationEvent, FALSE); 00465 Resource->ExclusiveWaiters = Event; 00466 } 00467 00468 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 00469 return ExAcquireResourceExclusiveLite(Resource, TRUE); 00470 } 00471 00472 // 00473 // Wait for exclusive access to the resource to be granted and set the 00474 // owner thread. 00475 // 00476 00477 Resource->NumberOfExclusiveWaiters += 1; 00478 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 00479 ExpWaitForResource(Resource, Resource->ExclusiveWaiters); 00480 00481 // 00482 // N.B. It is "safe" to store the owner thread without obtaining any 00483 // locks since the thread has already been granted exclusive 00484 // ownership. 00485 // 00486 00487 Resource->OwnerThreads[0].OwnerThread = (ERESOURCE_THREAD)PsGetCurrentThread(); 00488 return TRUE; 00489 }

VOID FASTCALL ExpBoostOwnerThread IN PKTHREAD  CurrentThread,
IN PKTHREAD  OwnerThread
 

Definition at line 2453 of file ex/resource.c.

References KiSetPriorityThread(), and ROUND_TRIP_DECREMENT_COUNT.

Referenced by ExpWaitForResource().

02459 : 02460 02461 This function boots the priority of the specified owner thread iff 02462 its priority is less than that of the current thread and is also 02463 less than fourteen. 02464 02465 N.B. this function is called with the dispatcher database lock held. 02466 02467 Arguments: 02468 02469 CurrentThread - Supplies a pointer to the current thread object. 02470 02471 OwnerThread - Supplies a pointer to the owner thread object. 02472 02473 Return Value: 02474 02475 None. 02476 02477 --*/ 02478 02479 { 02480 02481 // 02482 // If the owner thread is lower priority than the current thread, the 02483 // current thread is running at a priority less than 14, then boost the 02484 // priority of the owner thread for a quantum. 02485 // 02486 // N.B. A thread that has already been boosted may be reboosted to allow 02487 // it to execute and release resources. When the boost is removed, 02488 // the thread will return to its priority before any boosting. 02489 // 02490 02491 if (((ULONG_PTR)OwnerThread & 0x3) == 0) { 02492 if ((OwnerThread->Priority < CurrentThread->Priority) && 02493 (OwnerThread->Priority < 14)) { 02494 OwnerThread->PriorityDecrement += 14 - OwnerThread->Priority; 02495 OwnerThread->DecrementCount = ROUND_TRIP_DECREMENT_COUNT; 02496 KiSetPriorityThread(OwnerThread, 14); 02497 OwnerThread->Quantum = OwnerThread->ApcState.Process->ThreadQuantum; 02498 } 02499 } 02500 02501 return; 02502 }

PVOID ExpCheckForResource IN PVOID  p,
IN ULONG  Size
 

Definition at line 2894 of file ex/resource.c.

References DbgPrint, ExpResourceSpinLock, ExpSystemResourcesList, KeNumberProcessors, NULL, Resource, and Size.

Referenced by ExFreePoolSanityChecks(), and MmUnloadSystemImage().

02899 { 02900 02901 KIRQL OldIrql; 02902 PLIST_ENTRY Head, Next; 02903 PERESOURCE Resource; 02904 PCHAR BeginBlock; 02905 PCHAR EndBlock; 02906 02907 // 02908 // This can cause a deadlock on MP machines. 02909 // 02910 02911 if (KeNumberProcessors > 1) { 02912 return NULL; 02913 } 02914 02915 BeginBlock = (PCHAR)p; 02916 EndBlock = (PCHAR)p + Size; 02917 02918 ExAcquireSpinLock( &ExpResourceSpinLock, &OldIrql ); 02919 Head = &ExpSystemResourcesList; 02920 Next = Head->Flink; 02921 while (Next != Head) { 02922 Resource = CONTAINING_RECORD( Next, 02923 ERESOURCE, 02924 SystemResourcesList 02925 ); 02926 02927 if ((PCHAR)Resource >= BeginBlock && (PCHAR)Resource < EndBlock) { 02928 DbgPrint( "EX: ExFreePool( %lx, %lx ) contains an ERESOURCE structure that has not been ExDeleteResourced\n", 02929 p, Size 02930 ); 02931 DbgBreakPoint(); 02932 ExReleaseSpinLock( &ExpResourceSpinLock, OldIrql ); 02933 return (PVOID)Resource; 02934 } 02935 02936 Next = Next->Flink; 02937 } 02938 02939 ExReleaseSpinLock( &ExpResourceSpinLock, OldIrql ); 02940 return NULL; 02941 }

POWNER_ENTRY FASTCALL ExpFindCurrentThread IN PERESOURCE  Resource,
IN ERESOURCE_THREAD  CurrentThread
 

Definition at line 2683 of file ex/resource.c.

References ASSERT_RESOURCE, ExAllocatePoolWithTag, ExFreePool(), ExpIncrementCounter, KeBugCheck(), KeGetCurrentThread, KiLockDispatcherDatabase, KiUnlockDispatcherDatabase(), _RESOURCE_PERFORMANCE_DATA::MaximumTableExpand, NonPagedPool, NonPagedPoolMustSucceed, NULL, OWNER_ENTRY, _ERESOURCE::OwnerTable, _OWNER_ENTRY::OwnerThread, _ERESOURCE::OwnerThreads, PAGE_SIZE, Resource, and _OWNER_ENTRY::TableSize.

Referenced by ExAcquireResourceSharedLite(), ExAcquireSharedStarveExclusive(), and ExAcquireSharedWaitForExclusive().

02690 : 02691 02692 This function searches for the specified thread in the resource 02693 thread array. If the thread is located, then a pointer to the 02694 array entry is returned as the function value. Otherwise, a pointer 02695 to a free entry is returned. 02696 02697 Arguments: 02698 02699 Resource - Supplies a pointer to the resource for which the search 02700 is performed. 02701 02702 CurrentThread - Supplies the identification of the thread to search 02703 for. 02704 02705 Return Value: 02706 02707 A pointer to an owner entry is returned. 02708 02709 --*/ 02710 02711 { 02712 02713 POWNER_ENTRY FreeEntry; 02714 ULONG NewSize; 02715 ULONG OldSize; 02716 POWNER_ENTRY OwnerEntry; 02717 POWNER_ENTRY OwnerBound; 02718 POWNER_ENTRY OwnerTable, OldTable; 02719 KIRQL OldIrql; 02720 02721 // 02722 // Search the owner threads for the specified thread and return either 02723 // a pointer to the found thread or a pointer to a free thread table 02724 // entry. 02725 // 02726 02727 if (Resource->OwnerThreads[0].OwnerThread == CurrentThread) { 02728 return &Resource->OwnerThreads[0]; 02729 02730 } else if (Resource->OwnerThreads[1].OwnerThread == CurrentThread) { 02731 return &Resource->OwnerThreads[1]; 02732 02733 } else { 02734 FreeEntry = NULL; 02735 if (Resource->OwnerThreads[1].OwnerThread == 0) { 02736 FreeEntry = &Resource->OwnerThreads[1]; 02737 } 02738 02739 OwnerEntry = Resource->OwnerTable; 02740 if (OwnerEntry == NULL) { 02741 OldSize = 0; 02742 02743 } else { 02744 OldSize = OwnerEntry->TableSize; 02745 OwnerBound = &OwnerEntry[OldSize]; 02746 OwnerEntry += 1; 02747 do { 02748 if (OwnerEntry->OwnerThread == CurrentThread) { 02749 KeGetCurrentThread()->ResourceIndex = (UCHAR)(OwnerEntry - Resource->OwnerTable); 02750 return OwnerEntry; 02751 } 02752 02753 if ((FreeEntry == NULL) && 02754 (OwnerEntry->OwnerThread == 0)) { 02755 FreeEntry = OwnerEntry; 02756 } 02757 02758 OwnerEntry += 1; 02759 } while (OwnerEntry != OwnerBound); 02760 } 02761 } 02762 02763 // 02764 // If a free entry was found in the table, then return the address of the 02765 // free entry. Otherwise, expand the size of the owner thread table. 02766 // 02767 02768 if (FreeEntry != NULL) { 02769 KeGetCurrentThread()->ResourceIndex = (UCHAR)(FreeEntry - Resource->OwnerTable); 02770 return FreeEntry; 02771 } 02772 02773 // 02774 // Allocate an expanded owner table. 02775 // 02776 02777 ExpIncrementCounter(OwnerTableExpands); 02778 if (OldSize == 0 ) { 02779 NewSize = 3; 02780 02781 } else { 02782 NewSize = OldSize + 4; 02783 } 02784 02785 if (NewSize * sizeof(OWNER_ENTRY) <= PAGE_SIZE) { 02786 02787 OwnerTable = (POWNER_ENTRY)ExAllocatePoolWithTag( 02788 NonPagedPoolMustSucceed, 02789 NewSize * sizeof(OWNER_ENTRY), 02790 'aTeR'); 02791 } 02792 else { 02793 02794 // 02795 // If allocation is bigger than one page we need to 02796 // allocate from normal pool. If we fail then we will 02797 // bugcheck with `must_succeed_pool_empty' because logically 02798 // this is what we do. 02799 // 02800 02801 OwnerTable = (POWNER_ENTRY)ExAllocatePoolWithTag( 02802 NonPagedPool, 02803 NewSize * sizeof(OWNER_ENTRY), 02804 'aTeR'); 02805 02806 if (OwnerTable == NULL) { 02807 02808 KeBugCheck (MUST_SUCCEED_POOL_EMPTY); 02809 } 02810 02811 } 02812 02813 // 02814 // Zero the expanded owner table, compute the address of the owner 02815 // count and thread tables, and copy the old table to the new table. 02816 // 02817 02818 RtlZeroMemory((PVOID)(OwnerTable + OldSize), 02819 (NewSize - OldSize) * sizeof(OWNER_ENTRY)); 02820 02821 RtlCopyMemory((PVOID)OwnerTable, 02822 Resource->OwnerTable, 02823 OldSize * sizeof(OWNER_ENTRY)); 02824 02825 // 02826 // If an expanded table was previously allocated, then save it so it can be freed. 02827 // 02828 OldTable = Resource->OwnerTable; 02829 02830 // 02831 // Set new owner table parameters and return the address of the first 02832 // free entry. We need the dispatcher lock here to prevent table expansion while we are boosting 02833 // thread priorities. 02834 // 02835 KiLockDispatcherDatabase(&OldIrql); 02836 OwnerTable->TableSize = NewSize; 02837 Resource->OwnerTable = OwnerTable; 02838 KiUnlockDispatcherDatabase(OldIrql); 02839 02840 if (OldTable != NULL) { 02841 ExFreePool(OldTable); 02842 } 02843 02844 ASSERT_RESOURCE(Resource); 02845 02846 #if defined(_COLLECT_RESOURCE_DATA_) 02847 02848 if (NewSize > ExpResourcePerformanceData.MaximumTableExpand) { 02849 ExpResourcePerformanceData.MaximumTableExpand = NewSize; 02850 } 02851 02852 #endif 02853 02854 if (OldSize == 0) { 02855 OldSize = 1; 02856 } 02857 02858 KeGetCurrentThread()->ResourceIndex = (CCHAR)OldSize; 02859 return &OwnerTable[OldSize]; 02860 }

BOOLEAN ExpResourceInitialization VOID   ) 
 

Definition at line 150 of file ex/resource.c.

References _RESOURCE_PERFORMANCE_DATA::ActiveResourceCount, _RESOURCE_PERFORMANCE_DATA::ExclusiveAcquire, ExpResourceSpinLock, ExpSystemResourcesList, ExpTimeout, _RESOURCE_PERFORMANCE_DATA::HashTable, Index, KeInitializeSpinLock(), _RESOURCE_PERFORMANCE_DATA::MaximumTableExpand, _RESOURCE_PERFORMANCE_DATA::OwnerTableExpands, RESOURCE_HASH_TABLE_SIZE, _RESOURCE_PERFORMANCE_DATA::SharedFirstLevel, _RESOURCE_PERFORMANCE_DATA::SharedSecondLevel, _RESOURCE_PERFORMANCE_DATA::StarveFirstLevel, _RESOURCE_PERFORMANCE_DATA::StarveSecondLevel, _RESOURCE_PERFORMANCE_DATA::TotalResourceCount, TRUE, and _RESOURCE_PERFORMANCE_DATA::WaitForExclusive.

00156 : 00157 00158 This function initializes global data during system initialization. 00159 00160 Arguments: 00161 00162 None. 00163 00164 Return Value: 00165 00166 BOOLEAN - TRUE 00167 00168 --*/ 00169 00170 { 00171 00172 ULONG Index; 00173 00174 // 00175 // Initialize resource timeout value, the system resource listhead, 00176 // and the resource spinlock. 00177 // 00178 00179 ExpTimeout.QuadPart = Int32x32To64(4 * 1000, -10000); 00180 InitializeListHead(&ExpSystemResourcesList); 00181 KeInitializeSpinLock(&ExpResourceSpinLock); 00182 00183 // 00184 // Initialize resource performance data. 00185 // 00186 00187 #if defined(_COLLECT_RESOURCE_DATA_) 00188 00189 ExpResourcePerformanceData.ActiveResourceCount = 0; 00190 ExpResourcePerformanceData.TotalResourceCount = 0; 00191 ExpResourcePerformanceData.ExclusiveAcquire = 0; 00192 ExpResourcePerformanceData.SharedFirstLevel = 0; 00193 ExpResourcePerformanceData.SharedSecondLevel = 0; 00194 ExpResourcePerformanceData.StarveFirstLevel = 0; 00195 ExpResourcePerformanceData.StarveSecondLevel = 0; 00196 ExpResourcePerformanceData.WaitForExclusive = 0; 00197 ExpResourcePerformanceData.OwnerTableExpands = 0; 00198 ExpResourcePerformanceData.MaximumTableExpand = 0; 00199 for (Index = 0; Index < RESOURCE_HASH_TABLE_SIZE; Index += 1) { 00200 InitializeListHead(&ExpResourcePerformanceData.HashTable[Index]); 00201 } 00202 00203 #endif 00204 00205 return TRUE; 00206 }

VOID FASTCALL ExpWaitForResource IN PERESOURCE  Resource,
IN PVOID  Object
 

Definition at line 2506 of file ex/resource.c.

References _ERESOURCE::ActiveCount, _ERESOURCE::ContentionCount, DbgPrint, Executive, ExpBoostOwnerThread(), ExpResourceTimeoutCount, ExpTimeout, FALSE, Index, IsBoostAllowed, IsExclusiveWaiting, IsOwnedExclusive, IsSharedWaiting, KeGetCurrentThread, KernelMode, KeWaitForSingleObject(), KiLockDispatcherDatabase, NTSTATUS(), NULL, _ERESOURCE::NumberOfExclusiveWaiters, _OWNER_ENTRY::OwnerCount, _ERESOURCE::OwnerTable, _OWNER_ENTRY::OwnerThread, _ERESOURCE::OwnerThreads, Resource, _ERESOURCE::SpinLock, Status, _OWNER_ENTRY::TableSize, TRUE, _KTHREAD::WaitIrql, and _KTHREAD::WaitNext.

Referenced by ExAcquireResourceSharedLite(), ExAcquireSharedStarveExclusive(), ExAcquireSharedWaitForExclusive(), and ExpAcquireResourceExclusiveLite().

02512 : 02513 02514 The routine waits for the specified resource object to be set. If the 02515 wait is too long the priority of the current owners of the resource 02516 are boosted. 02517 02518 Arguments: 02519 02520 Resource - Supplies a pointer to the resource to wait for. 02521 02522 Object - Supplies a pointer to an event (exclusive) or semaphore 02523 (shared) to wait for. 02524 02525 Return Value: 02526 02527 None. 02528 02529 --*/ 02530 02531 { 02532 02533 ULONG Index; 02534 ULONG Limit; 02535 ULONG Number; 02536 KIRQL OldIrql; 02537 POWNER_ENTRY OwnerEntry; 02538 PKTHREAD OwnerThread; 02539 NTSTATUS Status; 02540 PKTHREAD CurrentThread; 02541 LARGE_INTEGER Timeout; 02542 02543 // 02544 // Increment the contention count for the resource, set the initial 02545 // timeout value, and wait for the specified object to be signalled 02546 // or a timeout to occur. 02547 // 02548 02549 Limit = 0; 02550 Resource->ContentionCount += 1; 02551 Timeout.QuadPart = 500 * -10000; 02552 do { 02553 Status = KeWaitForSingleObject ( 02554 Object, 02555 Executive, 02556 KernelMode, 02557 FALSE, 02558 &Timeout ); 02559 02560 if (Status != STATUS_TIMEOUT) { 02561 break; 02562 } 02563 02564 // 02565 // The limit has been exceeded, then output status information. 02566 // 02567 02568 Limit += 1; 02569 Timeout = ExpTimeout; 02570 if (Limit > ExpResourceTimeoutCount) { 02571 Limit = 0; 02572 02573 // 02574 // Output information for the specified resource. 02575 // 02576 02577 ExAcquireSpinLock(&Resource->SpinLock, &OldIrql); 02578 DbgPrint("Resource @ %lx\n", Resource); 02579 DbgPrint(" ActiveCount = %04lx Flags = %s%s%s\n", 02580 Resource->ActiveCount, 02581 IsOwnedExclusive(Resource) ? "IsOwnedExclusive " : "", 02582 IsSharedWaiting(Resource) ? "SharedWaiter " : "", 02583 IsExclusiveWaiting(Resource) ? "ExclusiveWaiter " : ""); 02584 02585 DbgPrint(" NumberOfExclusiveWaiters = %04lx\n", Resource->NumberOfExclusiveWaiters); 02586 02587 DbgPrint(" Thread = %08lx, Count = %02x\n", 02588 Resource->OwnerThreads[0].OwnerThread, 02589 Resource->OwnerThreads[0].OwnerCount); 02590 02591 DbgPrint(" Thread = %08lx, Count = %02x\n", 02592 Resource->OwnerThreads[1].OwnerThread, 02593 Resource->OwnerThreads[1].OwnerCount); 02594 02595 OwnerEntry = Resource->OwnerTable; 02596 if (OwnerEntry != NULL) { 02597 Number = OwnerEntry->TableSize; 02598 for(Index = 1; Index < Number; Index += 1) { 02599 OwnerEntry += 1; 02600 DbgPrint(" Thread = %08lx, Count = %02x\n", 02601 OwnerEntry->OwnerThread, 02602 OwnerEntry->OwnerCount); 02603 } 02604 } 02605 02606 DbgBreakPoint(); 02607 DbgPrint("EX - Rewaiting\n"); 02608 ExReleaseSpinLock(&Resource->SpinLock, OldIrql); 02609 } 02610 02611 // 02612 // If priority boosts are allowed, then attempt to boost the priority 02613 // of owner threads. 02614 // 02615 02616 if (IsBoostAllowed(Resource)) { 02617 02618 // 02619 // Get the current thread address, lock the dispatcher database, 02620 // and set wait next in the current thread so the dispatcher 02621 // database lock does not need to be released before waiting 02622 // for the resource. 02623 // 02624 // N.B. Since the dispatcher database lock instead of the resource 02625 // lock is being used to synchronize access to the resource, 02626 // it is possible for the information being read from the 02627 // resource to be stale. However, the important thing that 02628 // cannot change is a valid thread address. Thus a thread 02629 // could possibly get boosted that actually has dropped its 02630 // access to the resource, but it guaranteed that the thread 02631 // cannot be terminated or otherwise deleted. 02632 // 02633 // N.B. The dispatcher lock is released by the wait at the top of 02634 // loop. 02635 // 02636 02637 CurrentThread = KeGetCurrentThread(); 02638 02639 KiLockDispatcherDatabase(&CurrentThread->WaitIrql); 02640 CurrentThread->WaitNext = TRUE; 02641 02642 // 02643 // Attempt to boost the one owner that can be shared or exclusive. 02644 // 02645 02646 OwnerThread = (PKTHREAD)Resource->OwnerThreads[0].OwnerThread; 02647 if (OwnerThread != NULL) { 02648 ExpBoostOwnerThread(CurrentThread, OwnerThread); 02649 } 02650 02651 // 02652 // If the specified resource is not owned exclusive, then attempt 02653 // to boost all the owning shared threads priority. 02654 // 02655 02656 if (!IsOwnedExclusive(Resource)) { 02657 OwnerThread = (PKTHREAD)Resource->OwnerThreads[1].OwnerThread; 02658 if (OwnerThread != NULL) { 02659 ExpBoostOwnerThread(CurrentThread, OwnerThread); 02660 } 02661 02662 OwnerEntry = Resource->OwnerTable; 02663 if (OwnerEntry != NULL) { 02664 Number = OwnerEntry->TableSize; 02665 for(Index = 1; Index < Number; Index += 1) { 02666 OwnerEntry += 1; 02667 OwnerThread = (PKTHREAD)OwnerEntry->OwnerThread; 02668 if (OwnerThread != NULL) { 02669 ExpBoostOwnerThread(CurrentThread, OwnerThread); 02670 } 02671 } 02672 } 02673 } 02674 } 02675 02676 } while (TRUE); 02677 02678 return; 02679 }

NTSTATUS ExQuerySystemLockInformation OUT PRTL_PROCESS_LOCKS  LockInformation,
IN ULONG  LockInformationLength,
OUT PULONG ReturnLength  OPTIONAL
 

Definition at line 2335 of file ex/resource.c.

References _ERESOURCE::ActiveCount, _NTDDK_ERESOURCE::ActiveCount, _ETHREAD::Cid, _ERESOURCE::ContentionCount, _NTDDK_ERESOURCE::ContentionCount, _NTDDK_ERESOURCE::CreatorBackTraceIndex, _ERESOURCE::CreatorBackTraceIndex, ExpResourceSpinLock, ExpSystemResourcesList, _NTDDK_ERESOURCE::InitialOwnerThreads, NTSTATUS(), NULL, _ERESOURCE::NumberOfExclusiveWaiters, _NTDDK_ERESOURCE::NumberOfExclusiveWaiters, _ERESOURCE::NumberOfSharedWaiters, _NTDDK_ERESOURCE::NumberOfSharedWaiters, _OWNER_ENTRY::OwnerThread, _ERESOURCE::OwnerThreads, _NTDDK_ERESOURCE::OwnerThreads, PNTDDK_ERESOURCE, Resource, Status, and USHORT.

Referenced by ExpGetLockInformation().

02341 { 02342 02343 NTSTATUS Status; 02344 KIRQL OldIrql; 02345 ULONG RequiredLength; 02346 PLIST_ENTRY Head, Next; 02347 PRTL_PROCESS_LOCK_INFORMATION LockInfo; 02348 PERESOURCE Resource; 02349 PNTDDK_ERESOURCE NtDdkResource; 02350 PETHREAD OwningThread; 02351 02352 RequiredLength = FIELD_OFFSET(RTL_PROCESS_LOCKS, Locks); 02353 if (LockInformationLength < RequiredLength) { 02354 Status = STATUS_INFO_LENGTH_MISMATCH; 02355 02356 } else { 02357 Status = STATUS_SUCCESS; 02358 ExAcquireSpinLock(&ExpResourceSpinLock, &OldIrql); 02359 try { 02360 LockInformation->NumberOfLocks = 0; 02361 LockInfo = &LockInformation->Locks[0]; 02362 Head = &ExpSystemResourcesList; 02363 Next = Head->Flink; 02364 while (Next != Head) { 02365 Resource = CONTAINING_RECORD(Next, 02366 ERESOURCE, 02367 SystemResourcesList); 02368 02369 LockInformation->NumberOfLocks += 1; 02370 RequiredLength += sizeof(RTL_PROCESS_LOCK_INFORMATION); 02371 02372 // 02373 // Detect if this is an NtDdk resource. New lite resources 02374 // never contain pointers to themselves. 02375 // 02376 02377 NtDdkResource = (PNTDDK_ERESOURCE)Resource; 02378 if (NtDdkResource->OwnerThreads != &NtDdkResource->InitialOwnerThreads[0]) { 02379 NtDdkResource = NULL; 02380 } 02381 02382 if (LockInformationLength < RequiredLength) { 02383 Status = STATUS_INFO_LENGTH_MISMATCH; 02384 02385 } else { 02386 LockInfo->Address = Resource; 02387 LockInfo->Type = RTL_RESOURCE_TYPE; 02388 LockInfo->CreatorBackTraceIndex = 0; 02389 #if i386 && !FPO 02390 if (NtDdkResource) { 02391 LockInfo->CreatorBackTraceIndex = (USHORT)NtDdkResource->CreatorBackTraceIndex; 02392 } else { 02393 LockInfo->CreatorBackTraceIndex = (USHORT)Resource->CreatorBackTraceIndex; 02394 } 02395 #endif // i386 && !FPO 02396 02397 if (NtDdkResource) { 02398 if ((NtDdkResource->OwnerThreads[0] != 0) && 02399 ((NtDdkResource->OwnerThreads[0] & 3) == 0)) { 02400 OwningThread = (PETHREAD)(NtDdkResource->OwnerThreads[0]); 02401 LockInfo->OwningThread = OwningThread->Cid.UniqueThread; 02402 02403 } else { 02404 LockInfo->OwningThread = 0; 02405 } 02406 02407 LockInfo->LockCount = NtDdkResource->ActiveCount; 02408 LockInfo->ContentionCount = NtDdkResource->ContentionCount; 02409 LockInfo->NumberOfWaitingShared = NtDdkResource->NumberOfSharedWaiters; 02410 LockInfo->NumberOfWaitingExclusive = NtDdkResource->NumberOfExclusiveWaiters; 02411 02412 } else { 02413 if ((Resource->OwnerThreads[0].OwnerThread != 0) && 02414 ((Resource->OwnerThreads[0].OwnerThread & 3) == 0)) { 02415 OwningThread = (PETHREAD)(Resource->OwnerThreads[0].OwnerThread); 02416 LockInfo->OwningThread = OwningThread->Cid.UniqueThread; 02417 02418 } else { 02419 LockInfo->OwningThread = 0; 02420 } 02421 02422 LockInfo->LockCount = Resource->ActiveCount; 02423 LockInfo->ContentionCount = Resource->ContentionCount; 02424 LockInfo->NumberOfWaitingShared = Resource->NumberOfSharedWaiters; 02425 LockInfo->NumberOfWaitingExclusive = Resource->NumberOfExclusiveWaiters; 02426 } 02427 02428 LockInfo += 1; 02429 } 02430 02431 if (Next == Next->Flink) { 02432 Next = Head; 02433 02434 } else { 02435 Next = Next->Flink; 02436 } 02437 } 02438 02439 } finally { 02440 ExReleaseSpinLock(&ExpResourceSpinLock, OldIrql); 02441 } 02442 } 02443 02444 if (ARGUMENT_PRESENT(ReturnLength)) { 02445 *ReturnLength = RequiredLength; 02446 } 02447 02448 return Status; 02449 }

NTSTATUS ExReinitializeResourceLite IN PERESOURCE  Resource  ) 
 

Definition at line 273 of file ex/resource.c.

References _ERESOURCE::ActiveCount, ASSERT, _ERESOURCE::ContentionCount, Event(), _ERESOURCE::ExclusiveWaiters, FALSE, _ERESOURCE::Flag, Index, KeInitializeEvent, KeInitializeSemaphore(), KeInitializeSpinLock(), MmDeterminePoolType(), NonPagedPool, NULL, _ERESOURCE::NumberOfExclusiveWaiters, _ERESOURCE::NumberOfSharedWaiters, _OWNER_ENTRY::OwnerCount, _ERESOURCE::OwnerTable, _OWNER_ENTRY::OwnerThread, _ERESOURCE::OwnerThreads, Resource, _ERESOURCE::SharedWaiters, _ERESOURCE::SpinLock, and _OWNER_ENTRY::TableSize.

00279 : 00280 00281 This routine reinitializes the specified resource. 00282 00283 Arguments: 00284 00285 Resource - Supplies a pointer to the resource to initialize. 00286 00287 Return Value: 00288 00289 STATUS_SUCCESS. 00290 00291 --*/ 00292 00293 { 00294 00295 PKEVENT Event; 00296 ULONG Index; 00297 POWNER_ENTRY OwnerTable; 00298 PKSEMAPHORE Semaphore; 00299 ULONG TableSize; 00300 00301 ASSERT(MmDeterminePoolType(Resource) == NonPagedPool); 00302 00303 // 00304 // If the resource has an owner table, then zero the owner table. 00305 // 00306 00307 OwnerTable = Resource->OwnerTable; 00308 if (OwnerTable != NULL) { 00309 TableSize = OwnerTable->TableSize; 00310 for (Index = 1; Index < TableSize; Index += 1) { 00311 OwnerTable[Index].OwnerThread = 0; 00312 OwnerTable[Index].OwnerCount = 0; 00313 } 00314 } 00315 00316 // 00317 // Set the active count and flags to zero. 00318 // 00319 00320 Resource->ActiveCount = 0; 00321 Resource->Flag = 0; 00322 00323 // 00324 // If the resource has a shared waiter semaphore, then reinitialize 00325 // it. 00326 // 00327 00328 Semaphore = Resource->SharedWaiters; 00329 if (Semaphore != NULL) { 00330 KeInitializeSemaphore(Semaphore, 0, MAXLONG); 00331 } 00332 00333 // 00334 // If the resource has a exclusive waiter event, then reinitialize 00335 // it. 00336 // 00337 00338 Event = Resource->ExclusiveWaiters; 00339 if (Event != NULL) { 00340 KeInitializeEvent(Event, SynchronizationEvent, FALSE); 00341 } 00342 00343 // 00344 // Initialize the builtin owner table. 00345 // 00346 00347 Resource->OwnerThreads[0].OwnerThread = 0; 00348 Resource->OwnerThreads[0].OwnerCount = 0; 00349 Resource->OwnerThreads[1].OwnerThread = 0; 00350 Resource->OwnerThreads[1].OwnerCount = 0; 00351 00352 // 00353 // Set the contention count, number of shared waiters, and number 00354 // of exclusive waiters to zero. 00355 // 00356 00357 Resource->ContentionCount = 0; 00358 Resource->NumberOfSharedWaiters = 0; 00359 Resource->NumberOfExclusiveWaiters = 0; 00360 00361 // 00362 // Reinitialize the resource spinlock. 00363 // 00364 00365 KeInitializeSpinLock(&Resource->SpinLock); 00366 return STATUS_SUCCESS; 00367 }

VOID ExReleaseResourceForThreadLite IN PERESOURCE  Resource,
IN ERESOURCE_THREAD  CurrentThread
 

Definition at line 1607 of file ex/resource.c.

References _ERESOURCE::ActiveCount, ASSERT, ASSERT_RESOURCE, _ERESOURCE::ExclusiveWaiters, FALSE, _ERESOURCE::Flag, Index, IsExclusiveWaiting, IsOwnedExclusive, IsSharedWaiting, KeReleaseSemaphore(), KeSetEventBoostPriority(), NULL, _ERESOURCE::NumberOfExclusiveWaiters, _ERESOURCE::NumberOfSharedWaiters, _OWNER_ENTRY::OwnerCount, _ERESOURCE::OwnerTable, _OWNER_ENTRY::OwnerThread, _ERESOURCE::OwnerThreads, Resource, ResourceOwnedExclusive, _ERESOURCE::SharedWaiters, SHORT, _ERESOURCE::SpinLock, _OWNER_ENTRY::TableSize, and TRUE.

01614 : 01615 01616 This routine release the specified resource for the specified thread 01617 and decrements the recursion count. If the count reaches zero, then 01618 the resource may also be released. 01619 01620 N.B. This routine uses fast locking. 01621 01622 Arguments: 01623 01624 Resource - Supplies a pointer to the resource to release. 01625 01626 Thread - Supplies the thread that originally acquired the resource. 01627 01628 Return Value: 01629 01630 None. 01631 01632 --*/ 01633 01634 { 01635 01636 ULONG Index; 01637 ULONG Number; 01638 KIRQL OldIrql; 01639 POWNER_ENTRY OwnerEntry; 01640 01641 ASSERT(CurrentThread != 0); 01642 01643 // 01644 // Acquire exclusive access to the specified resource. 01645 // 01646 01647 ExAcquireFastLock(&Resource->SpinLock, &OldIrql); 01648 01649 ASSERT_RESOURCE(Resource); 01650 01651 // 01652 // If the resource is exclusively owned, then release exclusive 01653 // ownership. Otherwise, release shared ownership. 01654 // 01655 // N.B. The two release paths are split since this is such a high 01656 // frequency function. 01657 // 01658 01659 if (IsOwnedExclusive(Resource)) { 01660 01661 ASSERT(Resource->OwnerThreads[0].OwnerThread == CurrentThread); 01662 01663 // 01664 // Decrement the recursion count and check if ownership can be 01665 // released. 01666 // 01667 01668 ASSERT(Resource->OwnerThreads[0].OwnerCount > 0); 01669 01670 if (--Resource->OwnerThreads[0].OwnerCount != 0) { 01671 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 01672 return; 01673 } 01674 01675 // 01676 // Clear the owner thread. 01677 // 01678 01679 Resource->OwnerThreads[0].OwnerThread = 0; 01680 01681 // 01682 // The thread recursion count reached zero so decrement the resource 01683 // active count. If the active count reaches zero, then the resource 01684 // is no longer owned and an attempt should be made to grant access to 01685 // another thread. 01686 // 01687 01688 ASSERT(Resource->ActiveCount > 0); 01689 01690 if (--Resource->ActiveCount == 0) { 01691 01692 // 01693 // If there are shared waiters, then grant shared access to the 01694 // resource. Otherwise, grant exclusive ownership if there are 01695 // exclusive waiters. 01696 // 01697 01698 if (IsSharedWaiting(Resource)) { 01699 Resource->Flag &= ~ResourceOwnedExclusive; 01700 Number = Resource->NumberOfSharedWaiters; 01701 Resource->ActiveCount = (SHORT)Number; 01702 Resource->NumberOfSharedWaiters = 0; 01703 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 01704 KeReleaseSemaphore(Resource->SharedWaiters, 0, Number, FALSE); 01705 return; 01706 01707 } else if (IsExclusiveWaiting(Resource)) { 01708 Resource->OwnerThreads[0].OwnerThread = 1; 01709 Resource->OwnerThreads[0].OwnerCount = 1; 01710 Resource->ActiveCount = 1; 01711 Resource->NumberOfExclusiveWaiters -= 1; 01712 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 01713 KeSetEventBoostPriority(Resource->ExclusiveWaiters, 01714 (PRKTHREAD *)&Resource->OwnerThreads[0].OwnerThread); 01715 return; 01716 } 01717 01718 Resource->Flag &= ~ResourceOwnedExclusive; 01719 } 01720 01721 } else { 01722 if (Resource->OwnerThreads[1].OwnerThread == CurrentThread) { 01723 OwnerEntry = &Resource->OwnerThreads[1]; 01724 01725 } else if (Resource->OwnerThreads[0].OwnerThread == CurrentThread) { 01726 OwnerEntry = &Resource->OwnerThreads[0]; 01727 01728 } else { 01729 01730 // 01731 // If the specified current thread is an owner address (low 01732 // bits are nonzero), then set the hint index to the first 01733 // entry. Otherwise, set the hint index from the owner thread. 01734 // 01735 01736 Index = 1; 01737 if (((ULONG)CurrentThread & 3) == 0) { 01738 Index = ((PKTHREAD)(CurrentThread))->ResourceIndex; 01739 } 01740 01741 OwnerEntry = Resource->OwnerTable; 01742 01743 ASSERT(OwnerEntry != NULL); 01744 01745 // 01746 // If the resource hint is not within range or the resource 01747 // table entry does match the current thread, then search 01748 // the owner table for a match. 01749 // 01750 01751 if ((Index >= OwnerEntry->TableSize) || 01752 (OwnerEntry[Index].OwnerThread != CurrentThread)) { 01753 do { 01754 OwnerEntry += 1; 01755 if (OwnerEntry->OwnerThread == CurrentThread) { 01756 break; 01757 } 01758 01759 } while (TRUE); 01760 01761 } else { 01762 OwnerEntry = &OwnerEntry[Index]; 01763 } 01764 } 01765 01766 // 01767 // Decrement the recursion count and check if ownership can be 01768 // released. 01769 // 01770 01771 ASSERT(OwnerEntry->OwnerThread == CurrentThread); 01772 ASSERT(OwnerEntry->OwnerCount > 0); 01773 01774 if (--OwnerEntry->OwnerCount != 0) { 01775 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 01776 return; 01777 } 01778 01779 // 01780 // Clear the owner thread. 01781 // 01782 01783 OwnerEntry->OwnerThread = 0; 01784 01785 // 01786 // The thread recursion count reached zero so decrement the resource 01787 // active count. If the active count reaches zero, then the resource 01788 // is no longer owned and an attempt should be made to grant access to 01789 // another thread. 01790 // 01791 01792 ASSERT(Resource->ActiveCount > 0); 01793 01794 if (--Resource->ActiveCount == 0) { 01795 01796 // 01797 // If there are exclusive waiters, then grant exclusive access 01798 // to the resource. 01799 // 01800 01801 if (IsExclusiveWaiting(Resource)) { 01802 Resource->Flag |= ResourceOwnedExclusive; 01803 Resource->OwnerThreads[0].OwnerThread = 1; 01804 Resource->OwnerThreads[0].OwnerCount = 1; 01805 Resource->ActiveCount = 1; 01806 Resource->NumberOfExclusiveWaiters -= 1; 01807 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 01808 KeSetEventBoostPriority(Resource->ExclusiveWaiters, 01809 (PRKTHREAD *)&Resource->OwnerThreads[0].OwnerThread); 01810 return; 01811 } 01812 } 01813 } 01814 01815 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 01816 return; 01817 }

VOID FASTCALL ExReleaseResourceLite IN PERESOURCE  Resource  ) 
 

Definition at line 1389 of file ex/resource.c.

References _ERESOURCE::ActiveCount, ASSERT, ASSERT_RESOURCE, ERESOURCE_THREAD, _ERESOURCE::ExclusiveWaiters, FALSE, _ERESOURCE::Flag, Index, IsExclusiveWaiting, IsOwnedExclusive, IsSharedWaiting, KeBugCheckEx(), KeReleaseSemaphore(), KeSetEventBoostPriority(), NULL, _ERESOURCE::NumberOfExclusiveWaiters, _ERESOURCE::NumberOfSharedWaiters, _OWNER_ENTRY::OwnerCount, _ERESOURCE::OwnerTable, _OWNER_ENTRY::OwnerThread, _ERESOURCE::OwnerThreads, PsGetCurrentThread, Resource, ResourceOwnedExclusive, _ERESOURCE::SharedWaiters, SHORT, _ERESOURCE::SpinLock, and _OWNER_ENTRY::TableSize.

Referenced by MmTrimAllSystemPagableMemory(), and VerifierExReleaseResource().

01395 : 01396 01397 This routine releases the specified resource for the current thread 01398 and decrements the recursion count. If the count reaches zero, then 01399 the resource may also be released. 01400 01401 N.B. This routine uses fast locking. 01402 01403 Arguments: 01404 01405 Resource - Supplies a pointer to the resource to release. 01406 01407 Return Value: 01408 01409 None. 01410 01411 --*/ 01412 01413 { 01414 01415 ERESOURCE_THREAD CurrentThread; 01416 ULONG Index; 01417 ULONG Number; 01418 KIRQL OldIrql; 01419 POWNER_ENTRY OwnerEntry, OwnerEnd; 01420 01421 CurrentThread = (ERESOURCE_THREAD)PsGetCurrentThread(); 01422 01423 // 01424 // Acquire exclusive access to the specified resource. 01425 // 01426 01427 ExAcquireFastLock(&Resource->SpinLock, &OldIrql); 01428 01429 ASSERT_RESOURCE(Resource); 01430 01431 // 01432 // If the resource is exclusively owned, then release exclusive 01433 // ownership. Otherwise, release shared ownership. 01434 // 01435 // N.B. The two release paths are split since this is such a high 01436 // frequency function. 01437 // 01438 01439 if (IsOwnedExclusive(Resource)) { 01440 01441 // if (Resource->OwnerThreads[0].OwnerThread != CurrentThread) { 01442 // KeBugCheckEx(RESOURCE_NOT_OWNED, 01443 // (ULONG_PTR)Resource, 01444 // (ULONG_PTR)CurrentThread, 01445 // (ULONG_PTR)Resource->OwnerTable, 01446 // 0x1); 01447 // } 01448 01449 // 01450 // Decrement the recursion count and check if ownership can be 01451 // released. 01452 // 01453 01454 ASSERT(Resource->OwnerThreads[0].OwnerCount > 0); 01455 01456 if (--Resource->OwnerThreads[0].OwnerCount != 0) { 01457 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 01458 return; 01459 } 01460 01461 // 01462 // Clear the owner thread. 01463 // 01464 01465 Resource->OwnerThreads[0].OwnerThread = 0; 01466 01467 // 01468 // The thread recursion count reached zero so decrement the resource 01469 // active count. If the active count reaches zero, then the resource 01470 // is no longer owned and an attempt should be made to grant access to 01471 // another thread. 01472 // 01473 01474 ASSERT(Resource->ActiveCount > 0); 01475 01476 if (--Resource->ActiveCount == 0) { 01477 01478 // 01479 // If there are shared waiters, then grant shared access to the 01480 // resource. Otherwise, grant exclusive ownership if there are 01481 // exclusive waiters. 01482 // 01483 01484 if (IsSharedWaiting(Resource)) { 01485 Resource->Flag &= ~ResourceOwnedExclusive; 01486 Number = Resource->NumberOfSharedWaiters; 01487 Resource->ActiveCount = (SHORT)Number; 01488 Resource->NumberOfSharedWaiters = 0; 01489 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 01490 KeReleaseSemaphore(Resource->SharedWaiters, 0, Number, FALSE); 01491 return; 01492 01493 } else if (IsExclusiveWaiting(Resource)) { 01494 Resource->OwnerThreads[0].OwnerThread = 1; 01495 Resource->OwnerThreads[0].OwnerCount = 1; 01496 Resource->ActiveCount = 1; 01497 Resource->NumberOfExclusiveWaiters -= 1; 01498 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 01499 KeSetEventBoostPriority(Resource->ExclusiveWaiters, 01500 (PRKTHREAD *)&Resource->OwnerThreads[0].OwnerThread); 01501 return; 01502 } 01503 01504 Resource->Flag &= ~ResourceOwnedExclusive; 01505 } 01506 01507 } else { 01508 if (Resource->OwnerThreads[1].OwnerThread == CurrentThread) { 01509 OwnerEntry = &Resource->OwnerThreads[1]; 01510 01511 } else if (Resource->OwnerThreads[0].OwnerThread == CurrentThread) { 01512 OwnerEntry = &Resource->OwnerThreads[0]; 01513 01514 } else { 01515 Index = ((PKTHREAD)(CurrentThread))->ResourceIndex; 01516 OwnerEntry = Resource->OwnerTable; 01517 01518 if (OwnerEntry == NULL) { 01519 KeBugCheckEx(RESOURCE_NOT_OWNED, 01520 (ULONG_PTR)Resource, 01521 (ULONG_PTR)CurrentThread, 01522 (ULONG_PTR)Resource->OwnerTable, 01523 0x2); 01524 } 01525 01526 // 01527 // If the resource hint is not within range or the resource 01528 // table entry does match the current thread, then search 01529 // the owner table for a match. 01530 // 01531 01532 if ((Index >= OwnerEntry->TableSize) || 01533 (OwnerEntry[Index].OwnerThread != CurrentThread)) { 01534 OwnerEnd = &OwnerEntry[OwnerEntry->TableSize]; 01535 while (1) { 01536 OwnerEntry += 1; 01537 if (OwnerEntry >= OwnerEnd) { 01538 KeBugCheckEx(RESOURCE_NOT_OWNED, 01539 (ULONG_PTR)Resource, 01540 (ULONG_PTR)CurrentThread, 01541 (ULONG_PTR)Resource->OwnerTable, 01542 0x3); 01543 } 01544 if (OwnerEntry->OwnerThread == CurrentThread) { 01545 break; 01546 } 01547 }; 01548 } else { 01549 OwnerEntry = &OwnerEntry[Index]; 01550 } 01551 } 01552 01553 // 01554 // Decrement the recursion count and check if ownership can be 01555 // released. 01556 // 01557 01558 ASSERT(OwnerEntry->OwnerThread == CurrentThread); 01559 ASSERT(OwnerEntry->OwnerCount > 0); 01560 01561 if (--OwnerEntry->OwnerCount != 0) { 01562 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 01563 return; 01564 } 01565 01566 // 01567 // Clear the owner thread. 01568 // 01569 01570 OwnerEntry->OwnerThread = 0; 01571 01572 // 01573 // The thread recursion count reached zero so decrement the resource 01574 // active count. If the active count reaches zero, then the resource 01575 // is no longer owned and an attempt should be made to grant access to 01576 // another thread. 01577 // 01578 01579 ASSERT(Resource->ActiveCount > 0); 01580 01581 if (--Resource->ActiveCount == 0) { 01582 01583 // 01584 // If there are exclusive waiters, then grant exclusive access 01585 // to the resource. 01586 // 01587 01588 if (IsExclusiveWaiting(Resource)) { 01589 Resource->Flag |= ResourceOwnedExclusive; 01590 Resource->OwnerThreads[0].OwnerThread = 1; 01591 Resource->OwnerThreads[0].OwnerCount = 1; 01592 Resource->ActiveCount = 1; 01593 Resource->NumberOfExclusiveWaiters -= 1; 01594 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 01595 KeSetEventBoostPriority(Resource->ExclusiveWaiters, 01596 (PRKTHREAD *)&Resource->OwnerThreads[0].OwnerThread); 01597 return; 01598 } 01599 } 01600 } 01601 01602 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 01603 return; 01604 }

VOID ExSetResourceOwnerPointer IN PERESOURCE  Resource,
IN PVOID  OwnerPointer
 

Definition at line 1820 of file ex/resource.c.

References ASSERT, ASSERT_RESOURCE, ERESOURCE_THREAD, Index, IsOwnedExclusive, NULL, _OWNER_ENTRY::OwnerCount, _ERESOURCE::OwnerTable, _OWNER_ENTRY::OwnerThread, _ERESOURCE::OwnerThreads, PsGetCurrentThread, Resource, _ERESOURCE::SpinLock, _OWNER_ENTRY::TableSize, and TRUE.

Referenced by CcSetBcbOwnerPointer().

01827 : 01828 01829 This routine locates the owner entry for the current thread and stores 01830 the specified owner address as the owner thread. Subsequent to calling 01831 this routine, the only routine which may be called for this resource is 01832 ExReleaseResourceForThread, supplying the owner address as the "thread". 01833 01834 Owner addresses must obey the following rules: 01835 01836 They must be a unique pointer to a structure allocated in system space, 01837 and they must point to a structure which remains allocated until after 01838 the call to ExReleaseResourceForThread. This is to eliminate aliasing 01839 with a thread or other owner address. 01840 01841 The low order two bits of the owner address must be set by the caller, 01842 so that other routines in the resource package can distinguish owner 01843 address from thread addresses. 01844 01845 N.B. This routine uses fast locking. 01846 01847 Arguments: 01848 01849 Resource - Supplies a pointer to the resource to release. 01850 01851 OwnerPointer - Supplies a pointer to an allocated structure with the low 01852 order two bits set. 01853 01854 Return Value: 01855 01856 None. 01857 01858 --*/ 01859 01860 { 01861 01862 ERESOURCE_THREAD CurrentThread; 01863 ULONG Index; 01864 KIRQL OldIrql; 01865 POWNER_ENTRY OwnerEntry; 01866 01867 ASSERT((OwnerPointer != 0) && (((ULONG_PTR)OwnerPointer & 3) == 3)); 01868 01869 CurrentThread = (ERESOURCE_THREAD)PsGetCurrentThread(); 01870 01871 // 01872 // Acquire exclusive access to the specified resource. 01873 // 01874 01875 ExAcquireFastLock(&Resource->SpinLock, &OldIrql); 01876 01877 ASSERT_RESOURCE(Resource); 01878 01879 // 01880 // If the resource is exclusively owned, then it is the first owner entry. 01881 // 01882 01883 if (IsOwnedExclusive(Resource)) { 01884 01885 ASSERT(Resource->OwnerThreads[0].OwnerThread == CurrentThread); 01886 01887 // 01888 // Set the owner address. 01889 // 01890 01891 ASSERT(Resource->OwnerThreads[0].OwnerCount > 0); 01892 01893 Resource->OwnerThreads[0].OwnerThread = (ULONG_PTR)OwnerPointer; 01894 01895 // 01896 // For shared access we have to search for the current thread to set 01897 // the owner address. 01898 // 01899 01900 } else { 01901 if (Resource->OwnerThreads[1].OwnerThread == CurrentThread) { 01902 Resource->OwnerThreads[1].OwnerThread = (ULONG_PTR)OwnerPointer; 01903 01904 } else if (Resource->OwnerThreads[0].OwnerThread == CurrentThread) { 01905 Resource->OwnerThreads[0].OwnerThread = (ULONG_PTR)OwnerPointer; 01906 01907 } else { 01908 Index = ((PKTHREAD)(CurrentThread))->ResourceIndex; 01909 OwnerEntry = Resource->OwnerTable; 01910 01911 ASSERT(OwnerEntry != NULL); 01912 01913 // 01914 // If the resource hint is not within range or the resource 01915 // table entry does match the current thread, then search 01916 // the owner table for a match. 01917 // 01918 01919 if ((Index >= OwnerEntry->TableSize) || 01920 (OwnerEntry[Index].OwnerThread != CurrentThread)) { 01921 do { 01922 OwnerEntry += 1; 01923 if (OwnerEntry->OwnerThread == CurrentThread) { 01924 break; 01925 } 01926 01927 } while (TRUE); 01928 01929 } else { 01930 OwnerEntry = &OwnerEntry[Index]; 01931 } 01932 01933 OwnerEntry->OwnerThread = (ULONG_PTR)OwnerPointer; 01934 } 01935 } 01936 01937 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 01938 return; 01939 }

BOOLEAN ExTryToAcquireResourceExclusiveLite IN PERESOURCE  Resource  ) 
 

Definition at line 598 of file ex/resource.c.

References _ERESOURCE::ActiveCount, ASSERT, ASSERT_RESOURCE, ERESOURCE_THREAD, ExpIncrementCounter, FALSE, _ERESOURCE::Flag, IsOwnedExclusive, _OWNER_ENTRY::OwnerCount, _OWNER_ENTRY::OwnerThread, _ERESOURCE::OwnerThreads, PsGetCurrentThread, Resource, ResourceNeverExclusive, ResourceOwnedExclusive, _ERESOURCE::SpinLock, and TRUE.

Referenced by MiEmptyWorkingSet(), MmTrimAllSystemPagableMemory(), and MmWorkingSetManager().

00604 : 00605 00606 The routine attempts to acquire the specified resource for exclusive 00607 access. 00608 00609 N.B. This routine uses fast locking. 00610 00611 Arguments: 00612 00613 Resource - Supplies a pointer to the resource that is acquired 00614 for exclusive access. 00615 00616 Return Value: 00617 00618 BOOLEAN - TRUE if the resource is acquired and FALSE otherwise. 00619 00620 --*/ 00621 00622 { 00623 00624 ERESOURCE_THREAD CurrentThread; 00625 KIRQL OldIrql; 00626 BOOLEAN Result; 00627 00628 ASSERT((Resource->Flag & ResourceNeverExclusive) == 0); 00629 00630 // 00631 // Attempt to acquire exclusive access to the specified resource. 00632 // 00633 00634 CurrentThread = (ERESOURCE_THREAD)PsGetCurrentThread(); 00635 ExAcquireFastLock(&Resource->SpinLock, &OldIrql); 00636 00637 ASSERT(KeIsExecutingDpc() == FALSE); 00638 ASSERT_RESOURCE(Resource); 00639 00640 // 00641 // If the active count of the resource is zero, then there is neither 00642 // an exclusive owner nor a shared owner and access to the resource can 00643 // be immediately granted. Otherwise, if the resource is owned exclusive 00644 // and the current thread is the owner, then access to the resource can 00645 // be immediately granted. Otherwise, access cannot be granted. 00646 // 00647 00648 Result = FALSE; 00649 if (Resource->ActiveCount == 0) { 00650 ExpIncrementCounter(ExclusiveAcquire); 00651 Resource->Flag |= ResourceOwnedExclusive; 00652 Resource->OwnerThreads[0].OwnerThread = CurrentThread; 00653 Resource->OwnerThreads[0].OwnerCount = 1; 00654 Resource->ActiveCount = 1; 00655 Result = TRUE; 00656 00657 } else if (IsOwnedExclusive(Resource) && 00658 (Resource->OwnerThreads[0].OwnerThread == CurrentThread)) { 00659 ExpIncrementCounter(ExclusiveAcquire); 00660 Resource->OwnerThreads[0].OwnerCount += 1; 00661 Result = TRUE; 00662 } 00663 00664 ExReleaseFastLock(&Resource->SpinLock, OldIrql); 00665 return Result; 00666 }


Variable Documentation

KSPIN_LOCK ExpResourceSpinLock
 

Definition at line 114 of file ex/resource.c.

Referenced by ExDeleteResourceLite(), ExInitializeResourceLite(), ExpCheckForResource(), ExpResourceInitialization(), and ExQuerySystemLockInformation().

ULONG ExpResourceTimeoutCount = 648000
 

Definition at line 108 of file ex/resource.c.

LIST_ENTRY ExpSystemResourcesList
 

Definition at line 120 of file ex/resource.c.

LARGE_INTEGER ExpTimeout
 

Definition at line 102 of file ex/resource.c.

Referenced by ExpResourceInitialization(), ExpWaitForResource(), and ExpWaitForResourceDdk().


Generated on Sat May 15 19:45:29 2004 for test by doxygen 1.3.7