mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
[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:
@@ -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
|
||||||
|
|||||||
@@ -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] {
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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>",
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -5,15 +5,21 @@ extern __init_libc
|
|||||||
|
|
||||||
global _start:function (_start.end - _start)
|
global _start:function (_start.end - _start)
|
||||||
_start:
|
_start:
|
||||||
mov rbp, rsp
|
push 0 ; Add null frame
|
||||||
mov rdi, rsp
|
push 0
|
||||||
call __init_libj6
|
mov rbp, rsp
|
||||||
call __init_libc
|
|
||||||
|
|
||||||
pop rdi
|
call __init_libj6
|
||||||
mov rsi, rsp
|
mov rbx, rax
|
||||||
call main
|
|
||||||
|
|
||||||
mov rdi, rax
|
call __init_libc
|
||||||
call exit
|
|
||||||
|
pop rdi
|
||||||
|
mov rsi, rsp
|
||||||
|
mov rdx, 0 ; TODO: actually parse stack for argc, argv, envp
|
||||||
|
mov rcx, rbx
|
||||||
|
call main
|
||||||
|
|
||||||
|
mov rdi, rax
|
||||||
|
call exit
|
||||||
.end:
|
.end:
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user