diff --git a/zion/capability/capability.cpp b/zion/capability/capability.cpp index 7b01243..71708fa 100644 --- a/zion/capability/capability.cpp +++ b/zion/capability/capability.cpp @@ -1,11 +1,14 @@ #include "capability/capability.h" +#include "scheduler/process.h" +#include "scheduler/thread.h" + template <> Process& Capability::obj() { if (type_ != PROCESS) { panic("Accessing %u cap as object.", type_); } - return *static_cast(obj_); + return *static_cast(obj_.get()); } template <> @@ -13,5 +16,5 @@ Thread& Capability::obj() { if (type_ != THREAD) { panic("Accessing %u cap as object.", type_); } - return *static_cast(obj_); + return *static_cast(obj_.get()); } diff --git a/zion/capability/capability.h b/zion/capability/capability.h index 871de8c..e2ad96d 100644 --- a/zion/capability/capability.h +++ b/zion/capability/capability.h @@ -2,7 +2,8 @@ #include -#include "debug/debug.h" +#include "lib/ref_ptr.h" +#include "object/kernel_object.h" class Process; class Thread; @@ -14,9 +15,15 @@ class Capability { PROCESS, THREAD, }; - Capability(void* obj, Type type, uint64_t id, uint64_t permissions) + Capability(const RefPtr& obj, Type type, uint64_t id, + uint64_t permissions) : obj_(obj), type_(type), id_(id), permissions_(permissions) {} + template + Capability(const RefPtr& obj, Type type, uint64_t id, uint64_t permissions) + : Capability(StaticCastRefPtr(obj), type, id, permissions) { + } + template T& obj(); @@ -30,8 +37,7 @@ class Capability { } private: - // FIXME: This should somehow be a shared ptr to keep the object alive. - void* obj_; + RefPtr obj_; Type type_; uint64_t id_; uint64_t permissions_; diff --git a/zion/lib/ref_ptr.h b/zion/lib/ref_ptr.h index a6cdf65..685d40a 100644 --- a/zion/lib/ref_ptr.h +++ b/zion/lib/ref_ptr.h @@ -6,6 +6,9 @@ class RefPtr; template RefPtr AdoptPtr(T* ptr); +template +RefPtr StaticCastRefPtr(const RefPtr& ref); + template class RefPtr { public: @@ -38,6 +41,11 @@ class RefPtr { return *this; } + enum DontAdoptTag { + DontAdopt, + }; + RefPtr(T* ptr, DontAdoptTag) : ptr_(ptr) { ptr->Acquire(); } + T* get() const { return ptr_; }; T& operator*() const { return *ptr_; } T* operator->() const { return ptr_; } @@ -74,3 +82,8 @@ template RefPtr AdoptPtr(T* ptr) { return RefPtr(ptr); } + +template +RefPtr StaticCastRefPtr(const RefPtr& ref) { + return RefPtr(static_cast(ref.get()), RefPtr::DontAdopt); +} diff --git a/zion/loader/init_loader.cpp b/zion/loader/init_loader.cpp index 149b6f7..80e0d98 100644 --- a/zion/loader/init_loader.cpp +++ b/zion/loader/init_loader.cpp @@ -50,7 +50,7 @@ void LoadInitProgram() { const limine_file& init_prog = GetInitProgram("/sys/test"); const limine_file& prog2 = GetInitProgram("/sys/test2"); - RefPtr proc = MakeRefCounted(); + RefPtr proc = Process::Create(); gProcMan->InsertProcess(proc); uint64_t entry = LoadElfProgram( diff --git a/zion/object/kernel_object.h b/zion/object/kernel_object.h new file mode 100644 index 0000000..97c6a7f --- /dev/null +++ b/zion/object/kernel_object.h @@ -0,0 +1,5 @@ +#pragma once + +#include "lib/ref_counted.h" + +class KernelObject : public RefCounted {}; diff --git a/zion/scheduler/process.cpp b/zion/scheduler/process.cpp index a612e3b..be4cd82 100644 --- a/zion/scheduler/process.cpp +++ b/zion/scheduler/process.cpp @@ -20,13 +20,16 @@ RefPtr Process::RootProcess() { return proc; } -RefPtr Process::Create() { return MakeRefCounted(); } - -Process::Process() : id_(gNextId++), state_(RUNNING) { - caps_.PushBack(new Capability(this, Capability::PROCESS, Z_INIT_PROC_SELF, - ZC_PROC_SPAWN_PROC | ZC_PROC_SPAWN_THREAD)); +RefPtr Process::Create() { + auto proc = MakeRefCounted(); + proc->caps_.PushBack( + new Capability(proc, Capability::PROCESS, Z_INIT_PROC_SELF, + ZC_PROC_SPAWN_PROC | ZC_PROC_SPAWN_THREAD)); + return proc; } +Process::Process() : id_(gNextId++), state_(RUNNING) {} + RefPtr Process::CreateThread() { RefPtr thread = MakeRefCounted(*this, next_thread_id_++); threads_.PushBack(thread); @@ -65,12 +68,12 @@ SharedPtr Process::GetCapability(uint64_t cid) { ++iter; } dbgln("Bad cap access"); + dbgln("Num caps: %u", caps_.size()); return {}; } -uint64_t Process::AddCapability(RefPtr& thread) { +uint64_t Process::AddCapability(const RefPtr& thread) { uint64_t cap_id = next_cap_id_++; - caps_.PushBack( - new Capability(thread.get(), Capability::THREAD, cap_id, ZC_WRITE)); + caps_.PushBack(new Capability(thread, Capability::THREAD, cap_id, ZC_WRITE)); return cap_id; } diff --git a/zion/scheduler/process.h b/zion/scheduler/process.h index 051a460..4cf23dd 100644 --- a/zion/scheduler/process.h +++ b/zion/scheduler/process.h @@ -4,7 +4,6 @@ #include "capability/capability.h" #include "lib/linked_list.h" -#include "lib/ref_counted.h" #include "lib/ref_ptr.h" #include "lib/shared_ptr.h" #include "memory/virtual_memory.h" @@ -12,7 +11,7 @@ // Forward decl due to cyclic dependency. class Thread; -class Process : public RefCounted { +class Process : public KernelObject { public: enum State { UNSPECIFIED, @@ -30,7 +29,7 @@ class Process : public RefCounted { RefPtr GetThread(uint64_t tid); SharedPtr GetCapability(uint64_t cid); - uint64_t AddCapability(RefPtr& t); + uint64_t AddCapability(const RefPtr& t); // Checks the state of all child threads and transitions to // finished if all have finished. void CheckState(); diff --git a/zion/scheduler/thread.h b/zion/scheduler/thread.h index b2897dc..fca48bc 100644 --- a/zion/scheduler/thread.h +++ b/zion/scheduler/thread.h @@ -2,13 +2,13 @@ #include -#include "lib/ref_counted.h" #include "lib/ref_ptr.h" +#include "object/kernel_object.h" // Forward decl due to cyclic dependency. class Process; -class Thread : public RefCounted { +class Thread : public KernelObject { public: enum State { UNSPECIFIED, diff --git a/zion/syscall/syscall.cpp b/zion/syscall/syscall.cpp index 084d9e2..4702f1a 100644 --- a/zion/syscall/syscall.cpp +++ b/zion/syscall/syscall.cpp @@ -71,7 +71,7 @@ uint64_t ProcessSpawnElf(ZProcessSpawnElfReq* req) { return ZE_DENIED; } dbgln("Proc spawn: %u:%u", req->elf_base, req->elf_size); - RefPtr proc = MakeRefCounted(); + RefPtr proc = Process::Create(); gProcMan->InsertProcess(proc); uint64_t entry = LoadElfProgram(*proc, req->elf_base, req->elf_size); proc->CreateThread()->Start(entry, 0, 0);