FastMutex->Contention++;
/* Wait for the event */
- KeWaitForSingleObject(&FastMutex->Gate,
+ KeWaitForSingleObject(&FastMutex->Event,
WrMutex,
KernelMode,
FALSE,
NULL);
}
+VOID
+FASTCALL
+KiAcquireGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
+{
+ ULONG BitsToRemove, BitsToAdd;
+ LONG OldValue, NewValue;
+
+ /* We depend on these bits being just right */
+ C_ASSERT((GM_LOCK_WAITER_WOKEN * 2) == GM_LOCK_WAITER_INC);
+
+ /* Increase the contention count */
+ GuardedMutex->Contention++;
+
+ /* Start by unlocking the Guarded Mutex */
+ BitsToRemove = GM_LOCK_BIT;
+ BitsToAdd = GM_LOCK_WAITER_INC;
+
+ /* Start change loop */
+ for (;;)
+ {
+ /* Loop sanity checks */
+ ASSERT((BitsToRemove == GM_LOCK_BIT) ||
+ (BitsToRemove == (GM_LOCK_BIT | GM_LOCK_WAITER_WOKEN)));
+ ASSERT((BitsToAdd == GM_LOCK_WAITER_INC) ||
+ (BitsToAdd == GM_LOCK_WAITER_WOKEN));
+
+ /* Get the Count Bits */
+ OldValue = GuardedMutex->Count;
+
+ /* Start internal bit change loop */
+ for (;;)
+ {
+ /* Check if the Guarded Mutex is locked */
+ if (OldValue & GM_LOCK_BIT)
+ {
+ /* Sanity check */
+ ASSERT((BitsToRemove == GM_LOCK_BIT) ||
+ ((OldValue & GM_LOCK_WAITER_WOKEN) != 0));
+
+ /* Unlock it by removing the Lock Bit */
+ NewValue = OldValue ^ BitsToRemove;
+ NewValue = InterlockedCompareExchange(&GuardedMutex->Count,
+ NewValue,
+ OldValue);
+ if (NewValue == OldValue) return;
+ }
+ else
+ {
+ /* The Guarded Mutex isn't locked, so simply set the bits */
+ NewValue = OldValue + BitsToAdd;
+ NewValue = InterlockedCompareExchange(&GuardedMutex->Count,
+ NewValue,
+ OldValue);
+ if (NewValue == OldValue) break;
+ }
+
+ /* Old value changed, loop again */
+ OldValue = NewValue;
+ }
+
+ /* Now we have to wait for it */
+ KeWaitForGate(&GuardedMutex->Gate, WrGuardedMutex, KernelMode);
+ ASSERT((GuardedMutex->Count & GM_LOCK_WAITER_WOKEN) != 0);
+
+ /* Ok, the wait is done, so set the new bits */
+ BitsToRemove = GM_LOCK_BIT | GM_LOCK_WAITER_WOKEN;
+ BitsToAdd = GM_LOCK_WAITER_WOKEN;
+ }
+}
+
//
// This routine exits the dispatcher after a compatible operation and
// swaps the context to the next scheduled thread on the current CPU if
{
/* Check if it has an invalid count */
if ((Thread == CurrentObject->OwnerThread) &&
- (CurrentObject->Header.SignalState == MINLONG))
+ (CurrentObject->Header.SignalState == (LONG)MINLONG))
{
/* Raise an exception */
KiReleaseDispatcherLock(Thread->WaitIrql);
{
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
LARGE_INTEGER SafeInterval;
- NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS Status;
/* Check the previous mode */
- if(PreviousMode != KernelMode)
+ if (PreviousMode != KernelMode)
{
/* Enter SEH for probing */
- _SEH_TRY
+ _SEH2_TRY
{
/* Probe and capture the time out */
SafeInterval = ProbeForReadLargeInteger(DelayInterval);
DelayInterval = &SafeInterval;
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- /* Get SEH exception */
- Status = _SEH_GetExceptionCode();
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
}
- _SEH_END;
- if (!NT_SUCCESS(Status)) return Status;
+ _SEH2_END;
}
/* Call the Kernel Function */