[Zion] Add a proc/thread cleanup thread for future use.
This commit is contained in:
parent
8e4cd1562f
commit
cb590c96b8
|
@ -34,6 +34,7 @@ add_executable(zion
|
||||||
object/reply_port.cpp
|
object/reply_port.cpp
|
||||||
object/semaphore.cpp
|
object/semaphore.cpp
|
||||||
object/thread.cpp
|
object/thread.cpp
|
||||||
|
scheduler/cleanup.cpp
|
||||||
scheduler/context_switch.s
|
scheduler/context_switch.s
|
||||||
scheduler/jump_user_space.s
|
scheduler/jump_user_space.s
|
||||||
scheduler/process_manager.cpp
|
scheduler/process_manager.cpp
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "memory/kernel_vmm.h"
|
#include "memory/kernel_vmm.h"
|
||||||
#include "memory/paging_util.h"
|
#include "memory/paging_util.h"
|
||||||
#include "object/process.h"
|
#include "object/process.h"
|
||||||
|
#include "scheduler/process_manager.h"
|
||||||
#include "scheduler/scheduler.h"
|
#include "scheduler/scheduler.h"
|
||||||
|
|
||||||
#define K_THREAD_DEBUG 0
|
#define K_THREAD_DEBUG 0
|
||||||
|
@ -64,6 +65,10 @@ void Thread::Start(uint64_t entry, uint64_t arg1, uint64_t arg2) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Thread::Init() {
|
void Thread::Init() {
|
||||||
|
if (is_kernel_) {
|
||||||
|
((void (*)(void*))rip_)(reinterpret_cast<void*>(arg1_));
|
||||||
|
panic("Returned from kernel thread.");
|
||||||
|
}
|
||||||
#if K_THREAD_DEBUG
|
#if K_THREAD_DEBUG
|
||||||
dbgln("Thread start.", pid(), id_);
|
dbgln("Thread start.", pid(), id_);
|
||||||
#endif
|
#endif
|
||||||
|
@ -86,6 +91,7 @@ void Thread::Exit() {
|
||||||
panic("Thread::Exit called from [{}.{}] on [{}.{}]", curr_thread->pid(),
|
panic("Thread::Exit called from [{}.{}] on [{}.{}]", curr_thread->pid(),
|
||||||
curr_thread->tid(), pid(), tid());
|
curr_thread->tid(), pid(), tid());
|
||||||
}
|
}
|
||||||
|
gProcMan->CleanupThread(curr_thread);
|
||||||
Cleanup();
|
Cleanup();
|
||||||
process_.CheckState();
|
process_.CheckState();
|
||||||
gScheduler->Yield();
|
gScheduler->Yield();
|
||||||
|
|
|
@ -45,6 +45,8 @@ class Thread : public KernelObject, public glcr::IntrusiveListNode<Thread> {
|
||||||
|
|
||||||
uint8_t* FxData() { return fx_data_; }
|
uint8_t* FxData() { return fx_data_; }
|
||||||
|
|
||||||
|
void SetKernel() { is_kernel_ = true; }
|
||||||
|
|
||||||
// Switches the thread's state to runnable and enqueues it.
|
// Switches the thread's state to runnable and enqueues it.
|
||||||
void Start(uint64_t entry, uint64_t arg1, uint64_t arg2);
|
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_;
|
Process& process_;
|
||||||
uint64_t id_;
|
uint64_t id_;
|
||||||
State state_ = CREATED;
|
State state_ = CREATED;
|
||||||
|
bool is_kernel_ = false;
|
||||||
|
|
||||||
// Startup Context for the thread.
|
// Startup Context for the thread.
|
||||||
uint64_t rsp_;
|
uint64_t rsp_;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
|
@ -19,3 +19,21 @@ Process& ProcessManager::FromId(uint64_t pid) {
|
||||||
}
|
}
|
||||||
return *proc_map_.at(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);
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <glacier/memory/ref_ptr.h>
|
#include <glacier/memory/ref_ptr.h>
|
||||||
|
|
||||||
#include "object/process.h"
|
#include "object/process.h"
|
||||||
|
#include "scheduler/cleanup.h"
|
||||||
|
|
||||||
class ProcessManager {
|
class ProcessManager {
|
||||||
public:
|
public:
|
||||||
|
@ -16,8 +17,14 @@ class ProcessManager {
|
||||||
|
|
||||||
Process& FromId(uint64_t id);
|
Process& FromId(uint64_t id);
|
||||||
|
|
||||||
|
void InitCleanup();
|
||||||
|
|
||||||
|
void CleanupProcess(uint64_t pid);
|
||||||
|
void CleanupThread(glcr::RefPtr<Thread> thread);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
glcr::HashMap<uint64_t, glcr::RefPtr<Process>> proc_map_;
|
glcr::HashMap<uint64_t, glcr::RefPtr<Process>> proc_map_;
|
||||||
|
ProcessCleanup cleanup;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ProcessManager* gProcMan;
|
extern ProcessManager* gProcMan;
|
||||||
|
|
|
@ -2,12 +2,14 @@
|
||||||
|
|
||||||
#include "capability/capability.h"
|
#include "capability/capability.h"
|
||||||
#include "debug/debug.h"
|
#include "debug/debug.h"
|
||||||
|
#include "scheduler/cleanup.h"
|
||||||
#include "scheduler/process_manager.h"
|
#include "scheduler/process_manager.h"
|
||||||
#include "scheduler/scheduler.h"
|
#include "scheduler/scheduler.h"
|
||||||
|
|
||||||
z_err_t ProcessExit(ZProcessExitReq* req) {
|
z_err_t ProcessExit(ZProcessExitReq* req) {
|
||||||
auto curr_thread = gScheduler->CurrentThread();
|
auto curr_thread = gScheduler->CurrentThread();
|
||||||
dbgln("Exit code: {}", static_cast<glcr::ErrorCode>(req->code));
|
dbgln("Exit code: {}", static_cast<glcr::ErrorCode>(req->code));
|
||||||
|
gProcMan->CleanupProcess(curr_thread->pid());
|
||||||
curr_thread->process().Exit();
|
curr_thread->process().Exit();
|
||||||
panic("Returned from thread exit");
|
panic("Returned from thread exit");
|
||||||
return glcr::UNIMPLEMENTED;
|
return glcr::UNIMPLEMENTED;
|
||||||
|
|
|
@ -53,6 +53,7 @@ extern "C" void zion() {
|
||||||
dbgln("[boot] Init scheduler.");
|
dbgln("[boot] Init scheduler.");
|
||||||
ProcessManager::Init();
|
ProcessManager::Init();
|
||||||
Scheduler::Init();
|
Scheduler::Init();
|
||||||
|
gProcMan->InitCleanup();
|
||||||
|
|
||||||
dbgln("[boot] Loading sys init program.");
|
dbgln("[boot] Loading sys init program.");
|
||||||
LoadInitProgram();
|
LoadInitProgram();
|
||||||
|
|
Loading…
Reference in New Issue