[kernel] Remove process & thread self-handles

For the coming switch to cap/handle ref-counting being the main lifetime
determiner of objects, get rid of self handles for threads and processes
to avoid circular references. Instead, passing 0 to syscalls expecting a
thread or process handle signifies "this process/thread".
This commit is contained in:
Justin C. Miller
2023-02-19 11:23:23 -08:00
parent d2a6113fb7
commit 94b2a79f79
13 changed files with 45 additions and 63 deletions

View File

@@ -7,7 +7,7 @@ object thread : object {
] ]
method create [constructor] { method create [constructor] {
param process ref process [cap:create_thread] param process ref process [optional cap:create_thread]
param stack_top address param stack_top address
param entrypoint address param entrypoint address
param arg0 uint64 param arg0 uint64

View File

@@ -22,12 +22,12 @@ object vma : object {
} }
method map [cap:map] { method map [cap:map] {
param process ref process param process ref process [optional]
param address address param address address
} }
method unmap [cap:unmap] { method unmap [cap:unmap] {
param process ref process param process ref process [optional]
} }
method resize [cap:resize] { method resize [cap:resize] {

View File

@@ -24,8 +24,6 @@ process::process() :
kobject {kobject::type::process}, kobject {kobject::type::process},
m_state {state::running} m_state {state::running}
{ {
m_self_handle = g_cap_table.create(this, process::self_caps);
add_handle(m_self_handle);
} }
// The "kernel process"-only constructor // The "kernel process"-only constructor
@@ -71,28 +69,6 @@ process::exit(int32_t code)
current.exit(); current.exit();
} }
void
process::update()
{
util::scoped_lock lock {m_threads_lock};
kassert(false, "process::update used!");
kassert(m_threads.count() > 0, "process::update with zero threads!");
size_t i = 0;
while (i < m_threads.count()) {
thread *th = m_threads[i];
if (th->has_state(thread::state::exited)) {
m_threads.remove_swap_at(i);
continue;
}
i++;
}
if (m_threads.count() == 0)
exit(-1);
}
thread * thread *
process::create_thread(uintptr_t rsp3, uint8_t priority) process::create_thread(uintptr_t rsp3, uint8_t priority)
{ {

View File

@@ -20,9 +20,6 @@ public:
/// Capabilities on a newly constructed process handle /// Capabilities on a newly constructed process handle
static constexpr j6_cap_t creation_caps = j6_cap_process_all; static constexpr j6_cap_t creation_caps = j6_cap_process_all;
/// Capabilities on a process to itself
static constexpr j6_cap_t self_caps = j6_cap_process_all;
/// Top of memory area where thread stacks are allocated /// Top of memory area where thread stacks are allocated
static constexpr uintptr_t stacks_top = 0x0000800000000000; static constexpr uintptr_t stacks_top = 0x0000800000000000;
@@ -47,9 +44,6 @@ public:
/// \arg code The return code to exit with. /// \arg code The return code to exit with.
void exit(int32_t code); void exit(int32_t code);
/// Update internal bookkeeping about threads.
void update();
/// Get the process' virtual memory space /// Get the process' virtual memory space
vm_space & space() { return m_space; } vm_space & space() { return m_space; }
@@ -105,7 +99,6 @@ private:
// This constructor is called by create_kernel_process // This constructor is called by create_kernel_process
process(page_table *kpml4); process(page_table *kpml4);
j6_handle_t m_self_handle;
int32_t m_return_code; int32_t m_return_code;
vm_space m_space; vm_space m_space;

View File

@@ -32,8 +32,6 @@ thread::thread(process &parent, uint8_t pri, uintptr_t rsp0) :
m_tcb.rsp0 = rsp0; m_tcb.rsp0 = rsp0;
m_creator = current_cpu().thread; m_creator = current_cpu().thread;
m_self_handle = g_cap_table.create(this, thread::parent_caps);
parent.add_handle(m_self_handle);
} }
thread::~thread() thread::~thread()

View File

@@ -57,9 +57,6 @@ public:
/// Capabilities on a newly constructed thread handle /// Capabilities on a newly constructed thread handle
static constexpr j6_cap_t creation_caps = j6_cap_thread_all; static constexpr j6_cap_t creation_caps = j6_cap_thread_all;
/// Capabilities the parent process gets on new thread handles
static constexpr j6_cap_t parent_caps = j6_cap_thread_all;
static constexpr kobject::type type = kobject::type::thread; static constexpr kobject::type type = kobject::type::thread;
enum class state : uint8_t { enum class state : uint8_t {
@@ -168,9 +165,6 @@ public:
uintptr_t rip0 = 0, uintptr_t rip0 = 0,
uint64_t flags = 0); uint64_t flags = 0);
/// Get the handle representing this thread to its process
j6_handle_t self_handle() const { return m_self_handle; }
/// Create the kernel idle thread /// Create the kernel idle thread
/// \arg kernel The process object that owns kernel tasks /// \arg kernel The process object that owns kernel tasks
/// \arg rsp The existing stack for the idle thread /// \arg rsp The existing stack for the idle thread
@@ -208,7 +202,6 @@ private:
message_data m_message_data; message_data m_message_data;
wait_queue m_join_queue; wait_queue m_join_queue;
j6_handle_t m_self_handle;
}; };
} // namespace obj } // namespace obj

View File

@@ -133,7 +133,7 @@ for id, scope, method in syscalls.methods:
param.type.object.cname, param.type.object.cname,
arg, arg,
get_caps(param.options, param.type.object), get_caps(param.options, param.type.object),
param.optional)) param.optional != "required"))
if needs_obj: if needs_obj:
objparams.append((type, arg)) objparams.append((type, arg))
@@ -149,7 +149,7 @@ for id, scope, method in syscalls.methods:
f"obj::{param.type.object.cname}", f"obj::{param.type.object.cname}",
arg, arg,
get_caps(param.options, param.type.object, get_caps(param.options, param.type.object,
param.optional))) param.optional != "required")))
if param.refparam: if param.refparam:
subs = param.type.c_names(param.options) subs = param.type.c_names(param.options)

View File

@@ -17,9 +17,14 @@ thread_create(j6_handle_t *self, process *proc, uintptr_t stack_top, uintptr_t e
thread &parent_th = thread::current(); thread &parent_th = thread::current();
process &parent_pr = parent_th.parent(); process &parent_pr = parent_th.parent();
if (!proc)
proc = &parent_pr;
thread *child = proc->create_thread(stack_top); thread *child = proc->create_thread(stack_top);
child->add_thunk_user(entrypoint, arg0, arg1); child->add_thunk_user(entrypoint, arg0, arg1);
*self = child->self_handle();
*self = g_cap_table.create(child, thread::creation_caps);
child->set_state(thread::state::ready); child->set_state(thread::state::ready);
log::verbose(logs::task, "Thread <%02lx:%02lx> spawned new thread <%02lx:%02lx>", log::verbose(logs::task, "Thread <%02lx:%02lx> spawned new thread <%02lx:%02lx>",

View File

@@ -31,14 +31,16 @@ vma_create_map(j6_handle_t *self, size_t size, uintptr_t base, uint32_t flags)
j6_status_t j6_status_t
vma_map(vm_area *self, process *proc, uintptr_t base) vma_map(vm_area *self, process *proc, uintptr_t base)
{ {
proc->space().add(base, self); vm_space &space = proc ? proc->space() : process::current().space();
space.add(base, self);
return j6_status_ok; return j6_status_ok;
} }
j6_status_t j6_status_t
vma_unmap(vm_area *self, process *proc) vma_unmap(vm_area *self, process *proc)
{ {
proc->space().remove(self); vm_space &space = proc ? proc->space() : process::current().space();
space.remove(self);
return j6_status_ok; return j6_status_ok;
} }

View File

@@ -9,11 +9,10 @@
#include <j6/syscalls.h> #include <j6/syscalls.h>
#include <j6/types.h> #include <j6/types.h>
j6_handle_t __handle_self;
namespace { namespace {
constexpr size_t static_arr_count = 8; constexpr size_t static_arr_count = 8;
j6_handle_descriptor handle_array[static_arr_count]; j6_handle_descriptor handle_array[static_arr_count];
j6_init_args init_args;
} // namespace } // namespace
j6_handle_t j6_handle_t
@@ -37,10 +36,12 @@ j6_find_first_handle(j6_object_type obj_type)
return j6_handle_invalid; return j6_handle_invalid;
} }
extern "C" void extern "C" j6_init_args *
__init_libj6(uint64_t *rsp) __init_libj6(uint64_t arg0, uint64_t arg1)
{ {
__handle_self = j6_find_first_handle(j6_object_type_process); init_args.args[0] = arg0;
init_args.args[1] = arg1;
return &init_args;
} }
#endif // __j6kernel #endif // __j6kernel

View File

@@ -8,6 +8,11 @@
extern "C" { extern "C" {
#endif #endif
struct j6_init_args
{
uint64_t args[2];
};
/// Find the first handle of the given type held by this process /// Find the first handle of the given type held by this process
j6_handle_t j6_find_first_handle(j6_object_type obj_type); j6_handle_t j6_find_first_handle(j6_object_type obj_type);

View File

@@ -5,13 +5,19 @@ extern __init_libc
global _start:function (_start.end - _start) global _start:function (_start.end - _start)
_start: _start:
push 0 ; Add null frame
push 0
mov rbp, rsp mov rbp, rsp
mov rdi, rsp
call __init_libj6 call __init_libj6
mov rbx, rax
call __init_libc call __init_libc
pop rdi pop rdi
mov rsi, rsp mov rsi, rsp
mov rdx, 0 ; TODO: actually parse stack for argc, argv, envp
mov rcx, rbx
call main call main
mov rdi, rax mov rdi, rax

View File

@@ -11,11 +11,14 @@ namespace {
void void
run_ctor_list(cb *array, cb *end) run_ctor_list(cb *array, cb *end)
{ {
if (!array || !end)
return;
size_t i = 0; size_t i = 0;
while (true) { while (true) {
const cb &ctor = array[i++]; const cb &ctor = array[i++];
if (&ctor == end) return; if (&ctor == end) return;
ctor(); if (ctor) ctor();
} }
} }