diff --git a/Core/Timer.cpp b/Core/Timer.cpp index 3c46bff..0d91b6e 100644 --- a/Core/Timer.cpp +++ b/Core/Timer.cpp @@ -15,7 +15,7 @@ namespace Time void time::Sleep(uint64_t Milliseconds) { #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 uint64_t Counter = mminq(&((HPET *)hpet)->MainCounterValue); while (Counter < Target) @@ -31,6 +31,22 @@ namespace Time #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) { if (_acpi) diff --git a/Tasking/Task.cpp b/Tasking/Task.cpp index 89caf08..1d1c5ed 100644 --- a/Tasking/Task.cpp +++ b/Tasking/Task.cpp @@ -349,6 +349,47 @@ namespace Tasking 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) { SmartCriticalSection(SchedulerLock); @@ -409,6 +450,9 @@ namespace Tasking if (CurrentCPU->CurrentThread->Status == TaskStatus::Running) CurrentCPU->CurrentThread->Status = TaskStatus::Ready; + // Loop through all threads and find which one is ready. + WakeUpThreads(CurrentCPU); + // Get next available thread from the list. if (this->GetNextAvailableThread(CurrentCPU)) goto Success; @@ -690,6 +734,15 @@ namespace Tasking 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, IP EntryPoint, const char **argv, diff --git a/include/task.hpp b/include/task.hpp index af1510c..b9e7893 100644 --- a/include/task.hpp +++ b/include/task.hpp @@ -68,6 +68,7 @@ namespace Tasking struct TaskInfo { + uint64_t SleepUntil = 0; uint64_t SpawnTime = 0; uint64_t OldUserTime = 0, CurrentUserTime = 0; uint64_t OldKernelTime = 0, CurrentKernelTime = 0; @@ -216,6 +217,7 @@ namespace Tasking bool GetNextAvailableProcess(void *CPUDataPointer); void SchedulerCleanupProcesses(); bool SchedulerSearchProcessThread(void *CPUDataPointer); + void WakeUpThreads(void *CPUDataPointer); #if defined(__amd64__) void Schedule(CPU::x64::TrapFrame *Frame); @@ -276,6 +278,13 @@ namespace Tasking /** @brief Wait for thread to terminate */ 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, const char *Name, TaskTrustLevel TrustLevel, void *Image = nullptr); diff --git a/include/time.hpp b/include/time.hpp index 19aa907..8356746 100644 --- a/include/time.hpp +++ b/include/time.hpp @@ -35,6 +35,8 @@ namespace Time public: void Sleep(uint64_t Milliseconds); + uint64_t GetCounter(); + uint64_t CalculateTarget(uint64_t Milliseconds); time(void *acpi); ~time(); };