Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 9 ----- dlls/ntoskrnl.exe/sync.c | 71 ++++++++++++++++++++++++++++++++++++ include/ddk/wdm.h | 1 + 3 files changed, 72 insertions(+), 9 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index c6a10f19d2..441bfc57d1 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -3356,15 +3356,6 @@ NTSTATUS WINAPI IoCsqInitialize(PIO_CSQ csq, PIO_CSQ_INSERT_IRP insert_irp, PIO_ return STATUS_SUCCESS; }
-/*********************************************************************** - * ExAcquireResourceExclusiveLite (NTOSKRNL.EXE.@) - */ -BOOLEAN WINAPI ExAcquireResourceExclusiveLite( PERESOURCE resource, BOOLEAN wait ) -{ - FIXME( ":%p %u stub\n", resource, wait ); - return TRUE; -} - /*********************************************************************** * ExDeleteResourceLite (NTOSKRNL.EXE.@) */ diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c index 168c6d1642..0c8d02f7dd 100644 --- a/dlls/ntoskrnl.exe/sync.c +++ b/dlls/ntoskrnl.exe/sync.c @@ -30,6 +30,7 @@ #include "ddk/wdm.h"
#include "wine/debug.h" +#include "wine/heap.h"
#include "ntoskrnl_private.h"
@@ -718,6 +719,19 @@ void WINAPI ExReleaseFastMutexUnsafe( FAST_MUTEX *mutex ) KeSetEvent( &mutex->Event, IO_NO_INCREMENT, FALSE ); }
+/* Use of the fields of an ERESOURCE structure seems to vary wildly between + * Windows versions. The below implementation uses them as follows: + * + * OwnerTable - contains a list of shared owners, including threads which do + * not currently own the resource + * OwnerTable[i].OwnerThread - shared owner TID + * OwnerTable[i].OwnerCount - recursion count of this shared owner (may be 0) + * OwnerEntry.OwnerThread - the owner TID if exclusively owned + * OwnerEntry.TableSize - the number of entries in OwnerTable, including threads + * which do not currently own the resource + * ActiveEntries - total number of acquisitions (incl. recursive ones) + */ + /*********************************************************************** * ExInitializeResourceLite (NTOSKRNL.EXE.@) */ @@ -727,3 +741,60 @@ NTSTATUS WINAPI ExInitializeResourceLite( ERESOURCE *resource ) memset(resource, 0, sizeof(*resource)); return STATUS_SUCCESS; } + +/*********************************************************************** + * ExAcquireResourceExclusiveLite (NTOSKRNL.EXE.@) + */ +BOOLEAN WINAPI ExAcquireResourceExclusiveLite( ERESOURCE *resource, BOOLEAN wait ) +{ + KIRQL irql; + + TRACE("resource %p, wait %u.\n", resource, wait); + + KeAcquireSpinLock( &resource->SpinLock, &irql ); + + if (resource->OwnerEntry.OwnerThread == (ERESOURCE_THREAD)KeGetCurrentThread()) + { + resource->ActiveEntries++; + KeReleaseSpinLock( &resource->SpinLock, irql ); + return TRUE; + } + /* In order to avoid a race between waiting for the ExclusiveWaiters event + * and grabbing the lock, do not grab the resource if it is unclaimed but + * has waiters; instead queue ourselves. */ + else if (!resource->ActiveEntries && !resource->NumberOfExclusiveWaiters && !resource->NumberOfSharedWaiters) + { + resource->Flag |= ResourceOwnedExclusive; + resource->OwnerEntry.OwnerThread = (ERESOURCE_THREAD)KeGetCurrentThread(); + resource->ActiveEntries++; + KeReleaseSpinLock( &resource->SpinLock, irql ); + return TRUE; + } + else if (!wait) + { + KeReleaseSpinLock( &resource->SpinLock, irql ); + return FALSE; + } + + if (!resource->ExclusiveWaiters) + { + resource->ExclusiveWaiters = heap_alloc( sizeof(*resource->ExclusiveWaiters) ); + KeInitializeEvent( resource->ExclusiveWaiters, SynchronizationEvent, FALSE ); + } + resource->NumberOfExclusiveWaiters++; + + KeReleaseSpinLock( &resource->SpinLock, irql ); + + KeWaitForSingleObject( resource->ExclusiveWaiters, Executive, KernelMode, FALSE, NULL ); + + KeAcquireSpinLock( &resource->SpinLock, &irql ); + + resource->Flag |= ResourceOwnedExclusive; + resource->OwnerEntry.OwnerThread = (ERESOURCE_THREAD)KeGetCurrentThread(); + resource->ActiveEntries++; + resource->NumberOfExclusiveWaiters--; + + KeReleaseSpinLock( &resource->SpinLock, irql ); + + return TRUE; +} diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index a6536212b6..69916056eb 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1512,6 +1512,7 @@ static inline void IoSetCompletionRoutine(IRP *irp, PIO_COMPLETION_ROUTINE routi
NTSTATUS WINAPI DbgQueryDebugFilterState(ULONG, ULONG); void WINAPI ExAcquireFastMutexUnsafe(PFAST_MUTEX); +BOOLEAN WINAPI ExAcquireResourceExclusiveLite(ERESOURCE*,BOOLEAN); PVOID WINAPI ExAllocatePool(POOL_TYPE,SIZE_T); PVOID WINAPI ExAllocatePoolWithQuota(POOL_TYPE,SIZE_T); PVOID WINAPI ExAllocatePoolWithTag(POOL_TYPE,SIZE_T,ULONG);