From 960cbf95199ca6b5d1a789dd4e1672b3d16b8910 Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Thu, 18 May 2023 12:43:53 -0700 Subject: [PATCH] Add Scheduler wireframe. Right now does nothing but has containing classes for process and thread information. --- zion/CMakeLists.txt | 3 ++ zion/scheduler/process.cpp | 34 +++++++++++++++ zion/scheduler/process.h | 32 ++++++++++++++ zion/scheduler/scheduler.cpp | 84 ++++++++++++++++++++++++++++++++++++ zion/scheduler/scheduler.h | 24 +++++++++++ zion/scheduler/thread.cpp | 5 +++ zion/scheduler/thread.h | 23 ++++++++++ zion/zion.cpp | 4 +- 8 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 zion/scheduler/process.cpp create mode 100644 zion/scheduler/process.h create mode 100644 zion/scheduler/scheduler.cpp create mode 100644 zion/scheduler/scheduler.h create mode 100644 zion/scheduler/thread.cpp create mode 100644 zion/scheduler/thread.h diff --git a/zion/CMakeLists.txt b/zion/CMakeLists.txt index 5bd066e..d7f6d08 100644 --- a/zion/CMakeLists.txt +++ b/zion/CMakeLists.txt @@ -8,6 +8,9 @@ add_executable(zion memory/kernel_heap.cpp memory/paging_util.cpp memory/physical_memory.cpp + scheduler/process.cpp + scheduler/scheduler.cpp + scheduler/thread.cpp zion.cpp) target_include_directories(zion diff --git a/zion/scheduler/process.cpp b/zion/scheduler/process.cpp new file mode 100644 index 0000000..12d7d38 --- /dev/null +++ b/zion/scheduler/process.cpp @@ -0,0 +1,34 @@ +#include "scheduler/process.h" + +#include "debug/debug.h" +#include "scheduler/thread.h" + +namespace { + +static uint64_t gNextId = 1; + +} + +Process* Process::RootProcess() { + uint64_t pml4_addr = 0; + asm volatile("mov %%cr3, %0;" : "=r"(pml4_addr)); + Process* proc = new Process(0, pml4_addr); + proc->thread_list_front_ = new ThreadEntry{ + .thread = new Thread(proc, 0), + .next = nullptr, + }; + proc->next_thread_id_ = 1; + + return proc; +} + +Thread* Process::GetThread(uint64_t tid) { + ThreadEntry* entry = thread_list_front_; + while (entry != nullptr) { + if (entry->thread->tid() == tid) { + return entry->thread; + } + } + panic("Bad thread access."); + return nullptr; +} diff --git a/zion/scheduler/process.h b/zion/scheduler/process.h new file mode 100644 index 0000000..fb17e18 --- /dev/null +++ b/zion/scheduler/process.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +// Forward decl due to cyclic dependency. +class Thread; + +class Process { + public: + // Caller takes ownership of returned process. + static Process* RootProcess(); + Process(); + + uint64_t id() { return id_; } + + Thread* CreateThread(); + Thread* GetThread(uint64_t tid); + + private: + Process(uint64_t id, uint64_t cr3) : id_(id), cr3_(cr3) {} + uint64_t id_; + uint64_t cr3_; + + uint64_t next_thread_id_ = 0; + + // FIXME: Make a better data structure for this. + struct ThreadEntry { + Thread* thread; + ThreadEntry* next; + }; + ThreadEntry* thread_list_front_; +}; diff --git a/zion/scheduler/scheduler.cpp b/zion/scheduler/scheduler.cpp new file mode 100644 index 0000000..fcd41c9 --- /dev/null +++ b/zion/scheduler/scheduler.cpp @@ -0,0 +1,84 @@ +#include "scheduler/scheduler.h" + +#include "debug/debug.h" + +namespace sched { +namespace { + +// Simple linked list class with the intent of eventually replacing this with a +// map. +class ProcList { + public: + ProcList() {} + + // Takes ownership. + void InsertProcess(Process* proc) { + if (front_ == nullptr) { + front_ = new ProcEntry{ + .proc = proc, + .next = nullptr, + }; + return; + } + + ProcEntry* back = front_; + while (back->next != nullptr) { + back = back->next; + } + + back->next = new ProcEntry{ + .proc = proc, + .next = nullptr, + }; + } + + private: + struct ProcEntry { + Process* proc; + ProcEntry* next; + }; + + ProcEntry* front_ = nullptr; +}; + +class Scheduler { + public: + Scheduler() { + Process* root = Process::RootProcess(); + current_thread_ = root->GetThread(0); + proc_list_.InsertProcess(Process::RootProcess()); + } + void Enable() { enabled_ = true; } + + Process& CurrentProcess() { return current_thread_->process(); } + Thread& CurrentThread() { return *current_thread_; } + + void Yield() {} + + private: + bool enabled_ = false; + ProcList proc_list_; + + Thread* current_thread_; +}; + +static Scheduler* gScheduler = nullptr; + +Scheduler& GetScheduler() { + if (!gScheduler) { + panic("Scheduler not initialized"); + } + return *gScheduler; +} + +} // namespace + +void InitScheduler() { gScheduler = new Scheduler(); } +void EnableScheduler() { GetScheduler().Enable(); } + +void Yield() { GetScheduler().Yield(); } + +Process& CurrentProcess() { return GetScheduler().CurrentProcess(); } +Thread& CurrentThread() { return GetScheduler().CurrentThread(); } + +} // namespace sched diff --git a/zion/scheduler/scheduler.h b/zion/scheduler/scheduler.h new file mode 100644 index 0000000..efa0b52 --- /dev/null +++ b/zion/scheduler/scheduler.h @@ -0,0 +1,24 @@ +#pragma once + +#include "scheduler/process.h" +#include "scheduler/thread.h" + +namespace sched { + +// Create the scheduler object in a disabled state, +// processes can be added but will not be scheduled. +void InitScheduler(); + +// Enables the scheduler such that processes will yield on ticks. +void EnableScheduler(); + +void Yield(); + +// Scheduler will take ownership +// of the created process. +void InsertProcess(Process* proc); + +Process& CurrentProcess(); +Thread& CurrentThread(); + +} // namespace sched diff --git a/zion/scheduler/thread.cpp b/zion/scheduler/thread.cpp new file mode 100644 index 0000000..1549b55 --- /dev/null +++ b/zion/scheduler/thread.cpp @@ -0,0 +1,5 @@ +#include "scheduler/thread.h" + +#include "scheduler/process.h" + +uint64_t Thread::pid() { return process_->id(); } diff --git a/zion/scheduler/thread.h b/zion/scheduler/thread.h new file mode 100644 index 0000000..335ae67 --- /dev/null +++ b/zion/scheduler/thread.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +// Forward decl due to cyclic dependency. +class Process; + +class Thread { + public: + Thread(Process* proc, uint64_t thread_id) : process_(proc), id_(thread_id) {} + + uint64_t tid() { return id_; }; + uint64_t pid(); + + Process& process() { return *process_; } + + private: + Process* process_; + uint64_t id_; + + // Next task in queue for quick scheduling. + Thread* next_task_; +}; diff --git a/zion/zion.cpp b/zion/zion.cpp index 4313af0..33972f0 100644 --- a/zion/zion.cpp +++ b/zion/zion.cpp @@ -6,6 +6,7 @@ #include "memory/kernel_heap.h" #include "memory/paging_util.h" #include "memory/physical_memory.h" +#include "scheduler/scheduler.h" extern "C" void zion() { InitGdt(); @@ -15,7 +16,8 @@ extern "C" void zion() { phys_mem::InitBootstrapPageAllocation(); KernelHeap heap(0xFFFFFFFF'40000000, 0xFFFFFFFF'80000000); phys_mem::InitPhysicalMemoryManager(); - heap.Allocate(0x2000); + + sched::InitScheduler(); dbgln("Sleeping!"); while (1)