{
PKWAIT_BLOCK WaitBlock;
PKTIMER Timer;
+ LONG NewPriority;
/* Update wait status */
Thread->WaitStatus |= WaitStatus;
WaitBlock = WaitBlock->NextWaitBlock;
} while (WaitBlock != Thread->WaitBlockList);
- /* FIXME: Remove the thread from the wait list! */
- //RemoveEntryList(&Thread->WaitListEntry);
+ /* Remove the thread from the wait list! */
+ if (Thread->WaitListEntry.Flink) RemoveEntryList(&Thread->WaitListEntry);
/* Check if there's a Thread Timer */
Timer = &Thread->Timer;
/* Increment the Queue's active threads */
if (Thread->Queue) Thread->Queue->CurrentCount++;
+ /* Check if this is a non-RT thread */
+ if (Thread->Priority < LOW_REALTIME_PRIORITY)
+ {
+ /* Check if boosting is enabled and we can boost */
+ if (!(Thread->DisableBoost) && !(Thread->PriorityDecrement))
+ {
+ /* We can boost, so calculate the new priority */
+ NewPriority = Thread->BasePriority + Increment;
+ if (NewPriority > Thread->Priority)
+ {
+ /* Make sure the new priority wouldn't push the thread to RT */
+ if (NewPriority >= LOW_REALTIME_PRIORITY)
+ {
+ /* Set it just before the RT zone */
+ Thread->Priority = LOW_REALTIME_PRIORITY - 1;
+ }
+ else
+ {
+ /* Otherwise, set our calculated priority */
+ Thread->Priority = NewPriority;
+ }
+ }
+ }
+
+ /* Check if this is a high-priority thread */
+ if (Thread->BasePriority >= 14)
+ {
+ /* It is, simply reset the quantum */
+ Thread->Quantum = Thread->QuantumReset;
+ }
+ else
+ {
+ /* Otherwise, decrease quantum */
+ Thread->Quantum--;
+ if (Thread->Quantum <= 0)
+ {
+ /* We've went below 0, reset it */
+ Thread->Quantum = Thread->QuantumReset;
+
+ /* Apply per-quantum priority decrement */
+ Thread->Priority -= (Thread->PriorityDecrement + 1);
+ if (Thread->Priority < Thread->BasePriority)
+ {
+ /* We've went too low, reset it */
+ Thread->Priority = Thread->BasePriority;
+ }
+
+ /* Delete per-quantum decrement */
+ Thread->PriorityDecrement = 0;
+ }
+ }
+ }
+ else
+ {
+ /* For real time threads, just reset the quantum */
+ Thread->Quantum = Thread->QuantumReset;
+ }
+
/* Reschedule the Thread */
- KiUnblockThread(Thread, NULL, Increment);
+ KiReadyThread(Thread);
}
VOID
PKTIMER ThreadTimer;
PKTHREAD CurrentThread = KeGetCurrentThread();
NTSTATUS WaitStatus = STATUS_SUCCESS;
+ BOOLEAN Swappable;
+ PLARGE_INTEGER OriginalDueTime = Interval;
+ LARGE_INTEGER DueTime, NewDueTime;
/* Check if the lock is already held */
if (CurrentThread->WaitNext)
/* Check if we can do an alertable wait, if requested */
KiCheckAlertability();
+ /* Check if we can swap the thread's stack */
+ CurrentThread->WaitListEntry.Flink = NULL;
+ KiCheckThreadStackSwap(WaitMode, CurrentThread, Swappable);
+
/* Set status */
CurrentThread->WaitStatus = STATUS_WAIT_0;
break;
}
+ /* Save due time */
+ DueTime.QuadPart = ThreadTimer->DueTime.QuadPart;
+
/* Handle Kernel Queues */
if (CurrentThread->Queue) KiWakeQueue(CurrentThread->Queue);
CurrentThread->State = Waiting;
/* Find a new thread to run */
+ KiAddThreadToWaitList(CurrentThread, Swappable);
WaitStatus = KiSwapThread();
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
return WaitStatus;
}
- /* FIXME: Fixup interval */
+ /* Recalculate due times */
+ Interval = KiRecalculateDueTime(OriginalDueTime,
+ &DueTime,
+ &NewDueTime);
}
/* Acquire again the lock */
*/
NTSTATUS
NTAPI
-KeWaitForSingleObject(PVOID Object,
- KWAIT_REASON WaitReason,
- KPROCESSOR_MODE WaitMode,
- BOOLEAN Alertable,
- PLARGE_INTEGER Timeout)
+KeWaitForSingleObject(IN PVOID Object,
+ IN KWAIT_REASON WaitReason,
+ IN KPROCESSOR_MODE WaitMode,
+ IN BOOLEAN Alertable,
+ IN PLARGE_INTEGER Timeout OPTIONAL)
{
PKMUTANT CurrentObject;
PKWAIT_BLOCK WaitBlock;
PKTIMER ThreadTimer;
PKTHREAD CurrentThread = KeGetCurrentThread();
NTSTATUS WaitStatus = STATUS_SUCCESS;
+ BOOLEAN Swappable;
+ LARGE_INTEGER DueTime, NewDueTime;
+ PLARGE_INTEGER OriginalDueTime = Timeout;
/* Check if the lock is already held */
if (CurrentThread->WaitNext)
}
/* Start the actual Loop */
+ WaitBlock = &CurrentThread->WaitBlock[0];
do
{
/* Check if a kernel APC is pending and we're below APC_LEVEL */
/* Set default status */
CurrentThread->WaitStatus = STATUS_WAIT_0;
- /* Append wait block to the KTHREAD wait block list */
- WaitBlock = &CurrentThread->WaitBlock[0];
- CurrentThread->WaitBlockList = WaitBlock;
-
/* Get the Current Object */
CurrentObject = (PKMUTANT)Object;
goto DontWait;
}
+ /* Append wait block to the KTHREAD wait block list */
+ CurrentThread->WaitBlockList = WaitBlock;
+
/* Set up the Wait Block */
WaitBlock->Object = CurrentObject;
- WaitBlock->Thread = CurrentThread;
WaitBlock->WaitKey = (USHORT)(STATUS_SUCCESS);
WaitBlock->WaitType = WaitAny;
- WaitBlock->NextWaitBlock = WaitBlock;
/* Make sure we can satisfy the Alertable request */
KiCheckAlertability();
+ /* Check if we can swap the thread's stack */
+ CurrentThread->WaitListEntry.Flink = NULL;
+ KiCheckThreadStackSwap(WaitMode, CurrentThread, Swappable);
+
/* Enable the Timeout Timer if there was any specified */
if (Timeout)
{
WaitStatus = STATUS_TIMEOUT;
goto DontWait;
}
+
+ /* Set the current due time */
+ DueTime.QuadPart = ThreadTimer->DueTime.QuadPart;
+ }
+ else
+ {
+ /* No timer block, so just set our wait block as next */
+ WaitBlock->NextWaitBlock = WaitBlock;
}
/* Link the Object to this Wait Block */
CurrentThread->State = Waiting;
/* Find a new thread to run */
+ KiAddThreadToWaitList(CurrentThread, Swappable);
WaitStatus = KiSwapThread();
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Check if we had a timeout */
if (Timeout)
{
- /* FIXME: Fixup interval */
+ /* Recalculate due times */
+ Timeout = KiRecalculateDueTime(OriginalDueTime,
+ &DueTime,
+ &NewDueTime);
}
}
ULONG AllObjectsSignaled;
ULONG WaitIndex;
NTSTATUS WaitStatus = STATUS_SUCCESS;
+ BOOLEAN Swappable;
+ PLARGE_INTEGER OriginalDueTime = Timeout;
+ LARGE_INTEGER DueTime, NewDueTime;
/* Set the Current Thread */
CurrentThread = KeGetCurrentThread();
/* Make sure we can satisfy the Alertable request */
KiCheckAlertability();
+ /* Check if we can swap the thread's stack */
+ CurrentThread->WaitListEntry.Flink = NULL;
+ KiCheckThreadStackSwap(WaitMode, CurrentThread, Swappable);
+
/* Enable the Timeout Timer if there was any specified */
if (Timeout)
{
WaitStatus = STATUS_TIMEOUT;
goto DontWait;
}
+
+ /* Set the current due time */
+ DueTime.QuadPart = ThreadTimer->DueTime.QuadPart;
}
/* Insert into Object's Wait List*/
CurrentThread->State = Waiting;
/* Find a new thread to run */
+ KiAddThreadToWaitList(CurrentThread, Swappable);
WaitStatus = KiSwapThread();
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Check if we had a timeout */
if (Timeout)
{
- /* FIXME: Fixup interval */
+ /* Recalculate due times */
+ Timeout = KiRecalculateDueTime(OriginalDueTime,
+ &DueTime,
+ &NewDueTime);
}
/* Acquire again the lock */