Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- dlls/ntoskrnl.exe/sync.c | 64 +++++++++++++++++++++++++++++ include/ddk/wdm.h | 1 + 3 files changed, 66 insertions(+), 1 deletion(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 177800a8dc..347febb63f 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -122,7 +122,7 @@ @ stub DbgSetDebugFilterState @ stdcall ExAcquireResourceExclusiveLite(ptr long) @ stdcall ExAcquireResourceSharedLite(ptr long) -@ stub ExAcquireSharedStarveExclusive +@ stdcall ExAcquireSharedStarveExclusive(ptr long) @ stub ExAcquireSharedWaitForExclusive @ stub ExAllocateFromPagedLookasideList @ stdcall ExAllocatePool(long long) diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c index 82667e8510..2b362efc82 100644 --- a/dlls/ntoskrnl.exe/sync.c +++ b/dlls/ntoskrnl.exe/sync.c @@ -880,3 +880,67 @@ BOOLEAN WINAPI ExAcquireResourceSharedLite( ERESOURCE *resource, BOOLEAN wait )
return TRUE; } + +/*********************************************************************** + * ExAcquireSharedStarveExclusive (NTOSKRNL.EXE.@) + */ +BOOLEAN WINAPI ExAcquireSharedStarveExclusive( ERESOURCE *resource, BOOLEAN wait ) +{ + OWNER_ENTRY *entry; + KIRQL irql; + + TRACE("resource %p, wait %u.\n", resource, wait); + + KeAcquireSpinLock( &resource->SpinLock, &irql ); + + entry = resource_get_shared_entry( resource, (ERESOURCE_THREAD)KeGetCurrentThread() ); + + if (resource->Flag & ResourceOwnedExclusive) + { + if (resource->OwnerEntry.OwnerThread == (ERESOURCE_THREAD)KeGetCurrentThread()) + { + resource->ActiveEntries++; + KeReleaseSpinLock( &resource->SpinLock, irql ); + return TRUE; + } + } + /* We are starving exclusive waiters, but we cannot steal the resource out + * from under an exclusive waiter who is about to acquire it. (Because of + * locking, and because exclusive waiters are always waked first, this is + * guaranteed to be the case if the resource is unowned and there are + * exclusive waiters.) */ + else if (!(!resource->ActiveEntries && resource->NumberOfExclusiveWaiters)) + { + entry->OwnerCount++; + resource->ActiveEntries++; + KeReleaseSpinLock( &resource->SpinLock, irql ); + return TRUE; + } + + if (!wait) + { + KeReleaseSpinLock( &resource->SpinLock, irql ); + return FALSE; + } + + if (!resource->SharedWaiters) + { + resource->SharedWaiters = heap_alloc( sizeof(*resource->SharedWaiters) ); + KeInitializeSemaphore( resource->SharedWaiters, 0, INT_MAX ); + } + resource->NumberOfSharedWaiters++; + + KeReleaseSpinLock( &resource->SpinLock, irql ); + + KeWaitForSingleObject( resource->SharedWaiters, Executive, KernelMode, FALSE, NULL ); + + KeAcquireSpinLock( &resource->SpinLock, &irql ); + + entry->OwnerCount++; + resource->ActiveEntries++; + resource->NumberOfSharedWaiters--; + + KeReleaseSpinLock( &resource->SpinLock, irql ); + + return TRUE; +} diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index a153942bf5..8023fda64e 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1514,6 +1514,7 @@ NTSTATUS WINAPI DbgQueryDebugFilterState(ULONG, ULONG); void WINAPI ExAcquireFastMutexUnsafe(PFAST_MUTEX); BOOLEAN WINAPI ExAcquireResourceExclusiveLite(ERESOURCE*,BOOLEAN); BOOLEAN WINAPI ExAcquireResourceSharedLite(ERESOURCE*,BOOLEAN); +BOOLEAN WINAPI ExAcquireSharedStarveExclusive(ERESOURCE*,BOOLEAN); PVOID WINAPI ExAllocatePool(POOL_TYPE,SIZE_T); PVOID WINAPI ExAllocatePoolWithQuota(POOL_TYPE,SIZE_T); PVOID WINAPI ExAllocatePoolWithTag(POOL_TYPE,SIZE_T,ULONG);