From e6464bc179340424128f28be2f0aec044e285b8c Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 12 Jan 2005 13:43:05 +0000 Subject: [PATCH] Basic support for priority boosting. svn path=/trunk/; revision=12965 --- reactos/ntoskrnl/include/internal/ke.h | 2 +- reactos/ntoskrnl/include/internal/ps.h | 2 +- reactos/ntoskrnl/ke/event.c | 8 ++--- reactos/ntoskrnl/ke/mutex.c | 4 +-- reactos/ntoskrnl/ke/queue.c | 4 +-- reactos/ntoskrnl/ke/sem.c | 2 +- reactos/ntoskrnl/ke/timer.c | 2 +- reactos/ntoskrnl/ke/wait.c | 32 +++++++++--------- reactos/ntoskrnl/ps/create.c | 8 ++--- reactos/ntoskrnl/ps/kill.c | 4 +-- reactos/ntoskrnl/ps/thread.c | 45 +++++++++++++++++++++++++- 11 files changed, 79 insertions(+), 34 deletions(-) diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index b75646224b6..14ba678b188 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -147,7 +147,7 @@ VOID KeAcquireDispatcherDatabaseLockAtDpcLevel(VOID); VOID KeReleaseDispatcherDatabaseLock(KIRQL Irql); VOID KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID); -BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr); +BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment); VOID STDCALL KeExpireTimers(PKDPC Apc, PVOID Arg1, PVOID Arg2, diff --git a/reactos/ntoskrnl/include/internal/ps.h b/reactos/ntoskrnl/include/internal/ps.h index 362b0faaf4b..8e2110c0362 100644 --- a/reactos/ntoskrnl/include/internal/ps.h +++ b/reactos/ntoskrnl/include/internal/ps.h @@ -528,7 +528,7 @@ VOID PsBlockThread(PNTSTATUS Status, UCHAR Alertable, ULONG WaitMode, BOOLEAN DispatcherLock, KIRQL WaitIrql, UCHAR WaitReason); VOID -PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus); +PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus, KPRIORITY Increment); VOID PsApplicationProcessorInit(VOID); VOID diff --git a/reactos/ntoskrnl/ke/event.c b/reactos/ntoskrnl/ke/event.c index b352142f623..acca6f21367 100644 --- a/reactos/ntoskrnl/ke/event.c +++ b/reactos/ntoskrnl/ke/event.c @@ -87,9 +87,9 @@ LONG STDCALL KeSetEvent (PKEVENT Event, OldIrql = KeAcquireDispatcherDatabaseLock(); - ret = InterlockedExchange(&(Event->Header.SignalState),1); + ret = InterlockedExchange(&Event->Header.SignalState,1); - KiDispatcherObjectWake((DISPATCHER_HEADER *)Event); + KiDispatcherObjectWake(&Event->Header, Increment); if (Wait == FALSE) { @@ -117,8 +117,8 @@ NTSTATUS STDCALL KePulseEvent (PKEVENT Event, DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event,Wait); OldIrql = KeAcquireDispatcherDatabaseLock(); - ret = InterlockedExchange(&(Event->Header.SignalState),1); - KiDispatcherObjectWake((DISPATCHER_HEADER *)Event); + ret = InterlockedExchange(&Event->Header.SignalState,1); + KiDispatcherObjectWake(&Event->Header, Increment); InterlockedExchange(&(Event->Header.SignalState),0); if (Wait == FALSE) diff --git a/reactos/ntoskrnl/ke/mutex.c b/reactos/ntoskrnl/ke/mutex.c index 841b44d3ddf..5f69af5ee61 100644 --- a/reactos/ntoskrnl/ke/mutex.c +++ b/reactos/ntoskrnl/ke/mutex.c @@ -82,7 +82,7 @@ KeReleaseMutex(IN PKMUTEX Mutex, Mutex->OwnerThread = NULL; if (Mutex->MutantListEntry.Flink && Mutex->MutantListEntry.Blink) RemoveEntryList(&Mutex->MutantListEntry); - KiDispatcherObjectWake(&Mutex->Header); + KiDispatcherObjectWake(&Mutex->Header, IO_NO_INCREMENT); } if (Wait == FALSE) @@ -191,7 +191,7 @@ KeReleaseMutant(IN PKMUTANT Mutant, Mutant->OwnerThread = NULL; if (Mutant->MutantListEntry.Flink && Mutant->MutantListEntry.Blink) RemoveEntryList(&Mutant->MutantListEntry); - KiDispatcherObjectWake(&Mutant->Header); + KiDispatcherObjectWake(&Mutant->Header, Increment); } if (Wait == FALSE) diff --git a/reactos/ntoskrnl/ke/queue.c b/reactos/ntoskrnl/ke/queue.c index 1e45c3c65e7..35095eed030 100644 --- a/reactos/ntoskrnl/ke/queue.c +++ b/reactos/ntoskrnl/ke/queue.c @@ -100,7 +100,7 @@ KiInsertQueue( !IsListEmpty(&Queue->Header.WaitListHead) && KeGetCurrentThread()->Queue != Queue) { - KiDispatcherObjectWake(&Queue->Header); + KiDispatcherObjectWake(&Queue->Header, IO_NO_INCREMENT); } return InitialState; @@ -179,7 +179,7 @@ KeRemoveQueue(IN PKQUEUE Queue, if (Thread->Queue->CurrentCount < Thread->Queue->MaximumCount && !IsListEmpty(&Thread->Queue->EntryListHead)) { - KiDispatcherObjectWake(&Thread->Queue->Header); + KiDispatcherObjectWake(&Thread->Queue->Header, 0); } } diff --git a/reactos/ntoskrnl/ke/sem.c b/reactos/ntoskrnl/ke/sem.c index f3b226b4456..51493a02c8d 100644 --- a/reactos/ntoskrnl/ke/sem.c +++ b/reactos/ntoskrnl/ke/sem.c @@ -105,7 +105,7 @@ KeReleaseSemaphore (PKSEMAPHORE Semaphore, Semaphore->Header.SignalState += Adjustment; if (InitialState == 0) { - KiDispatcherObjectWake(&Semaphore->Header); + KiDispatcherObjectWake(&Semaphore->Header, SEMAPHORE_INCREMENT); } if (Wait == FALSE) diff --git a/reactos/ntoskrnl/ke/timer.c b/reactos/ntoskrnl/ke/timer.c index 28a44c32a1b..4e0a421680d 100644 --- a/reactos/ntoskrnl/ke/timer.c +++ b/reactos/ntoskrnl/ke/timer.c @@ -529,7 +529,7 @@ HandleExpiredTimer(PKTIMER Timer) KeAcquireDispatcherDatabaseLockAtDpcLevel(); Timer->Header.SignalState = TRUE; - KiDispatcherObjectWake(&Timer->Header); + KiDispatcherObjectWake(&Timer->Header, 0); KeReleaseDispatcherDatabaseLockFromDpcLevel(); if (Timer->Period != 0) diff --git a/reactos/ntoskrnl/ke/wait.c b/reactos/ntoskrnl/ke/wait.c index 89c0c048b6f..c13cd4466c0 100644 --- a/reactos/ntoskrnl/ke/wait.c +++ b/reactos/ntoskrnl/ke/wait.c @@ -25,8 +25,8 @@ static KSPIN_LOCK DispatcherDatabaseLock; -#define KeDispatcherObjectWakeOne(hdr) KeDispatcherObjectWakeOneOrAll(hdr, FALSE) -#define KeDispatcherObjectWakeAll(hdr) KeDispatcherObjectWakeOneOrAll(hdr, TRUE) +#define KeDispatcherObjectWakeOne(hdr, increment) KeDispatcherObjectWakeOneOrAll(hdr, increment, FALSE) +#define KeDispatcherObjectWakeAll(hdr, increment) KeDispatcherObjectWakeOneOrAll(hdr, increment, TRUE) extern POBJECT_TYPE EXPORTED ExMutantObjectType; extern POBJECT_TYPE EXPORTED ExSemaphoreObjectType; @@ -227,13 +227,14 @@ BOOLEAN KiAbortWaitThread(PKTHREAD Thread, NTSTATUS WaitStatus) if (WasWaiting) { - PsUnblockThread((PETHREAD)Thread, &WaitStatus); + PsUnblockThread((PETHREAD)Thread, &WaitStatus, 0); } return WasWaiting; } static BOOLEAN KeDispatcherObjectWakeOneOrAll(DISPATCHER_HEADER * hdr, + KPRIORITY increment, BOOLEAN WakeAll) { PKWAIT_BLOCK Waiter; @@ -332,7 +333,8 @@ KeDispatcherObjectWakeOneOrAll(DISPATCHER_HEADER * hdr, WakedAny = TRUE; DPRINT("Waking %x status = %x\n", WaiterHead->Thread, Status); - PsUnblockThread(CONTAINING_RECORD(WaiterHead->Thread, ETHREAD, Tcb), &Status); + PsUnblockThread(CONTAINING_RECORD(WaiterHead->Thread, ETHREAD, Tcb), + &Status, increment); } } @@ -340,7 +342,7 @@ KeDispatcherObjectWakeOneOrAll(DISPATCHER_HEADER * hdr, } -BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr) +BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment) /* * FUNCTION: Wake threads waiting on a dispatcher object * NOTE: The exact semantics of waking are dependant on the type of object @@ -355,19 +357,19 @@ BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr) switch (hdr->Type) { case InternalNotificationEvent: - return(KeDispatcherObjectWakeAll(hdr)); + return(KeDispatcherObjectWakeAll(hdr, increment)); case InternalNotificationTimer: - return(KeDispatcherObjectWakeAll(hdr)); + return(KeDispatcherObjectWakeAll(hdr, increment)); case InternalSynchronizationEvent: - return(KeDispatcherObjectWakeOne(hdr)); + return(KeDispatcherObjectWakeOne(hdr, increment)); case InternalSynchronizationTimer: - return(KeDispatcherObjectWakeOne(hdr)); + return(KeDispatcherObjectWakeOne(hdr, increment)); case InternalQueueType: - return(KeDispatcherObjectWakeOne(hdr)); + return(KeDispatcherObjectWakeOne(hdr, increment)); case InternalSemaphoreType: DPRINT("hdr->SignalState %d\n", hdr->SignalState); @@ -376,20 +378,20 @@ BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr) do { DPRINT("Waking one semaphore waiter\n"); - Ret = KeDispatcherObjectWakeOne(hdr); + Ret = KeDispatcherObjectWakeOne(hdr, increment); } while(hdr->SignalState > 0 && Ret) ; return(Ret); } else return FALSE; case InternalProcessType: - return(KeDispatcherObjectWakeAll(hdr)); + return(KeDispatcherObjectWakeAll(hdr, increment)); case InternalThreadType: - return(KeDispatcherObjectWakeAll(hdr)); + return(KeDispatcherObjectWakeAll(hdr, increment)); case InternalMutexType: - return(KeDispatcherObjectWakeOne(hdr)); + return(KeDispatcherObjectWakeOne(hdr, increment)); } DbgPrint("Dispatcher object %x has unknown type %d\n", hdr, hdr->Type); KEBUGCHECK(0); @@ -723,7 +725,7 @@ KeWaitForMultipleObjects(ULONG Count, if (CurrentThread->Queue->CurrentCount < CurrentThread->Queue->MaximumCount && !IsListEmpty(&CurrentThread->Queue->EntryListHead)) { - KiDispatcherObjectWake(&CurrentThread->Queue->Header); + KiDispatcherObjectWake(&CurrentThread->Queue->Header, IO_NO_INCREMENT); } } diff --git a/reactos/ntoskrnl/ps/create.c b/reactos/ntoskrnl/ps/create.c index 0197e2e09c7..744808f06f7 100644 --- a/reactos/ntoskrnl/ps/create.c +++ b/reactos/ntoskrnl/ps/create.c @@ -748,7 +748,7 @@ NtCreateThread(OUT PHANDLE ThreadHandle, Thread->Tcb.Alerted[KernelMode] = TRUE; oldIrql = KeAcquireDispatcherDatabaseLock (); - PsUnblockThread(Thread, NULL); + PsUnblockThread(Thread, NULL, 0); KeReleaseDispatcherDatabaseLock(oldIrql); @@ -814,9 +814,9 @@ PsCreateSystemThread(PHANDLE ThreadHandle, *ClientId=Thread->Cid; } - oldIrql = KeAcquireDispatcherDatabaseLock (); - PsUnblockThread(Thread, NULL); - KeReleaseDispatcherDatabaseLock(oldIrql); + oldIrql = KeAcquireDispatcherDatabaseLock (); + PsUnblockThread(Thread, NULL, 0); + KeReleaseDispatcherDatabaseLock(oldIrql); return(STATUS_SUCCESS); } diff --git a/reactos/ntoskrnl/ps/kill.c b/reactos/ntoskrnl/ps/kill.c index 40d24b14f71..e9eee49b044 100644 --- a/reactos/ntoskrnl/ps/kill.c +++ b/reactos/ntoskrnl/ps/kill.c @@ -191,7 +191,7 @@ PsTerminateCurrentThread(NTSTATUS ExitStatus) oldIrql = KeAcquireDispatcherDatabaseLock(); CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE; - KiDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader); + KiDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader, IO_NO_INCREMENT); KeReleaseDispatcherDatabaseLock (oldIrql); /* The last thread shall close the door on exit */ @@ -325,7 +325,7 @@ PiTerminateProcess(PEPROCESS Process, } OldIrql = KeAcquireDispatcherDatabaseLock (); Process->Pcb.DispatcherHeader.SignalState = TRUE; - KiDispatcherObjectWake(&Process->Pcb.DispatcherHeader); + KiDispatcherObjectWake(&Process->Pcb.DispatcherHeader, IO_NO_INCREMENT); KeReleaseDispatcherDatabaseLock (OldIrql); ObDereferenceObject(Process); return(STATUS_SUCCESS); diff --git a/reactos/ntoskrnl/ps/thread.c b/reactos/ntoskrnl/ps/thread.c index e854dab2e62..0e72788a719 100644 --- a/reactos/ntoskrnl/ps/thread.c +++ b/reactos/ntoskrnl/ps/thread.c @@ -475,7 +475,7 @@ PsDispatchThread(ULONG NewThreadStatus) } VOID -PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus) +PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus, KPRIORITY Increment) { if (THREAD_STATE_TERMINATED_1 == Thread->Tcb.State || THREAD_STATE_TERMINATED_2 == Thread->Tcb.State) @@ -493,6 +493,22 @@ PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus) { ULONG Processor; KAFFINITY Affinity; + + /* FIXME: This propably isn't the right way to do it... */ + if (Thread->Tcb.Priority < LOW_REALTIME_PRIORITY && + Thread->Tcb.BasePriority < LOW_REALTIME_PRIORITY - 2) + { + if (!Thread->Tcb.PriorityDecrement && !Thread->Tcb.DisableBoost) + { + Thread->Tcb.Priority = Thread->Tcb.BasePriority + Increment; + Thread->Tcb.PriorityDecrement = Increment; + } + } + else + { + Thread->Tcb.Quantum = Thread->Tcb.ApcState.Process->ThreadQuantum; + } + if (WaitStatus != NULL) { Thread->Tcb.WaitStatus = *WaitStatus; @@ -965,6 +981,33 @@ KeSetAffinityThread(PKTHREAD Thread, } +NTSTATUS STDCALL +NtAlertThread (IN HANDLE ThreadHandle) +{ + PETHREAD Thread; + NTSTATUS Status; + NTSTATUS ThreadStatus; + KIRQL oldIrql; + + Status = ObReferenceObjectByHandle(ThreadHandle, + THREAD_SUSPEND_RESUME, + PsThreadType, + UserMode, + (PVOID*)&Thread, + NULL); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + + ThreadStatus = STATUS_ALERTED; + oldIrql = KeAcquireDispatcherDatabaseLock(); + (VOID)PsUnblockThread(Thread, &ThreadStatus, 0); + KeReleaseDispatcherDatabaseLock(oldIrql); + + ObDereferenceObject(Thread); + return(STATUS_SUCCESS); +} /********************************************************************** * NtOpenThread/4