From 36d82370c122b5a383684e29fe8d4a3e88edb419 Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Thu, 22 Jun 2023 02:17:50 -0700 Subject: [PATCH] [zion] Add a thread wait syscall --- lib/mammoth/include/mammoth/thread.h | 3 +++ lib/mammoth/src/thread.cpp | 4 +++- zion/include/zcall.h | 1 + zion/include/ztypes.h | 1 + zion/object/thread.cpp | 13 +++++++++++++ zion/object/thread.h | 4 ++++ zion/syscall/syscall.cpp | 1 + zion/syscall/thread.cpp | 17 +++++++++++++---- zion/syscall/thread.h | 9 ++++++--- 9 files changed, 45 insertions(+), 8 deletions(-) diff --git a/lib/mammoth/include/mammoth/thread.h b/lib/mammoth/include/mammoth/thread.h index 804db35..c3ac709 100644 --- a/lib/mammoth/include/mammoth/thread.h +++ b/lib/mammoth/include/mammoth/thread.h @@ -1,5 +1,6 @@ #pragma once +#include #include class Thread { @@ -9,6 +10,8 @@ class Thread { Thread() : thread_cap_(0) {} Thread(Entry e, const void* arg1); + [[nodiscard]] glcr::ErrorCode Join(); + private: uint64_t thread_cap_; }; diff --git a/lib/mammoth/src/thread.cpp b/lib/mammoth/src/thread.cpp index 4af95ff..333f5ea 100644 --- a/lib/mammoth/src/thread.cpp +++ b/lib/mammoth/src/thread.cpp @@ -10,7 +10,7 @@ namespace { extern "C" void thread_entry(Thread::Entry entry, void* arg1) { entry(arg1); - ZThreadExit(); + (void)ZThreadExit(); } } // namespace @@ -21,3 +21,5 @@ Thread::Thread(Entry e, const void* arg1) { reinterpret_cast(e), reinterpret_cast(arg1))); } + +glcr::ErrorCode Thread::Join() { return ZThreadWait(thread_cap_); } diff --git a/zion/include/zcall.h b/zion/include/zcall.h index fe56496..e3da8f1 100644 --- a/zion/include/zcall.h +++ b/zion/include/zcall.h @@ -96,6 +96,7 @@ SYS2(ThreadCreate, z_cap_t, proc_cap, z_cap_t*, thread_cap); SYS4(ThreadStart, z_cap_t, thread_cap, uint64_t, entry, uint64_t, arg1, uint64_t, arg2); SYS0(ThreadExit); +SYS1(ThreadWait, z_cap_t, thread_cap); SYS4(AddressSpaceMap, z_cap_t, vmas_cap, uint64_t, vmas_offset, z_cap_t, vmmo_cap, uint64_t*, vaddr); diff --git a/zion/include/ztypes.h b/zion/include/ztypes.h index c0a7482..a8268f3 100644 --- a/zion/include/ztypes.h +++ b/zion/include/ztypes.h @@ -17,6 +17,7 @@ const uint64_t kZionProcessSpawn = 0x2; const uint64_t kZionThreadCreate = 0x10; const uint64_t kZionThreadStart = 0x11; const uint64_t kZionThreadExit = 0x12; +const uint64_t kZionThreadWait = 0x13; // Memory Calls const uint64_t kZionAddressSpaceMap = 0x21; diff --git a/zion/object/thread.cpp b/zion/object/thread.cpp index c90e950..286d731 100644 --- a/zion/object/thread.cpp +++ b/zion/object/thread.cpp @@ -69,5 +69,18 @@ void Thread::Exit() { #endif state_ = FINISHED; process_.CheckState(); + while (!blocked_threads_.size() == 0) { + auto thread = blocked_threads_.PopFront(); + thread->SetState(Thread::RUNNABLE); + gScheduler->Enqueue(thread); + } + gScheduler->Yield(); +} + +void Thread::Wait() { + // FIXME: We need synchronization code here. + auto thread = gScheduler->CurrentThread(); + thread->SetState(Thread::BLOCKED); + blocked_threads_.PushBack(thread); gScheduler->Yield(); } diff --git a/zion/object/thread.h b/zion/object/thread.h index bd8c9c4..154098f 100644 --- a/zion/object/thread.h +++ b/zion/object/thread.h @@ -48,6 +48,8 @@ class Thread : public KernelObject, public glcr::IntrusiveListNode { void SetState(State state) { state_ = state; } void Exit(); + void Wait(); + private: friend class glcr::MakeRefCountedFriend; Thread(Process& proc, uint64_t tid); @@ -68,4 +70,6 @@ class Thread : public KernelObject, public glcr::IntrusiveListNode { // Stack pointer to take when returning from userspace. // I don't think me mind clobbering the stack here. uint64_t rsp0_start_; + + glcr::IntrusiveList blocked_threads_; }; diff --git a/zion/syscall/syscall.cpp b/zion/syscall/syscall.cpp index 99eaae3..cd6f59f 100644 --- a/zion/syscall/syscall.cpp +++ b/zion/syscall/syscall.cpp @@ -55,6 +55,7 @@ extern "C" z_err_t SyscallHandler(uint64_t call_id, void* req) { CASE(ThreadCreate); CASE(ThreadStart); CASE(ThreadExit); + CASE(ThreadWait); // syscall/address_space.h CASE(AddressSpaceMap); // syscall/memory_object.h diff --git a/zion/syscall/thread.cpp b/zion/syscall/thread.cpp index ca624c2..d10166c 100644 --- a/zion/syscall/thread.cpp +++ b/zion/syscall/thread.cpp @@ -3,18 +3,18 @@ #include "capability/capability.h" #include "scheduler/scheduler.h" -z_err_t ThreadCreate(ZThreadCreateReq* req) { +glcr::ErrorCode ThreadCreate(ZThreadCreateReq* req) { auto& curr_proc = gScheduler->CurrentProcess(); auto cap = curr_proc.GetCapability(req->proc_cap); RET_ERR(ValidateCapability(cap, ZC_PROC_SPAWN_THREAD)); auto parent_proc = cap->obj(); auto thread = parent_proc->CreateThread(); - *req->thread_cap = curr_proc.AddNewCapability(thread, ZC_WRITE); + *req->thread_cap = curr_proc.AddNewCapability(thread, ZC_WRITE | ZC_READ); return glcr::OK; } -z_err_t ThreadStart(ZThreadStartReq* req) { +glcr::ErrorCode ThreadStart(ZThreadStartReq* req) { auto& curr_proc = gScheduler->CurrentProcess(); auto cap = curr_proc.GetCapability(req->thread_cap); RET_ERR(ValidateCapability(cap, ZC_WRITE)); @@ -25,8 +25,17 @@ z_err_t ThreadStart(ZThreadStartReq* req) { return glcr::OK; } -z_err_t ThreadExit(ZThreadExitReq*) { +glcr::ErrorCode ThreadExit(ZThreadExitReq*) { auto curr_thread = gScheduler->CurrentThread(); curr_thread->Exit(); panic("Returned from thread exit"); } + +glcr::ErrorCode ThreadWait(ZThreadWaitReq* req) { + auto& curr_proc = gScheduler->CurrentProcess(); + auto cap = curr_proc.GetCapability(req->thread_cap); + RET_ERR(ValidateCapability(cap, ZC_READ)); + auto thread = cap->obj(); + thread->Wait(); + return glcr::OK; +} diff --git a/zion/syscall/thread.h b/zion/syscall/thread.h index 0d17180..17cc288 100644 --- a/zion/syscall/thread.h +++ b/zion/syscall/thread.h @@ -1,7 +1,10 @@ #pragma once +#include + #include "include/zcall.h" -z_err_t ThreadCreate(ZThreadCreateReq* req); -z_err_t ThreadStart(ZThreadStartReq* req); -z_err_t ThreadExit(ZThreadExitReq*); +glcr::ErrorCode ThreadCreate(ZThreadCreateReq* req); +glcr::ErrorCode ThreadStart(ZThreadStartReq* req); +glcr::ErrorCode ThreadExit(ZThreadExitReq*); +glcr::ErrorCode ThreadWait(ZThreadWaitReq* req);