Zebediah Figura : ntoskrnl.exe: Implement DPC-level queued spinlock functions.

Alexandre Julliard julliard at winehq.org
Tue Jan 29 15:18:16 CST 2019


Module: wine
Branch: master
Commit: c3c2a4f697c2c249a6e3376f273bf3ee74223350
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=c3c2a4f697c2c249a6e3376f273bf3ee74223350

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Mon Jan 28 19:21:12 2019 -0600

ntoskrnl.exe: Implement DPC-level queued spinlock functions.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntoskrnl.exe/ntoskrnl.exe.spec |  4 +--
 dlls/ntoskrnl.exe/sync.c            | 65 +++++++++++++++++++++++++++++++++++++
 2 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
index 52ffc3d..7bda160 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
+++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
@@ -42,9 +42,9 @@
 @ stdcall -norelay IofCallDriver(ptr ptr)
 @ stdcall -norelay IofCompleteRequest(ptr long)
 @ stdcall -norelay KeAcquireInStackQueuedSpinLock(ptr ptr)
-@ stub KeAcquireInStackQueuedSpinLockAtDpcLevel
+@ stdcall -norelay KeAcquireInStackQueuedSpinLockAtDpcLevel(ptr ptr)
 @ stdcall -norelay KeReleaseInStackQueuedSpinLock(ptr)
-@ stub KeReleaseInStackQueuedSpinLockFromDpcLevel
+@ stdcall -norelay KeReleaseInStackQueuedSpinLockFromDpcLevel(ptr)
 @ stub KeSetTimeUpdateNotifyRoutine
 @ stub KefAcquireSpinLockAtDpcLevel
 @ stub KefReleaseSpinLockFromDpcLevel
diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c
index 2a4685c..4dc1fc3 100644
--- a/dlls/ntoskrnl.exe/sync.c
+++ b/dlls/ntoskrnl.exe/sync.c
@@ -414,6 +414,71 @@ void WINAPI KeReleaseSpinLockFromDpcLevel( KSPIN_LOCK *lock )
     InterlockedExchangePointer( (void **)lock, 0 );
 }
 
+#define QUEUED_SPINLOCK_OWNED   0x2
+
+/***********************************************************************
+ *           KeAcquireInStackQueuedSpinLockAtDpcLevel  (NTOSKRNL.EXE.@)
+ */
+#ifdef DEFINE_FASTCALL2_ENTRYPOINT
+DEFINE_FASTCALL2_ENTRYPOINT( KeAcquireInStackQueuedSpinLockAtDpcLevel )
+void WINAPI DECLSPEC_HIDDEN __regs_KeAcquireInStackQueuedSpinLockAtDpcLevel( KSPIN_LOCK *lock, KLOCK_QUEUE_HANDLE *queue )
+#else
+void WINAPI KeAcquireInStackQueuedSpinLockAtDpcLevel( KSPIN_LOCK *lock, KLOCK_QUEUE_HANDLE *queue )
+#endif
+{
+    KSPIN_LOCK_QUEUE *tail;
+
+    TRACE("lock %p, queue %p.\n", lock, queue);
+
+    queue->LockQueue.Next = NULL;
+
+    if (!(tail = InterlockedExchangePointer( (void **)lock, &queue->LockQueue )))
+        queue->LockQueue.Lock = (KSPIN_LOCK *)((ULONG_PTR)lock | QUEUED_SPINLOCK_OWNED);
+    else
+    {
+        queue->LockQueue.Lock = lock;
+        InterlockedExchangePointer( (void **)&tail->Next, &queue->LockQueue );
+
+        while (!((ULONG_PTR)InterlockedCompareExchangePointer( (void **)&queue->LockQueue.Lock, 0, 0 )
+                 & QUEUED_SPINLOCK_OWNED))
+        {
+            small_pause();
+        }
+    }
+}
+
+/***********************************************************************
+ *           KeReleaseInStackQueuedSpinLockFromDpcLevel  (NTOSKRNL.EXE.@)
+ */
+#ifdef DEFINE_FASTCALL1_ENTRYPOINT
+DEFINE_FASTCALL1_ENTRYPOINT( KeReleaseInStackQueuedSpinLockFromDpcLevel )
+void WINAPI DECLSPEC_HIDDEN __regs_KeReleaseInStackQueuedSpinLockFromDpcLevel( KLOCK_QUEUE_HANDLE *queue )
+#else
+void WINAPI KeReleaseInStackQueuedSpinLockFromDpcLevel( KLOCK_QUEUE_HANDLE *queue )
+#endif
+{
+    KSPIN_LOCK *lock = (KSPIN_LOCK *)((ULONG_PTR)queue->LockQueue.Lock & ~QUEUED_SPINLOCK_OWNED);
+    KSPIN_LOCK_QUEUE *next;
+
+    TRACE("lock %p, queue %p.\n", lock, queue);
+
+    queue->LockQueue.Lock = NULL;
+
+    if (!(next = queue->LockQueue.Next))
+    {
+        /* If we are truly the last in the queue, the lock will point to us. */
+        if (InterlockedCompareExchangePointer( (void **)lock, NULL, &queue->LockQueue ) == queue)
+            return;
+
+        /* Otherwise, someone just queued themselves, but hasn't yet set
+         * themselves as successor. Spin waiting for them to do so. */
+        while (!(next = queue->LockQueue.Next))
+            small_pause();
+    }
+
+    InterlockedExchangePointer( (void **)&next->Lock, (KSPIN_LOCK *)((ULONG_PTR)lock | QUEUED_SPINLOCK_OWNED) );
+}
+
 #ifndef __i386__
 /***********************************************************************
  *           KeReleaseSpinLock (NTOSKRNL.EXE.@)




More information about the wine-cvs mailing list