Files
jsix/src/kernel/objects/process.cpp
Justin C. Miller 1d30322820 [kernel] Pass objects not handles to syscall impls
This commit contains a couple large, interdependent changes:

- In preparation for capability checking, the _syscall_verify_*
  functions now load most handles passed in, and verify that they exist
  and are of the correct type. Lists and out-handles are not converted
  to objects.
- Also in preparation for capability checking, the internal
  representation of handles has changed. j6_handle_t is now 32 bits, and
  a new j6_cap_t (also 32 bits) is added. Handles of a process are now a
  util::map<j6_handle_t, handle> where handle is a new struct containing
  the id, capabilities, and object pointer.
- The kernel object definition DSL gained a few changes to support auto
  generating the handle -> object conversion in the _syscall_verify_*
  functions, mostly knowing the object type, and an optional "cname"
  attribute on objects where their names differ from C++ code.
  (Specifically vma/vm_area)
- Kernel object code and other code under kernel/objects is now in a new
  obj:: namespace, because fuck you <cstdlib> for putting "system" in
  the global namespace. Why even have that header then?
- Kernel object types constructed with the construct_handle helper now
  have a creation_caps static member to declare what capabilities a
  newly created object's handle should have.
2022-01-17 23:23:04 -08:00

151 lines
3.2 KiB
C++

#include <util/no_construct.h>
#include "assert.h"
#include "cpu.h"
#include "objects/process.h"
#include "objects/thread.h"
#include "objects/vm_area.h"
#include "scheduler.h"
// This object is initialized _before_ global constructors are called,
// so we don't want it to have a global constructor at all, lest it
// overwrite the previous initialization.
static util::no_construct<obj::process> __g_kernel_process_storage;
obj::process &g_kernel_process = __g_kernel_process_storage.value;
namespace obj {
process::process() :
kobject {kobject::type::process},
m_next_handle {1},
m_state {state::running}
{
j6_handle_t self = add_handle(this, process::self_caps);
kassert(self == self_handle(), "Process self-handle is not 1");
}
// The "kernel process"-only constructor
process::process(page_table *kpml4) :
kobject {kobject::type::process},
m_space {kpml4},
m_next_handle {self_handle()+1},
m_state {state::running}
{
}
process::~process()
{
}
process & process::current() { return *current_cpu().process; }
process & process::kernel_process() { return g_kernel_process; }
process *
process::create_kernel_process(page_table *pml4)
{
return new (&g_kernel_process) process {pml4};
}
void
process::exit(int32_t code)
{
// TODO: make this thread-safe
m_state = state::exited;
m_return_code = code;
close();
for (auto *thread : m_threads) {
thread->exit(code);
}
if (this == current_cpu().process)
scheduler::get().schedule();
}
void
process::update()
{
kassert(m_threads.count() > 0, "process::update with zero threads!");
size_t i = 0;
uint32_t status = 0;
while (i < m_threads.count()) {
thread *th = m_threads[i];
if (th->has_state(thread::state::exited)) {
status = th->m_return_code;
m_threads.remove_swap_at(i);
continue;
}
i++;
}
if (m_threads.count() == 0) {
// TODO: What really is the return code in this case?
exit(status);
}
}
thread *
process::create_thread(uintptr_t rsp3, uint8_t priority)
{
if (priority == default_priority)
priority = scheduler::default_priority;
thread *th = new thread(*this, priority);
kassert(th, "Failed to create thread!");
if (rsp3)
th->tcb()->rsp3 = rsp3;
m_threads.append(th);
scheduler::get().add_thread(th->tcb());
return th;
}
bool
process::thread_exited(thread *th)
{
kassert(&th->m_parent == this, "Process got thread_exited for non-child!");
uint32_t status = th->m_return_code;
m_threads.remove_swap(th);
remove_handle(th->self_handle());
delete th;
// TODO: delete the thread's stack VMA
if (m_threads.count() == 0) {
exit(status);
return true;
}
return false;
}
j6_handle_t
process::add_handle(kobject *obj, j6_cap_t caps)
{
if (!obj)
return j6_handle_invalid;
j6_handle_t id = m_next_handle++;
m_handles.insert(id, {id, obj, caps});
return id;
}
bool
process::remove_handle(j6_handle_t id)
{
return m_handles.erase(id);
}
handle *
process::lookup_handle(j6_handle_t id)
{
return m_handles.find(id);
}
} // namespace obj