[PATCH 2/8] ntoskrnl.exe: Implement ExAcquireResourceExclusiveLite().

Zebediah Figura z.figura12 at gmail.com
Mon Apr 8 16:57:49 CDT 2019


Signed-off-by: Zebediah Figura <z.figura12 at 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 013be47040..bb27f1cfe6 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -3360,15 +3360,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);
-- 
2.21.0




More information about the wine-devel mailing list