diff --git a/zion/CMakeLists.txt b/zion/CMakeLists.txt index b4bc251..75ae166 100644 --- a/zion/CMakeLists.txt +++ b/zion/CMakeLists.txt @@ -14,6 +14,7 @@ add_executable(zion scheduler/context_switch.s scheduler/jump_user_space.s scheduler/process.cpp + scheduler/process_manager.cpp scheduler/scheduler.cpp scheduler/thread.cpp syscall/syscall.cpp diff --git a/zion/loader/init_loader.cpp b/zion/loader/init_loader.cpp index d183bd6..a10da9c 100644 --- a/zion/loader/init_loader.cpp +++ b/zion/loader/init_loader.cpp @@ -4,7 +4,7 @@ #include "debug/debug.h" #include "loader/elf_loader.h" #include "scheduler/process.h" -#include "scheduler/scheduler.h" +#include "scheduler/process_manager.h" namespace { @@ -25,6 +25,6 @@ const limine_file& GetInitProgram() { void LoadInitProgram() { const limine_file& init_prog = GetInitProgram(); - sched::InsertProcess( + gProcMan->InsertProcess( new Process(reinterpret_cast(init_prog.address))); } diff --git a/zion/scheduler/process_manager.cpp b/zion/scheduler/process_manager.cpp new file mode 100644 index 0000000..bb00763 --- /dev/null +++ b/zion/scheduler/process_manager.cpp @@ -0,0 +1,34 @@ +#include "scheduler/process_manager.h" + +ProcessManager* gProcMan = nullptr; + +void ProcessManager::Init() { + gProcMan = new ProcessManager(); + gProcMan->InsertProcess(Process::RootProcess()); +} + +void ProcessManager::InsertProcess(const SharedPtr& proc) { + proc_list_.PushBack(proc); +} + +Process& ProcessManager::FromId(uint64_t pid) { + auto iter = proc_list_.begin(); + while (iter != proc_list_.end()) { + if (iter->id() == pid) { + return **iter; + } + ++iter; + } + + panic("Searching for invalid process id"); + return *((Process*)0); +} + +void ProcessManager::DumpProcessStates() { + dbgln("Process States: %u", proc_list_.size()); + auto iter = proc_list_.begin(); + while (iter != proc_list_.end()) { + dbgln("%u: %u", iter->id(), iter->GetState()); + ++iter; + } +} diff --git a/zion/scheduler/process_manager.h b/zion/scheduler/process_manager.h new file mode 100644 index 0000000..ea92436 --- /dev/null +++ b/zion/scheduler/process_manager.h @@ -0,0 +1,23 @@ +#pragma once + +#include "lib/linked_list.h" +#include "lib/shared_ptr.h" +#include "scheduler/process.h" + +class ProcessManager { + public: + // Initializes the ProcessManager + // and stores it in the global variable. + static void Init(); + + void InsertProcess(const SharedPtr& proc); + Process& FromId(uint64_t id); + + void DumpProcessStates(); + + private: + // TODO: This should be a hashmap. + LinkedList> proc_list_; +}; + +extern ProcessManager* gProcMan; diff --git a/zion/scheduler/scheduler.cpp b/zion/scheduler/scheduler.cpp index 78bd686..007f61b 100644 --- a/zion/scheduler/scheduler.cpp +++ b/zion/scheduler/scheduler.cpp @@ -2,36 +2,26 @@ #include "debug/debug.h" #include "lib/linked_list.h" +#include "scheduler/process_manager.h" namespace sched { namespace { extern "C" void context_switch(uint64_t* current_esp, uint64_t* next_esp); -void DumpProcessStates(LinkedList>& proc_list) { - dbgln("Process States: %u", proc_list.size()); - auto iter = proc_list.begin(); - while (iter != proc_list.end()) { - dbgln("%u: %u", iter->id(), iter->GetState()); - ++iter; - } -} - class Scheduler { public: Scheduler() { - SharedPtr root = Process::RootProcess(); - sleep_thread_ = root->GetThread(0); + Process& root = gProcMan->FromId(0); + sleep_thread_ = root.GetThread(0); // TODO: Implement a separate sleep thread? current_thread_ = sleep_thread_; - proc_list_.PushBack(root); } void Enable() { enabled_ = true; } Process& CurrentProcess() { return CurrentThread().process(); } Thread& CurrentThread() { return *current_thread_; } - void InsertProcess(Process* process) { proc_list_.PushBack(process); } void Enqueue(Thread* thread) { runnable_threads_.PushBack(thread); } void SwapToCurrent(Thread& prev) { @@ -90,7 +80,7 @@ class Scheduler { if (runnable_threads_.size() == 0) { current_thread_ = sleep_thread_; dbgln("Sleeping"); - DumpProcessStates(proc_list_); + gProcMan->DumpProcessStates(); } else { // FIXME: Memory operation. current_thread_ = runnable_threads_.PopFront(); @@ -102,8 +92,6 @@ class Scheduler { private: bool enabled_ = false; - // TODO: move this to a separate process manager class. - LinkedList> proc_list_; SharedPtr current_thread_; LinkedList> runnable_threads_; @@ -128,7 +116,6 @@ void EnableScheduler() { GetScheduler().Enable(); } void Preempt() { GetScheduler().Preempt(); } void Yield() { GetScheduler().Yield(); } -void InsertProcess(Process* process) { GetScheduler().InsertProcess(process); } void EnqueueThread(Thread* thread) { GetScheduler().Enqueue(thread); } Process& CurrentProcess() { return GetScheduler().CurrentProcess(); } diff --git a/zion/scheduler/scheduler.h b/zion/scheduler/scheduler.h index 550af20..7253739 100644 --- a/zion/scheduler/scheduler.h +++ b/zion/scheduler/scheduler.h @@ -21,10 +21,6 @@ void Preempt(); // Used when a thread blocks or exits. void Yield(); -// Scheduler will take ownership -// of the created process. -void InsertProcess(Process* proc); - void EnqueueThread(Thread* thread); Process& CurrentProcess(); diff --git a/zion/zion.cpp b/zion/zion.cpp index 1b1b4af..a37b529 100644 --- a/zion/zion.cpp +++ b/zion/zion.cpp @@ -8,6 +8,7 @@ #include "memory/kernel_heap.h" #include "memory/paging_util.h" #include "memory/physical_memory.h" +#include "scheduler/process_manager.h" #include "scheduler/scheduler.h" #include "syscall/syscall.h" @@ -28,6 +29,7 @@ extern "C" void zion() { InitSyscall(); dbgln("[boot] Init scheduler."); + ProcessManager::Init(); // Schedule every 50ms. SetFrequency(/* hertz= */ 20); sched::InitScheduler();