diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index dcea4428c46..40830894598 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -81,6 +81,10 @@ NTSTATUS FASTCALL KiSwapContext(PKTHREAD NewThread); +VOID +STDCALL +KiAdjustQuantumThread(IN PKTHREAD Thread); + /* gmutex.c ********************************************************************/ VOID diff --git a/reactos/ntoskrnl/ke/kthread.c b/reactos/ntoskrnl/ke/kthread.c index 31ab30ab04d..83834665dae 100644 --- a/reactos/ntoskrnl/ke/kthread.c +++ b/reactos/ntoskrnl/ke/kthread.c @@ -274,6 +274,9 @@ KiUnblockThread(PKTHREAD Thread, Thread->PriorityDecrement = Increment; } + /* Also decrease quantum */ + Thread->Quantum--; + } else { Thread->Quantum = Thread->QuantumReset; @@ -319,6 +322,53 @@ KiUnblockThread(PKTHREAD Thread, } } +VOID +STDCALL +KiAdjustQuantumThread(IN PKTHREAD Thread) +{ + KPRIORITY Priority; + + /* Don't adjust for RT threads */ + if ((Thread->Priority < LOW_REALTIME_PRIORITY) && + Thread->BasePriority < LOW_REALTIME_PRIORITY - 2) + { + /* Decrease Quantum by one and see if we've ran out */ + if (--Thread->Quantum <= 0) + { + /* Return quantum */ + Thread->Quantum = Thread->QuantumReset; + + /* Calculate new Priority */ + Priority = Thread->Priority - (Thread->PriorityDecrement + 1); + + /* Normalize it if we've gone too low */ + if (Priority < Thread->BasePriority) + { + /* Normalize it if we've gone too low */ + Priority = Thread->BasePriority; + } + + /* Reset the priority decrement, we've done it */ + Thread->PriorityDecrement = 0; + + /* Set the new priority, if needed */ + if (Priority != Thread->Priority) + { + /* HACK HACK This isn't nice, but it's the only way with our current codebase */ + Thread->Priority = Priority; + } + else + { + /* Priority hasn't changed, find a new thread */ + } + } + } + + /* Nothing to do... */ + return; +} + + VOID STDCALL KiSuspendThreadKernelRoutine(PKAPC Apc, diff --git a/reactos/ntoskrnl/ke/wait.c b/reactos/ntoskrnl/ke/wait.c index de1a7830406..7c1d2045b76 100644 --- a/reactos/ntoskrnl/ke/wait.c +++ b/reactos/ntoskrnl/ke/wait.c @@ -250,7 +250,7 @@ KeWaitForSingleObject(PVOID Object, /* It has a normal signal state, so unwait it and return */ KiSatisfyObjectWait(CurrentObject, CurrentThread); Status = STATUS_WAIT_0; - goto WaitDone; + goto DontWait; } else { @@ -285,7 +285,7 @@ KeWaitForSingleObject(PVOID Object, /* Return a timeout */ Status = STATUS_TIMEOUT; - goto WaitDone; + goto DontWait; } /* Point to Timer Wait Block and Thread Timer */ @@ -311,7 +311,7 @@ KeWaitForSingleObject(PVOID Object, /* Return a timeout if we couldn't insert the timer for some reason */ Status = STATUS_TIMEOUT; - goto WaitDone; + goto DontWait; } } @@ -344,11 +344,19 @@ KeWaitForSingleObject(PVOID Object, } while (TRUE); -WaitDone: /* Release the Lock, we are done */ DPRINT("Returning from KeWaitForMultipleObjects(), %x. Status: %d\n", KeGetCurrentThread(), Status); KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql); return Status; + +DontWait: + /* Adjust the Quantum */ + KiAdjustQuantumThread(CurrentThread); + + /* Release & Return */ + DPRINT("Returning from KeWaitForMultipleObjects(), %x. Status: %d\n. We did not wait.", KeGetCurrentThread(), Status); + KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql); + return Status; } /* @@ -460,7 +468,7 @@ KeWaitForMultipleObjects(ULONG Count, /* It has a normal signal state, so unwait it and return */ KiSatisfyObjectWait(CurrentObject, CurrentThread); Status = STATUS_WAIT_0 | WaitIndex; - goto WaitDone; + goto DontWait; } else { @@ -504,7 +512,7 @@ KeWaitForMultipleObjects(ULONG Count, /* Satisfy their Waits and return to the caller */ KiSatisifyMultipleObjectWaits(WaitBlock); Status = STATUS_WAIT_0; - goto WaitDone; + goto DontWait; } /* Make sure we can satisfy the Alertable request */ @@ -521,7 +529,7 @@ KeWaitForMultipleObjects(ULONG Count, /* Return a timeout */ Status = STATUS_TIMEOUT; - goto WaitDone; + goto DontWait; } /* Point to Timer Wait Block and Thread Timer */ @@ -546,7 +554,7 @@ KeWaitForMultipleObjects(ULONG Count, /* Return a timeout if we couldn't insert the timer for some reason */ Status = STATUS_TIMEOUT; - goto WaitDone; + goto DontWait; } } @@ -590,11 +598,19 @@ KeWaitForMultipleObjects(ULONG Count, } while (TRUE); -WaitDone: /* Release the Lock, we are done */ DPRINT("Returning from KeWaitForMultipleObjects(), %x. Status: %d\n", KeGetCurrentThread(), Status); KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql); return Status; + +DontWait: + /* Adjust the Quantum */ + KiAdjustQuantumThread(CurrentThread); + + /* Release & Return */ + DPRINT("Returning from KeWaitForMultipleObjects(), %x. Status: %d\n. We did not wait.", KeGetCurrentThread(), Status); + KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql); + return Status; } VOID