--- trunk/reactos/lib/kernel32/thread/thread.c 2005-08-09 07:42:00 UTC (rev 17233)
+++ trunk/reactos/lib/kernel32/thread/thread.c 2005-08-09 08:02:05 UTC (rev 17234)
@@ -15,6 +15,9 @@
#define NDEBUG
#include "../include/debug.h"
+/* FIXME: NDK */
+#define HIGH_PRIORITY 31
+
/* FUNCTIONS *****************************************************************/
_SEH_FILTER(BaseThreadExceptionFilter)
{
@@ -536,52 +539,77 @@
/*
* @implemented
*/
-BOOL STDCALL
+BOOL
+STDCALL
SetThreadPriority(HANDLE hThread,
- int nPriority)
+ int nPriority)
{
- ULONG Prio = nPriority;
- NTSTATUS Status;
+ ULONG Prio = nPriority;
+ NTSTATUS Status;
- Status = NtSetInformationThread(hThread,
- ThreadBasePriority,
- &Prio,
- sizeof(ULONG));
+ /* Check if values forcing saturation should be used */
+ if (Prio == THREAD_PRIORITY_TIME_CRITICAL)
+ {
+ Prio = (HIGH_PRIORITY + 1) / 2;
+ }
+ else if (Prio == THREAD_PRIORITY_IDLE)
+ {
+ Prio = -((HIGH_PRIORITY + 1) / 2);
+ }
- if (!NT_SUCCESS(Status))
+ /* Set the Base Priority */
+ Status = NtSetInformationThread(hThread,
+ ThreadBasePriority,
+ &Prio,
+ sizeof(ULONG));
+ if (!NT_SUCCESS(Status))
{
- SetLastErrorByStatus(Status);
- return(FALSE);
+ /* Failure */
+ SetLastErrorByStatus(Status);
+ return FALSE;
}
- return(TRUE);
+ /* Return */
+ return TRUE;
}
-
/*
* @implemented
*/
-int STDCALL
+int
+STDCALL
GetThreadPriority(HANDLE hThread)
{
- THREAD_BASIC_INFORMATION ThreadBasic;
- NTSTATUS Status;
+ THREAD_BASIC_INFORMATION ThreadBasic;
+ NTSTATUS Status;
- Status = NtQueryInformationThread(hThread,
- ThreadBasicInformation,
- &ThreadBasic,
- sizeof(THREAD_BASIC_INFORMATION),
- NULL);
- if (!NT_SUCCESS(Status))
+ /* Query the Base Priority Increment */
+ Status = NtQueryInformationThread(hThread,
+ ThreadBasicInformation,
+ &ThreadBasic,
+ sizeof(THREAD_BASIC_INFORMATION),
+ NULL);
+ if (!NT_SUCCESS(Status))
{
- SetLastErrorByStatus(Status);
- return(THREAD_PRIORITY_ERROR_RETURN);
+ /* Failure */
+ SetLastErrorByStatus(Status);
+ return THREAD_PRIORITY_ERROR_RETURN;
}
- return(ThreadBasic.BasePriority);
+ /* Do some conversions for out of boundary values */
+ if (ThreadBasic.BasePriority > THREAD_BASE_PRIORITY_MAX)
+ {
+ ThreadBasic.BasePriority = THREAD_PRIORITY_TIME_CRITICAL;
+ }
+ else if (ThreadBasic.BasePriority < THREAD_BASE_PRIORITY_MIN)
+ {
+ ThreadBasic.BasePriority = THREAD_PRIORITY_IDLE;
+ }
+
+ /* Return the final result */
+ return ThreadBasic.BasePriority;
}
-
/*
* @implemented
*/
--- trunk/reactos/ntoskrnl/ke/kthread.c 2005-08-09 07:42:00 UTC (rev 17233)
+++ trunk/reactos/ntoskrnl/ke/kthread.c 2005-08-09 08:02:05 UTC (rev 17234)
@@ -348,8 +348,9 @@
if (Priority != Thread->Priority)
{
/*
- * HACK HACK This isn't nice, but it's the only way with our
- * current codebase
+ * FIXME: This should be a call to KiSetPriorityThread but
+ * due to the current ""scheduler"" in ROS, it can't be done
+ * cleanly since it actualyl dispatches threads instead.
*/
Thread->Priority = Priority;
}
@@ -1054,121 +1055,231 @@
return BasePriorityIncrement;
}
-/*
- * @implemented
- */
-LONG STDCALL
-KeSetBasePriorityThread (PKTHREAD Thread,
- LONG Increment)
-/*
- * Sets thread's base priority relative to the process' base priority
- * Should only be passed in THREAD_PRIORITY_ constants in pstypes.h
- */
+VOID
+STDCALL
+KiSetPriorityThread(PKTHREAD Thread,
+ KPRIORITY Priority,
+ PBOOLEAN Released)
{
- KPRIORITY Priority;
- if (Increment < -2)
- {
- Increment = -2;
- }
- else if (Increment > 2)
- {
- Increment = 2;
- }
- Priority = ((PETHREAD)Thread)->ThreadsProcess->Pcb.BasePriority + Increment;
- if (Priority < LOW_PRIORITY)
- {
- Priority = LOW_PRIORITY;
- }
- else if (Priority >= MAXIMUM_PRIORITY)
- {
- Thread->BasePriority = HIGH_PRIORITY;
- }
- KeSetPriorityThread(Thread, Priority);
- return 1;
+ KPRIORITY OldPriority = Thread->Priority;
+ ULONG Mask;
+ int i;
+ PKPCR Pcr;
+ DPRINT("Changing prio to : %lx\n", Priority);
+
+ /* Check if priority changed */
+ if (OldPriority != Priority)
+ {
+ /* Set it */
+ Thread->Priority = Priority;
+
+ /* Choose action based on thread's state */
+ if (Thread->State == Ready)
+ {
+ /* Remove it from the current queue */
+ KiRemoveFromThreadList(Thread);
+
+ /* Re-insert it at its current priority */
+ KiInsertIntoThreadList(Priority, Thread);
+
+ /* Check if the old priority was lower */
+ if (KeGetCurrentThread()->Priority < Priority)
+ {
+ /* Dispatch it immediately */
+ KiDispatchThreadNoLock(Ready);
+ *Released = TRUE;
+ return;
+ }
+ }
+ else if (Thread->State == Running)
+ {
+ /* Check if the new priority is lower */
+ if (Priority < OldPriority)
+ {
+ /* Check for threads with a higher priority */
+ Mask = ~((1 << (Priority + 1)) - 1);
+ if (PriorityListMask & Mask)
+ {
+ /* Found a thread, is it us? */
+ if (Thread == KeGetCurrentThread())
+ {
+ /* Dispatch us */
+ KiDispatchThreadNoLock(Ready);
+ *Released = TRUE;
+ return;
+ }
+ else
+ {
+ /* Loop every CPU */
+ for (i = 0; i < KeNumberProcessors; i++)
+ {
+ /* Get the PCR for this CPU */
+ Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
+
+ /* Reschedule if the new one is already on a CPU */
+ if (Pcr->Prcb->CurrentThread == Thread)
+ {
+ KeReleaseDispatcherDatabaseLockFromDpcLevel();
+ KiRequestReschedule(i);
+ *Released = TRUE;
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Return to caller */
+ return;
}
/*
+ * Sets thread's base priority relative to the process' base priority
+ * Should only be passed in THREAD_PRIORITY_ constants in pstypes.h
+ *
* @implemented
*/
-KPRIORITY
+LONG
STDCALL
-KeSetPriorityThread(PKTHREAD Thread,
- KPRIORITY Priority)
+KeSetBasePriorityThread (PKTHREAD Thread,
+ LONG Increment)
{
- KPRIORITY OldPriority;
KIRQL OldIrql;
- PKTHREAD CurrentThread;
- ULONG Mask;
- int i;
- PKPCR Pcr;
+ PKPROCESS Process;
+ KPRIORITY Priority;
+ KPRIORITY CurrentBasePriority;
+ KPRIORITY BasePriority;
+ BOOLEAN Released = FALSE;
+ LONG CurrentIncrement;
+
+ /* Lock the Dispatcher Database */
+ OldIrql = KeAcquireDispatcherDatabaseLock();
- if (Priority < LOW_PRIORITY || Priority >= MAXIMUM_PRIORITY) {
+ /* Get the process and calculate current BP and BPI */
+ Process = Thread->ApcStatePointer[0]->Process;
+ CurrentBasePriority = Thread->BasePriority;
+ CurrentIncrement = CurrentBasePriority - Process->BasePriority;
- KEBUGCHECK(0);
+ /* Change to use the SI if Saturation was used */
+ if (Thread->Saturation) CurrentIncrement = (HIGH_PRIORITY + 1) / 2 *
+ Thread->Saturation;
+
+ /* Now check if saturation is being used for the new value */
+ if (abs(Increment) >= ((HIGH_PRIORITY + 1) / 2))
+ {
+ /* Check if we need positive or negative saturation */
+ Thread->Saturation = (Increment > 0) ? 1 : -1;
}
- OldIrql = KeAcquireDispatcherDatabaseLock();
+ /* Normalize the Base Priority */
+ BasePriority = Process->BasePriority + Increment;
+ if (Process->BasePriority >= LOW_REALTIME_PRIORITY)
+ {
+ /* Check if it's too low */
+ if (BasePriority < LOW_REALTIME_PRIORITY)
+ BasePriority = LOW_REALTIME_PRIORITY;
- OldPriority = Thread->Priority;
+ /* Check if it's too high */
+ if (BasePriority > HIGH_PRIORITY) BasePriority = HIGH_PRIORITY;
- if (OldPriority != Priority) {
+ /* We are at RTP, so use the raw BP */
+ Priority = BasePriority;
+ }
+ else
+ {
+ /* Check if it's entering RTP */
+ if (BasePriority >= LOW_REALTIME_PRIORITY)
+ BasePriority = LOW_REALTIME_PRIORITY - 1;
- CurrentThread = KeGetCurrentThread();
+ /* Check if it's too low */
+ if (BasePriority <= LOW_PRIORITY)
+ BasePriority = 1;
- if (Thread->State == Ready) {
+ /* If Saturation is used, then use the raw BP */
+ if (Thread->Saturation)
+ {
+ Priority = BasePriority;
+ }
+ else
+ {
+ /* Calculate the new priority */
+ Priority = Thread->Priority + (BasePriority - CurrentBasePriority)-
+ Thread->PriorityDecrement;
- KiRemoveFromThreadList(Thread);
- Thread->BasePriority = Thread->Priority = (CHAR)Priority;
- KiInsertIntoThreadList(Priority, Thread);
+ /* Make sure it won't enter RTP ranges */
+ if (Priority >= LOW_REALTIME_PRIORITY)
+ Priority = LOW_REALTIME_PRIORITY - 1;
+ }
+ }
- if (CurrentThread->Priority < Priority) {
+ /* Finally set the new base priority */
+ Thread->BasePriority = BasePriority;
- KiDispatchThreadNoLock(Ready);
- KeLowerIrql(OldIrql);
- return (OldPriority);
- }
+ /* Reset the decrements */
+ Thread->DecrementCount = 0;
+ Thread->PriorityDecrement = 0;
- } else if (Thread->State == Running) {
+ /* If the priority will change, reset quantum and change it for real */
+ if (Priority != Thread->Priority)
+ {
+ Thread->Quantum = Thread->QuantumReset;
+ KiSetPriorityThread(Thread, Priority, &Released);
+ }
- Thread->BasePriority = Thread->Priority = (CHAR)Priority;
+ /* Release Lock if needed */
+ if (!Released)
+ {
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+ }
+ else
+ {
+ KeLowerIrql(OldIrql);
+ }
- if (Priority < OldPriority) {
+ /* Return the Old Increment */
+ return CurrentIncrement;
+}
- /* Check for threads with a higher priority */
- Mask = ~((1 << (Priority + 1)) - 1);
- if (PriorityListMask & Mask) {
+/*
+ * @implemented
+ */
+KPRIORITY
+STDCALL
+KeSetPriorityThread(PKTHREAD Thread,
+ KPRIORITY Priority)
+{
+ KPRIORITY OldPriority;
+ BOOLEAN Released = FALSE;
+ KIRQL OldIrql;
- if (Thread == CurrentThread) {
+ /* Lock the Dispatcher Database */
+ OldIrql = KeAcquireDispatcherDatabaseLock();
- KiDispatchThreadNoLock(Ready);
- KeLowerIrql(OldIrql);
- return (OldPriority);
+ /* Save the old Priority */
+ OldPriority = Thread->Priority;
- } else {
+ /* Reset the Quantum and Decrements */
+ Thread->Quantum = Thread->QuantumReset;
+ Thread->DecrementCount = 0;
+ Thread->PriorityDecrement = 0;
- for (i = 0; i < KeNumberProcessors; i++) {
+ /* Set the new Priority */
+ KiSetPriorityThread(Thread, Priority, &Released);
- Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
-
- if (Pcr->Prcb->CurrentThread == Thread) {
-
- KeReleaseDispatcherDatabaseLockFromDpcLevel();
- KiRequestReschedule(i);
- KeLowerIrql(OldIrql);
- return (OldPriority);
- }
- }
- }
- }
- }
- } else {
-
- Thread->BasePriority = Thread->Priority = (CHAR)Priority;
- }
+ /* Release Lock if needed */
+ if (!Released)
+ {
+ KeReleaseDispatcherDatabaseLock(OldIrql);
}
+ else
+ {
+ KeLowerIrql(OldIrql);
+ }
- KeReleaseDispatcherDatabaseLock(OldIrql);
- return(OldPriority);
+ /* Return Old Priority */
+ return OldPriority;
}
/*