Add dispatcher object routing for wait satisfaction and interval calculation
This commit is contained in:
@@ -67,6 +67,9 @@
|
|||||||
#define READY_SKIP_QUANTUM 2
|
#define READY_SKIP_QUANTUM 2
|
||||||
#define THREAD_QUANTUM 6
|
#define THREAD_QUANTUM 6
|
||||||
|
|
||||||
|
/* Dispatcher object type mask */
|
||||||
|
#define DISPATCHER_OBJECT_TYPE_MASK 0x7L
|
||||||
|
|
||||||
/* Thread priority levels */
|
/* Thread priority levels */
|
||||||
#define THREAD_LOW_PRIORITY 0
|
#define THREAD_LOW_PRIORITY 0
|
||||||
#define THREAD_LOW_REALTIME_PRIORITY 16
|
#define THREAD_LOW_REALTIME_PRIORITY 16
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ list(APPEND XTOSKRNL_SOURCE
|
|||||||
${XTOSKRNL_SOURCE_DIR}/ke/crash.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/crash.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/data.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/data.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/dispatch.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/dispatch.cc
|
||||||
|
${XTOSKRNL_SOURCE_DIR}/ke/dispobj.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/dpc.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/dpc.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/event.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/event.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/exports.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/exports.cc
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <ke/bootinfo.hh>
|
#include <ke/bootinfo.hh>
|
||||||
#include <ke/crash.hh>
|
#include <ke/crash.hh>
|
||||||
#include <ke/dispatch.hh>
|
#include <ke/dispatch.hh>
|
||||||
|
#include <ke/dispobj.hh>
|
||||||
#include <ke/dpc.hh>
|
#include <ke/dpc.hh>
|
||||||
#include <ke/event.hh>
|
#include <ke/event.hh>
|
||||||
#include <ke/guard.hh>
|
#include <ke/guard.hh>
|
||||||
|
|||||||
@@ -23,10 +23,20 @@ namespace KE
|
|||||||
STATIC XTCDECL VOID HandleDispatchInterrupt(IN PKTRAP_FRAME TrapFrame);
|
STATIC XTCDECL VOID HandleDispatchInterrupt(IN PKTRAP_FRAME TrapFrame);
|
||||||
STATIC XTFASTCALL BOOLEAN SwitchContext(IN PKTHREAD CurrentThread,
|
STATIC XTFASTCALL BOOLEAN SwitchContext(IN PKTHREAD CurrentThread,
|
||||||
IN KRUNLEVEL RunLevel);
|
IN KRUNLEVEL RunLevel);
|
||||||
|
STATIC XTAPI XTSTATUS WaitForSingleObject(IN PVOID Object,
|
||||||
|
IN KWAIT_REASON WaitReason,
|
||||||
|
IN KPROCESSOR_MODE WaitMode,
|
||||||
|
IN BOOLEAN Alertable,
|
||||||
|
IN PLARGE_INTEGER Timeout);
|
||||||
STATIC XTAPI VOID UpdateRunTime(IN PKTRAP_FRAME TrapFrame,
|
STATIC XTAPI VOID UpdateRunTime(IN PKTRAP_FRAME TrapFrame,
|
||||||
IN KRUNLEVEL RunLevel);
|
IN KRUNLEVEL RunLevel);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
STATIC XTFASTCALL PLARGE_INTEGER ComputeWaitInterval(IN PLARGE_INTEGER OriginalDueTime,
|
||||||
|
IN PLARGE_INTEGER PreviousDueTime,
|
||||||
|
IN OUT PLARGE_INTEGER NewDueTime);
|
||||||
|
STATIC XTFASTCALL XTSTATUS SatisfyWaitingObject(IN PDISPATCHER_HEADER Object,
|
||||||
|
IN PKTHREAD Thread);
|
||||||
STATIC XTFASTCALL BOOLEAN SwitchThreadContext(IN PKTHREAD CurrentThread,
|
STATIC XTFASTCALL BOOLEAN SwitchThreadContext(IN PKTHREAD CurrentThread,
|
||||||
IN BOOLEAN ApcBypass);
|
IN BOOLEAN ApcBypass);
|
||||||
STATIC XTFASTCALL BOOLEAN SwitchThreadStack(IN PKTHREAD CurrentThread,
|
STATIC XTFASTCALL BOOLEAN SwitchThreadStack(IN PKTHREAD CurrentThread,
|
||||||
|
|||||||
29
xtoskrnl/includes/ke/dispobj.hh
Normal file
29
xtoskrnl/includes/ke/dispobj.hh
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* PROJECT: ExectOS
|
||||||
|
* COPYRIGHT: See COPYING.md in the top level directory
|
||||||
|
* FILE: xtoskrnl/includes/ke/dispobj.hh
|
||||||
|
* DESCRIPTION: Kernel Thread Dispatcher Objects
|
||||||
|
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XTOSKRNL_KE_DISPOBJ_HH
|
||||||
|
#define __XTOSKRNL_KE_DISPOBJ_HH
|
||||||
|
|
||||||
|
#include <xtos.hh>
|
||||||
|
|
||||||
|
|
||||||
|
/* Kernel Library */
|
||||||
|
namespace KE
|
||||||
|
{
|
||||||
|
class DispatcherObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
STATIC XTFASTCALL VOID SatisfyWaitingMutexObject(IN PKMUTEX MutexObject,
|
||||||
|
IN PKTHREAD Thread);
|
||||||
|
STATIC XTFASTCALL VOID SatisfyWaitingNonMutexObject(IN PDISPATCHER_HEADER MutexObject);
|
||||||
|
STATIC XTFASTCALL VOID SatisfyWaitingObject(IN PDISPATCHER_HEADER MutexObject,
|
||||||
|
IN PKTHREAD Thread);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __XTOSKRNL_KE_DISPOBJ_HH */
|
||||||
@@ -10,6 +10,45 @@
|
|||||||
#include <xtos.hh>
|
#include <xtos.hh>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the remaining wait interval for a thread after a wait operation has been interrupted.
|
||||||
|
*
|
||||||
|
* @param OriginalDueTime
|
||||||
|
* Supplies the original timeout value requested by the caller.
|
||||||
|
*
|
||||||
|
* @param PreviousDueTime
|
||||||
|
* Supplies the base timestamp, usually the time when the wait was first initiated.
|
||||||
|
*
|
||||||
|
* @param NewDueTime
|
||||||
|
* Supplies a pointer to a LARGE_INTEGER buffer where the recalculated time will be stored.
|
||||||
|
*
|
||||||
|
* @return This routine returns a pointer to the resulting due time.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTFASTCALL
|
||||||
|
PLARGE_INTEGER
|
||||||
|
KE::Dispatcher::ComputeWaitInterval(IN PLARGE_INTEGER OriginalDueTime,
|
||||||
|
IN PLARGE_INTEGER PreviousDueTime,
|
||||||
|
IN OUT PLARGE_INTEGER NewDueTime)
|
||||||
|
{
|
||||||
|
/* Check if the timeout is absolute */
|
||||||
|
if(OriginalDueTime->QuadPart >= 0)
|
||||||
|
{
|
||||||
|
/* No recalculation is needed, return the original value */
|
||||||
|
return OriginalDueTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fetch the current system interrupt time for the recalculation base */
|
||||||
|
KE::SystemTime::GetInterruptTime(NewDueTime);
|
||||||
|
|
||||||
|
/* Calculate the delta */
|
||||||
|
NewDueTime->QuadPart -= PreviousDueTime->QuadPart;
|
||||||
|
|
||||||
|
/* Return the new due time */
|
||||||
|
return NewDueTime;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enters the system idle thread loop for the current processor, running continuously when no other
|
* Enters the system idle thread loop for the current processor, running continuously when no other
|
||||||
* threads are scheduled for execution.
|
* threads are scheduled for execution.
|
||||||
@@ -149,7 +188,7 @@ KE::Dispatcher::HandleDispatchInterrupt(IN PKTRAP_FRAME TrapFrame)
|
|||||||
/* Start a guarded code block */
|
/* Start a guarded code block */
|
||||||
{
|
{
|
||||||
/* Lock the processor control block */
|
/* Lock the processor control block */
|
||||||
KE::SpinLockGuard ControlBlockGuard(&Prcb->PrcbLock);
|
KE::SpinLockGuard PrcbGuard(&Prcb->PrcbLock);
|
||||||
|
|
||||||
/* Capture the outgoing (preempted) and incoming threads */
|
/* Capture the outgoing (preempted) and incoming threads */
|
||||||
CurrentThread = Prcb->CurrentThread;
|
CurrentThread = Prcb->CurrentThread;
|
||||||
@@ -175,6 +214,60 @@ KE::Dispatcher::HandleDispatchInterrupt(IN PKTRAP_FRAME TrapFrame)
|
|||||||
AR::CpuFunctions::ClearInterruptFlag();
|
AR::CpuFunctions::ClearInterruptFlag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates the state of a dispatcher object to determine if a wait can be satisfied immediately without
|
||||||
|
* suspending the current thread.
|
||||||
|
*
|
||||||
|
* @param Object
|
||||||
|
* Supplies a pointer to the dispatcher object header.
|
||||||
|
*
|
||||||
|
* @param Thread
|
||||||
|
* Supplies a pointer to the current thread attempting to acquire the object.
|
||||||
|
*
|
||||||
|
* @return This routine returns a status code indicating the success or failure of the operation.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTFASTCALL
|
||||||
|
XTSTATUS
|
||||||
|
KE::Dispatcher::SatisfyWaitingObject(IN PDISPATCHER_HEADER Object,
|
||||||
|
IN PKTHREAD Thread)
|
||||||
|
{
|
||||||
|
PKMUTEX Mutex;
|
||||||
|
|
||||||
|
/* Check if the object is a Mutex */
|
||||||
|
if(Object->Type == MutexObject)
|
||||||
|
{
|
||||||
|
/* Get a pointer to the Mutex object */
|
||||||
|
Mutex = (PKMUTEX)Object;
|
||||||
|
|
||||||
|
/* Check if the mutex is free or if the current thread already owns it */
|
||||||
|
if((Mutex->Header.SignalState > 0) || (Thread == Mutex->OwnerThread))
|
||||||
|
{
|
||||||
|
/* Verify that recursive acquisition has not hit the mathematical lower bound */
|
||||||
|
if(Mutex->Header.SignalState != MINLONG)
|
||||||
|
{
|
||||||
|
/* Satisfy the wait and inherit priority if applicable */
|
||||||
|
KE::DispatcherObject::SatisfyWaitingMutexObject(Mutex, Thread);
|
||||||
|
return (XTSTATUS)Thread->WaitStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The mutex counter has overflowed */
|
||||||
|
return STATUS_MUTEX_LIMIT_EXCEEDED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(Object->SignalState > 0)
|
||||||
|
{
|
||||||
|
/* Apply generic satisfaction rules */
|
||||||
|
KE::DispatcherObject::SatisfyWaitingNonMutexObject(Object);
|
||||||
|
return STATUS_WAIT_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Object is not signaled, the thread must be queued */
|
||||||
|
return STATUS_PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the runtime quantum of the currently executing thread and handles preemption.
|
* Updates the runtime quantum of the currently executing thread and handles preemption.
|
||||||
*
|
*
|
||||||
@@ -291,3 +384,83 @@ KE::Dispatcher::UpdateRunTime(IN PKTRAP_FRAME TrapFrame,
|
|||||||
HL::Irq::SendSoftwareInterrupt(DISPATCH_LEVEL);
|
HL::Irq::SendSoftwareInterrupt(DISPATCH_LEVEL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Places the current thread into a wait state until the specified dispatcher object is set to a signaled state,
|
||||||
|
* or until the optional timeout expires.
|
||||||
|
*
|
||||||
|
* @param Object
|
||||||
|
* Supplies a pointer to the dispatcher object to wait on.
|
||||||
|
*
|
||||||
|
* @param WaitReason
|
||||||
|
* Supplies the reason for the wait, utilized for diagnostic and profiling purposes.
|
||||||
|
*
|
||||||
|
* @param WaitMode
|
||||||
|
* Supplies the processor mode in which the wait is occurring (KernelMode or UserMode).
|
||||||
|
*
|
||||||
|
* @param Alertable
|
||||||
|
* Specifies whether the wait is alertable by asynchronous procedure calls (APCs).
|
||||||
|
*
|
||||||
|
* @param Timeout
|
||||||
|
* Supplies an optional pointer to an absolute or relative timeout value.
|
||||||
|
*
|
||||||
|
* @return This routine returns the completion status of the wait operation.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTAPI
|
||||||
|
XTSTATUS
|
||||||
|
KE::Dispatcher::WaitForSingleObject(IN PVOID Object,
|
||||||
|
IN KWAIT_REASON WaitReason,
|
||||||
|
IN KPROCESSOR_MODE WaitMode,
|
||||||
|
IN BOOLEAN Alertable,
|
||||||
|
IN PLARGE_INTEGER Timeout)
|
||||||
|
{
|
||||||
|
PDISPATCHER_HEADER Header;
|
||||||
|
LARGE_INTEGER CurrentTime;
|
||||||
|
PKTHREAD CurrentThread;
|
||||||
|
|
||||||
|
/* Not implemented, active polling only */
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
|
||||||
|
/* Get the dispatcher header */
|
||||||
|
Header = (PDISPATCHER_HEADER)Object;
|
||||||
|
|
||||||
|
/* Get the current thread */
|
||||||
|
CurrentThread = KE::Processor::GetCurrentThread();
|
||||||
|
|
||||||
|
/* Check if the object is already signaled or if it is an already owned Mutex */
|
||||||
|
if((Header->SignalState > 0) || ((Header->Type == MutexObject) && (CurrentThread == ((PKMUTEX)Object)->OwnerThread)))
|
||||||
|
{
|
||||||
|
/* Satisfy the object and return status code */
|
||||||
|
SatisfyWaitingObject(Header, CurrentThread);
|
||||||
|
return STATUS_WAIT_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter cctive polling loop */
|
||||||
|
while(Header->SignalState <= 0)
|
||||||
|
{
|
||||||
|
/* Check if the timeout has expired */
|
||||||
|
if(Timeout != NULLPTR)
|
||||||
|
{
|
||||||
|
/* Get the current interrupt time */
|
||||||
|
KE::SystemTime::GetInterruptTime(&CurrentTime);
|
||||||
|
|
||||||
|
/* Check if current time exceeds the timeout value */
|
||||||
|
if(CurrentTime.QuadPart >= Timeout->QuadPart)
|
||||||
|
{
|
||||||
|
/* Wait expired, return status code */
|
||||||
|
return STATUS_TIMEOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Yield the processor */
|
||||||
|
AR::CpuFunctions::YieldProcessor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Apply acquisition rules */
|
||||||
|
SatisfyWaitingObject(Header, CurrentThread);
|
||||||
|
|
||||||
|
/* Return status code */
|
||||||
|
return STATUS_WAIT_0;
|
||||||
|
}
|
||||||
|
|||||||
113
xtoskrnl/ke/dispobj.cc
Normal file
113
xtoskrnl/ke/dispobj.cc
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
/**
|
||||||
|
* PROJECT: ExectOS
|
||||||
|
* COPYRIGHT: See COPYING.md in the top level directory
|
||||||
|
* FILE: xtoskrnl/ke/dispobj.cc
|
||||||
|
* DESCRIPTION: Kernel Thread Dispatcher Objects
|
||||||
|
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <xtos.hh>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Satisfies a wait operation specifically for a Mutex object.
|
||||||
|
*
|
||||||
|
* @param Mutex
|
||||||
|
* Supplies a pointer to the Mutex object being acquired.
|
||||||
|
*
|
||||||
|
* @param Thread
|
||||||
|
* Supplies a pointer to the thread that is acquiring the Mutex.
|
||||||
|
*
|
||||||
|
* @return This routine does not return any value.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTFASTCALL
|
||||||
|
VOID
|
||||||
|
KE::DispatcherObject::SatisfyWaitingMutexObject(IN PKMUTEX Mutex,
|
||||||
|
IN PKTHREAD Thread)
|
||||||
|
{
|
||||||
|
/* Decrement the signal state */
|
||||||
|
Mutex->Header.SignalState--;
|
||||||
|
|
||||||
|
/* Check if the mutex is now fully acquired */
|
||||||
|
if(!Mutex->Header.SignalState)
|
||||||
|
{
|
||||||
|
/* Bind the mutex ownership to the current acquiring thread */
|
||||||
|
Mutex->OwnerThread = Thread;
|
||||||
|
|
||||||
|
/* Inherit the APC disable from the mutex */
|
||||||
|
Thread->KernelApcDisable = Thread->KernelApcDisable - Mutex->ApcDisable;
|
||||||
|
|
||||||
|
/* Check if the previous owner terminated without releasing the mutex */
|
||||||
|
if(Mutex->Abandoned)
|
||||||
|
{
|
||||||
|
/* Clear the abandonment flag */
|
||||||
|
Mutex->Abandoned = FALSE;
|
||||||
|
|
||||||
|
/* Alert the thread */
|
||||||
|
Thread->WaitStatus = STATUS_ABANDONED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Track this mutex in the thread's local list */
|
||||||
|
RTL::LinkedList::InsertHeadList(Thread->MutexListHead.Blink, &Mutex->MutexListEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Satisfies a wait operation for non-mutex dispatcher objects, such as Synchronization Events and Semaphores.
|
||||||
|
*
|
||||||
|
* @param Object
|
||||||
|
* Supplies a pointer to the dispatcher object.
|
||||||
|
*
|
||||||
|
* @return This routine does not return any value.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTFASTCALL
|
||||||
|
VOID
|
||||||
|
KE::DispatcherObject::SatisfyWaitingNonMutexObject(IN PDISPATCHER_HEADER Object)
|
||||||
|
{
|
||||||
|
/* Check if the object is a Synchronization Event */
|
||||||
|
if((Object->Type & DISPATCHER_OBJECT_TYPE_MASK) == EventSynchronizationObject)
|
||||||
|
{
|
||||||
|
/* Reset the event */
|
||||||
|
Object->SignalState = 0;
|
||||||
|
}
|
||||||
|
else if(Object->Type == SemaphoreObject)
|
||||||
|
{
|
||||||
|
/* Decrement the signal state */
|
||||||
|
Object->SignalState--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates the object type and routes the wait satisfaction logic to the appropriate specialized handler.
|
||||||
|
*
|
||||||
|
* @param Object
|
||||||
|
* Supplies a pointer to the dispatcher object being acquired.
|
||||||
|
*
|
||||||
|
* @param Thread
|
||||||
|
* Supplies a pointer to the thread acquiring the object.
|
||||||
|
*
|
||||||
|
* @return This routine does not return any value.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTFASTCALL
|
||||||
|
VOID
|
||||||
|
KE::DispatcherObject::SatisfyWaitingObject(IN PDISPATCHER_HEADER Object,
|
||||||
|
IN PKTHREAD Thread)
|
||||||
|
{
|
||||||
|
/* Check if the object is a Mutex */
|
||||||
|
if(Object->Type == MutexObject)
|
||||||
|
{
|
||||||
|
/* Apply mutex-specific acquisition rules */
|
||||||
|
SatisfyWaitingMutexObject((PKMUTEX)Object, Thread);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Apply generic acquisition rules for events, semaphores, and timers */
|
||||||
|
SatisfyWaitingNonMutexObject(Object);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user