[Zion] Add a proc/thread cleanup thread for future use.

This commit is contained in:
Drew Galbraith 2023-11-24 15:04:03 -08:00
parent 8e4cd1562f
commit cb590c96b8
9 changed files with 95 additions and 0 deletions

View File

@ -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

View File

@ -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<void*>(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();

View File

@ -45,6 +45,8 @@ class Thread : public KernelObject, public glcr::IntrusiveListNode<Thread> {
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<Thread> {
Process& process_;
uint64_t id_;
State state_ = CREATED;
bool is_kernel_ = false;
// Startup Context for the thread.
uint64_t rsp_;

View File

@ -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) {
process_list_.PushBack(process);
semaphore_.Signal();
}
void ProcessCleanup::CleanupThread(glcr::RefPtr<Thread> thread) {
thread_list_.PushBack(thread);
semaphore_.Signal();
}
void CleanupThreadEntry(ProcessCleanup* cleanup) {
cleanup->CleanupLoop();
UNREACHABLE;
}

25
zion/scheduler/cleanup.h Normal file
View File

@ -0,0 +1,25 @@
#pragma once
#include <glacier/container/linked_list.h>
#include <glacier/memory/ref_ptr.h>
#include "object/process.h"
#include "object/semaphore.h"
#include "object/thread.h"
class ProcessCleanup {
public:
ProcessCleanup() {}
void CleanupLoop();
void CleanupProcess(glcr::RefPtr<Process> process);
void CleanupThread(glcr::RefPtr<Thread> thread);
private:
Semaphore semaphore_;
glcr::LinkedList<glcr::RefPtr<Thread>> thread_list_;
glcr::LinkedList<glcr::RefPtr<Process>> process_list_;
};
void CleanupThreadEntry(ProcessCleanup* cleanup);

View File

@ -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<uint64_t>(CleanupThreadEntry),
reinterpret_cast<uint64_t>(&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> thread) {
cleanup.CleanupThread(thread);
}

View File

@ -4,6 +4,7 @@
#include <glacier/memory/ref_ptr.h>
#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> thread);
private:
glcr::HashMap<uint64_t, glcr::RefPtr<Process>> proc_map_;
ProcessCleanup cleanup;
};
extern ProcessManager* gProcMan;

View File

@ -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<glcr::ErrorCode>(req->code));
gProcMan->CleanupProcess(curr_thread->pid());
curr_thread->process().Exit();
panic("Returned from thread exit");
return glcr::UNIMPLEMENTED;

View File

@ -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();