wine-staging/patches/ntoskrnl.exe-Resources/0002-ntoskrnl.exe-Implement-ExAcquireResourceExclusiveLit.patch
2019-02-19 19:03:35 -06:00

144 lines
5.3 KiB
Diff

From 0a7df47900ff847f137836341d086dc5690f97d7 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Tue, 29 Jan 2019 21:35:44 -0600
Subject: [PATCH 02/13] ntoskrnl.exe: Implement
ExAcquireResourceExclusiveLite().
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
---
dlls/ntoskrnl.exe/ntoskrnl.c | 9 -----
dlls/ntoskrnl.exe/sync.c | 73 ++++++++++++++++++++++++++++++++++++
include/ddk/wdm.h | 1 +
3 files changed, 74 insertions(+), 9 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index 93ba89be..d6c35d1c 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -3038,15 +3038,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 56d46a86..205914a7 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"
@@ -664,6 +665,18 @@ 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 (TID and recursion count),
+ * including threads which do not currently own the resource
+ * (recursion count == 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.@)
*/
@@ -673,3 +686,63 @@ 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 );
+
+ FIXME("%#lx/%d/%d/%d\n", resource->OwnerEntry.OwnerThread, resource->ActiveEntries,
+ resource->NumberOfExclusiveWaiters, resource->NumberOfSharedWaiters);
+
+ if (resource->OwnerEntry.OwnerThread == (ERESOURCE_THREAD)KeGetCurrentThread())
+ {
+ resource->ActiveEntries++;
+ KeReleaseSpinLock( &resource->SpinLock, irql );
+ return TRUE;
+ }
+ else if (!resource->ActiveEntries && !resource->NumberOfExclusiveWaiters && !resource->NumberOfSharedWaiters)
+ {
+ /* 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. */
+ 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 f76444f1..a8cbdc2e 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);
--
2.20.1