- Implemented Queued and In-Stack Queued Spinlocks (at DPC-Level). See
"Windows Internals II" Chapter 4, Pages 25-27.
Modified: trunk/reactos/ntoskrnl/ke/spinlock.c
_____
Modified: trunk/reactos/ntoskrnl/ke/spinlock.c
--- trunk/reactos/ntoskrnl/ke/spinlock.c 2006-01-05 12:48:33 UTC
(rev 20572)
+++ trunk/reactos/ntoskrnl/ke/spinlock.c 2006-01-05 13:12:48 UTC
(rev 20573)
@@ -18,6 +18,9 @@
#undef KefReleaseSpinLockFromDpcLevel
#undef KeReleaseSpinLockFromDpcLevel
+#define LQ_WAIT 1
+#define LQ_OWN 2
+
/* FUNCTIONS
***************************************************************/
/*
@@ -190,25 +193,98 @@
#endif
}
+VOID
+FASTCALL
+KeAcquireQueuedSpinLockAtDpcLevel(IN PKLOCK_QUEUE_HANDLE LockHandle)
+{
+#ifdef CONFIG_SMP
+ PKSPIN_LOCK_QUEUE Prev;
+
+ /* Set the new lock */
+ Prev = (PKSPIN_LOCK_QUEUE)
+ InterlockedExchange((PLONG)LockHandle->LockQueue.Lock,
+ (LONG)LockHandle);
+ if (!Prev)
+ {
+ /* There was nothing there before. We now own it */
+ *(ULONG_PTR*)&LockHandle->LockQueue.Lock |= LQ_OWN;
+ return;
+ }
+
+ /* Set the wait flag */
+ *(ULONG_PTR*)&LockHandle->LockQueue.Lock |= LQ_WAIT;
+
+ /* Link us */
+ Prev->Next = (PKSPIN_LOCK_QUEUE)LockHandle;
+
+ /* Loop and wait */
+ while ( *(ULONG_PTR*)&LockHandle->LockQueue.Lock & LQ_WAIT)
YieldProcessor();
+ return;
+#endif
+}
+
+VOID
+FASTCALL
+KeReleaseQueuedSpinLockFromDpcLevel(IN PKLOCK_QUEUE_HANDLE LockHandle)
+{
+#ifdef CONFIG_SMP
+ KSPIN_LOCK LockVal;
+ PKSPIN_LOCK_QUEUE Waiter;
+
+ /* Remove own and wait flags */
+ *(ULONG_PTR*)&LockHandle->LockQueue.Lock &= ~(LQ_OWN | LQ_WAIT);
+ LockVal = *LockHandle->LockQueue.Lock;
+
+ /* Check if we already own it */
+ if (LockVal == (KSPIN_LOCK)LockHandle)
+ {
+ /* Disown it */
+ LockVal = (KSPIN_LOCK)
+
InterlockedCompareExchangePointer(LockHandle->LockQueue.Lock,
+ NULL,
+ LockHandle);
+ }
+ if (LockVal == (KSPIN_LOCK)LockHandle) return;
+
+ /* Need to wait for it */
+ Waiter = LockHandle->LockQueue.Next;
+ while (!Waiter)
+ {
+ YieldProcessor();
+ Waiter = LockHandle->LockQueue.Next;
+ }
+
+ /* It's gone */
+ *(ULONG_PTR*)&Waiter->Lock ^= (LQ_OWN | LQ_WAIT);
+ LockHandle->LockQueue.Next = NULL;
+#endif
+}
+
/*
- * @unimplemented
+ * @implemented
*/
VOID
FASTCALL
KeAcquireInStackQueuedSpinLockAtDpcLevel(IN PKSPIN_LOCK SpinLock,
IN PKLOCK_QUEUE_HANDLE
LockHandle)
{
- UNIMPLEMENTED;
+ /* Set it up properly */
+ LockHandle->LockQueue.Next = NULL;
+ LockHandle->LockQueue.Lock = SpinLock;
+ KeAcquireQueuedSpinLockAtDpcLevel((PKLOCK_QUEUE_HANDLE)
+ &LockHandle->LockQueue.Next);
}
/*
- * @unimplemented
+ * @implemented
*/
VOID
FASTCALL
KeReleaseInStackQueuedSpinLockFromDpcLevel(IN PKLOCK_QUEUE_HANDLE
LockHandle)
{
- UNIMPLEMENTED;
+ /* Call the internal function */
+ KeReleaseQueuedSpinLockFromDpcLevel((PKLOCK_QUEUE_HANDLE)
+ &LockHandle->LockQueue.Next);
}
/* EOF */
Show replies by date