test: ex/resource.c File Reference

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 |  | ) | (((a)->Flag & DisablePriorityBoost) == 0)

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

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

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

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

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

#define IsSharedWaiting | ( | a |  | ) | ((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().