From cb590c96b80bfbf1f2b15acb75ea5cd9b30b6503 Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Fri, 24 Nov 2023 15:04:03 -0800 Subject: [PATCH] [Zion] Add a proc/thread cleanup thread for future use. --- zion/CMakeLists.txt | 1 + zion/object/thread.cpp | 6 ++++++ zion/object/thread.h | 3 +++ zion/scheduler/cleanup.cpp | 32 ++++++++++++++++++++++++++++++ zion/scheduler/cleanup.h | 25 +++++++++++++++++++++++ zion/scheduler/process_manager.cpp | 18 +++++++++++++++++ zion/scheduler/process_manager.h | 7 +++++++ zion/syscall/process.cpp | 2 ++ zion/zion.cpp | 1 + 9 files changed, 95 insertions(+) create mode 100644 zion/scheduler/cleanup.cpp create mode 100644 zion/scheduler/cleanup.h diff --git a/zion/CMakeLists.txt b/zion/CMakeLists.txt index 575e5c5..9adc404 100644 --- a/zion/CMakeLists.txt +++ b/zion/CMakeLists.txt @@ -34,6 +34,7 @@ add_executable(zion object/reply_port.cpp object/semaphore.cpp object/thread.cpp + scheduler/cleanup.cpp scheduler/context_switch.s scheduler/jump_user_space.s scheduler/process_manager.cpp diff --git a/zion/object/thread.cpp b/zion/object/thread.cpp index 1adf607..0b69547 100644 --- a/zion/object/thread.cpp +++ b/zion/object/thread.cpp @@ -6,6 +6,7 @@ #include "memory/kernel_vmm.h" #include "memory/paging_util.h" #include "object/process.h" +#include "scheduler/process_manager.h" #include "scheduler/scheduler.h" #define K_THREAD_DEBUG 0 @@ -64,6 +65,10 @@ void Thread::Start(uint64_t entry, uint64_t arg1, uint64_t arg2) { } void Thread::Init() { + if (is_kernel_) { + ((void (*)(void*))rip_)(reinterpret_cast(arg1_)); + panic("Returned from kernel thread."); + } #if K_THREAD_DEBUG dbgln("Thread start.", pid(), id_); #endif @@ -86,6 +91,7 @@ void Thread::Exit() { panic("Thread::Exit called from [{}.{}] on [{}.{}]", curr_thread->pid(), curr_thread->tid(), pid(), tid()); } + gProcMan->CleanupThread(curr_thread); Cleanup(); process_.CheckState(); gScheduler->Yield(); diff --git a/zion/object/thread.h b/zion/object/thread.h index 1fae0b1..1d96b21 100644 --- a/zion/object/thread.h +++ b/zion/object/thread.h @@ -45,6 +45,8 @@ class Thread : public KernelObject, public glcr::IntrusiveListNode { uint8_t* FxData() { return fx_data_; } + void SetKernel() { is_kernel_ = true; } + // Switches the thread's state to runnable and enqueues it. void Start(uint64_t entry, uint64_t arg1, uint64_t arg2); @@ -75,6 +77,7 @@ class Thread : public KernelObject, public glcr::IntrusiveListNode { Process& process_; uint64_t id_; State state_ = CREATED; + bool is_kernel_ = false; // Startup Context for the thread. uint64_t rsp_; diff --git a/zion/scheduler/cleanup.cpp b/zion/scheduler/cleanup.cpp new file mode 100644 index 0000000..cc4f9fb --- /dev/null +++ b/zion/scheduler/cleanup.cpp @@ -0,0 +1,32 @@ +#include "scheduler/cleanup.h" + +void ProcessCleanup::CleanupLoop() { + while (true) { + while (process_list_.empty() && thread_list_.empty()) { + semaphore_.Wait(); + } + // TODO: I think we need to protect these lists with a mutex as well. + while (!process_list_.empty()) { + auto proc = process_list_.PopFront(); + dbgln("CLEANUP Proc {}", proc->id()); + } + while (!thread_list_.empty()) { + auto thread = thread_list_.PopFront(); + dbgln("CLEANUP Thread {}.{}", thread->pid(), thread->tid()); + } + } +} + +void ProcessCleanup::CleanupProcess(glcr::RefPtr process) { + process_list_.PushBack(process); + semaphore_.Signal(); +} +void ProcessCleanup::CleanupThread(glcr::RefPtr thread) { + thread_list_.PushBack(thread); + semaphore_.Signal(); +} + +void CleanupThreadEntry(ProcessCleanup* cleanup) { + cleanup->CleanupLoop(); + UNREACHABLE; +} diff --git a/zion/scheduler/cleanup.h b/zion/scheduler/cleanup.h new file mode 100644 index 0000000..0717c42 --- /dev/null +++ b/zion/scheduler/cleanup.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +#include "object/process.h" +#include "object/semaphore.h" +#include "object/thread.h" + +class ProcessCleanup { + public: + ProcessCleanup() {} + + void CleanupLoop(); + + void CleanupProcess(glcr::RefPtr process); + void CleanupThread(glcr::RefPtr thread); + + private: + Semaphore semaphore_; + glcr::LinkedList> thread_list_; + glcr::LinkedList> process_list_; +}; + +void CleanupThreadEntry(ProcessCleanup* cleanup); diff --git a/zion/scheduler/process_manager.cpp b/zion/scheduler/process_manager.cpp index 1390615..c4b4a59 100644 --- a/zion/scheduler/process_manager.cpp +++ b/zion/scheduler/process_manager.cpp @@ -19,3 +19,21 @@ Process& ProcessManager::FromId(uint64_t pid) { } return *proc_map_.at(pid); } + +void ProcessManager::InitCleanup() { + auto cleanup_thread = FromId(0).CreateThread(); + cleanup_thread->SetKernel(); + cleanup_thread->Start(reinterpret_cast(CleanupThreadEntry), + reinterpret_cast(&gProcMan->cleanup), 0); +} + +void ProcessManager::CleanupProcess(uint64_t pid) { + if (!proc_map_.Contains(pid)) { + panic("Bad proc access {}, have {} processes", pid, proc_map_.size()); + } + cleanup.CleanupProcess(proc_map_.at(pid)); +} + +void ProcessManager::CleanupThread(glcr::RefPtr thread) { + cleanup.CleanupThread(thread); +} diff --git a/zion/scheduler/process_manager.h b/zion/scheduler/process_manager.h index fad1f5e..159920a 100644 --- a/zion/scheduler/process_manager.h +++ b/zion/scheduler/process_manager.h @@ -4,6 +4,7 @@ #include #include "object/process.h" +#include "scheduler/cleanup.h" class ProcessManager { public: @@ -16,8 +17,14 @@ class ProcessManager { Process& FromId(uint64_t id); + void InitCleanup(); + + void CleanupProcess(uint64_t pid); + void CleanupThread(glcr::RefPtr thread); + private: glcr::HashMap> proc_map_; + ProcessCleanup cleanup; }; extern ProcessManager* gProcMan; diff --git a/zion/syscall/process.cpp b/zion/syscall/process.cpp index a8f5769..0d9926c 100644 --- a/zion/syscall/process.cpp +++ b/zion/syscall/process.cpp @@ -2,12 +2,14 @@ #include "capability/capability.h" #include "debug/debug.h" +#include "scheduler/cleanup.h" #include "scheduler/process_manager.h" #include "scheduler/scheduler.h" z_err_t ProcessExit(ZProcessExitReq* req) { auto curr_thread = gScheduler->CurrentThread(); dbgln("Exit code: {}", static_cast(req->code)); + gProcMan->CleanupProcess(curr_thread->pid()); curr_thread->process().Exit(); panic("Returned from thread exit"); return glcr::UNIMPLEMENTED; diff --git a/zion/zion.cpp b/zion/zion.cpp index c5e04e4..43aff22 100644 --- a/zion/zion.cpp +++ b/zion/zion.cpp @@ -53,6 +53,7 @@ extern "C" void zion() { dbgln("[boot] Init scheduler."); ProcessManager::Init(); Scheduler::Init(); + gProcMan->InitCleanup(); dbgln("[boot] Loading sys init program."); LoadInitProgram();