Implemented sleep for threads🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉

This commit is contained in:
Alex 2022-12-24 06:22:50 +02:00
parent 690191b927
commit 0942fb4cd3
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
4 changed files with 81 additions and 1 deletions

View File

@ -15,7 +15,7 @@ namespace Time
void time::Sleep(uint64_t Milliseconds) void time::Sleep(uint64_t Milliseconds)
{ {
#if defined(__amd64__) || defined(__i386__) #if defined(__amd64__) || defined(__i386__)
uintptr_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Milliseconds * 1000000000000) / clk; uint64_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Milliseconds * 1000000000000) / clk;
#ifdef DEBUG #ifdef DEBUG
uint64_t Counter = mminq(&((HPET *)hpet)->MainCounterValue); uint64_t Counter = mminq(&((HPET *)hpet)->MainCounterValue);
while (Counter < Target) while (Counter < Target)
@ -31,6 +31,22 @@ namespace Time
#endif #endif
} }
uint64_t time::GetCounter()
{
#if defined(__amd64__) || defined(__i386__)
return mminq(&((HPET *)hpet)->MainCounterValue);
#elif defined(__aarch64__)
#endif
}
uint64_t time::CalculateTarget(uint64_t Milliseconds)
{
#if defined(__amd64__) || defined(__i386__)
return mminq(&((HPET *)hpet)->MainCounterValue) + (Milliseconds * 1000000000000) / clk;
#elif defined(__aarch64__)
#endif
}
time::time(void *_acpi) time::time(void *_acpi)
{ {
if (_acpi) if (_acpi)

View File

@ -349,6 +349,47 @@ namespace Tasking
return false; return false;
} }
SafeFunction __no_instrument_function void Task::WakeUpThreads(void *CPUDataPointer)
{
CPUData *CurrentCPU = (CPUData *)CPUDataPointer;
// Loop through all the processes.
foreach (PCB *pcb in ListProcess)
{
if (InvalidPCB(pcb))
continue;
// Check process status.
switch (pcb->Status)
{
case TaskStatus::Ready:
schedbg("Ready process (%s)%d", pcb->Name, pcb->ID);
break;
default:
schedbg("Process \"%s\"(%d) status %d", pcb->Name, pcb->ID, pcb->Status);
continue;
}
// Loop through all the threads.
foreach (TCB *tcb in pcb->Threads)
{
if (InvalidTCB(tcb))
continue;
// Check if the thread is sleeping.
if (tcb->Status != TaskStatus::Sleeping)
continue;
// Check if the thread is ready to wake up.
if (tcb->Info.SleepUntil < TimeManager->GetCounter())
{
tcb->Status = TaskStatus::Ready;
tcb->Info.SleepUntil = 0;
schedbg("Thread \"%s\"(%d) woke up.", tcb->Name, tcb->ID);
}
}
}
}
SafeFunction __no_instrument_function void Task::Schedule(CPU::x64::TrapFrame *Frame) SafeFunction __no_instrument_function void Task::Schedule(CPU::x64::TrapFrame *Frame)
{ {
SmartCriticalSection(SchedulerLock); SmartCriticalSection(SchedulerLock);
@ -409,6 +450,9 @@ namespace Tasking
if (CurrentCPU->CurrentThread->Status == TaskStatus::Running) if (CurrentCPU->CurrentThread->Status == TaskStatus::Running)
CurrentCPU->CurrentThread->Status = TaskStatus::Ready; CurrentCPU->CurrentThread->Status = TaskStatus::Ready;
// Loop through all threads and find which one is ready.
WakeUpThreads(CurrentCPU);
// Get next available thread from the list. // Get next available thread from the list.
if (this->GetNextAvailableThread(CurrentCPU)) if (this->GetNextAvailableThread(CurrentCPU))
goto Success; goto Success;
@ -690,6 +734,15 @@ namespace Tasking
CPU::Halt(); CPU::Halt();
} }
void Task::Sleep(uint64_t Milliseconds)
{
SmartCriticalSection(SchedulerLock);
TCB *thread = this->GetCurrentThread();
thread->Status = TaskStatus::Sleeping;
thread->Info.SleepUntil = TimeManager->CalculateTarget(Milliseconds);
OneShot(1);
}
TCB *Task::CreateThread(PCB *Parent, TCB *Task::CreateThread(PCB *Parent,
IP EntryPoint, IP EntryPoint,
const char **argv, const char **argv,

View File

@ -68,6 +68,7 @@ namespace Tasking
struct TaskInfo struct TaskInfo
{ {
uint64_t SleepUntil = 0;
uint64_t SpawnTime = 0; uint64_t SpawnTime = 0;
uint64_t OldUserTime = 0, CurrentUserTime = 0; uint64_t OldUserTime = 0, CurrentUserTime = 0;
uint64_t OldKernelTime = 0, CurrentKernelTime = 0; uint64_t OldKernelTime = 0, CurrentKernelTime = 0;
@ -216,6 +217,7 @@ namespace Tasking
bool GetNextAvailableProcess(void *CPUDataPointer); bool GetNextAvailableProcess(void *CPUDataPointer);
void SchedulerCleanupProcesses(); void SchedulerCleanupProcesses();
bool SchedulerSearchProcessThread(void *CPUDataPointer); bool SchedulerSearchProcessThread(void *CPUDataPointer);
void WakeUpThreads(void *CPUDataPointer);
#if defined(__amd64__) #if defined(__amd64__)
void Schedule(CPU::x64::TrapFrame *Frame); void Schedule(CPU::x64::TrapFrame *Frame);
@ -276,6 +278,13 @@ namespace Tasking
/** @brief Wait for thread to terminate */ /** @brief Wait for thread to terminate */
void WaitForThread(TCB *tcb); void WaitForThread(TCB *tcb);
/**
* @brief Sleep for a given amount of milliseconds
*
* @param Milliseconds Amount of milliseconds to sleep
*/
void Sleep(uint64_t Milliseconds);
PCB *CreateProcess(PCB *Parent, PCB *CreateProcess(PCB *Parent,
const char *Name, const char *Name,
TaskTrustLevel TrustLevel, void *Image = nullptr); TaskTrustLevel TrustLevel, void *Image = nullptr);

View File

@ -35,6 +35,8 @@ namespace Time
public: public:
void Sleep(uint64_t Milliseconds); void Sleep(uint64_t Milliseconds);
uint64_t GetCounter();
uint64_t CalculateTarget(uint64_t Milliseconds);
time(void *acpi); time(void *acpi);
~time(); ~time();
}; };