X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fntoskrnl%2Fke%2Fwait.c;h=a4737b0b7faf173b06412b938f8624e14d870db1;hp=b1488063b9e7bbbd86465aa6fd2b798e05835d16;hb=cbdf28bb6ace5e3faec494c5743371d7288f191c;hpb=cc9ff1e194099522629eb1dec47cf44b4d147dfa diff --git a/reactos/ntoskrnl/ke/wait.c b/reactos/ntoskrnl/ke/wait.c index b1488063b9e..a4737b0b7fa 100644 --- a/reactos/ntoskrnl/ke/wait.c +++ b/reactos/ntoskrnl/ke/wait.c @@ -110,13 +110,83 @@ KiAcquireFastMutex(IN PFAST_MUTEX FastMutex) 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 @@ -628,7 +698,7 @@ KeWaitForMultipleObjects(IN ULONG Count, { /* 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); @@ -779,25 +849,24 @@ NtDelayExecution(IN BOOLEAN Alertable, { 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 */