[Zion] Add a ProcessWait syscall.
This commit is contained in:
parent
642fc4d80d
commit
d9a4be6555
|
@ -10,6 +10,7 @@ z_err_t SysCall1(uint64_t code, const void* req);
|
||||||
SYS1(ProcessExit, uint64_t, code);
|
SYS1(ProcessExit, uint64_t, code);
|
||||||
SYS5(ProcessSpawn, z_cap_t, proc_cap, z_cap_t, bootstrap_cap, z_cap_t*,
|
SYS5(ProcessSpawn, z_cap_t, proc_cap, z_cap_t, bootstrap_cap, z_cap_t*,
|
||||||
new_proc_cap, z_cap_t*, new_vmas_cap, z_cap_t*, new_bootstrap_cap);
|
new_proc_cap, z_cap_t*, new_vmas_cap, z_cap_t*, new_bootstrap_cap);
|
||||||
|
SYS2(ProcessWait, z_cap_t, proc_cap, z_err_t*, exit_code);
|
||||||
|
|
||||||
SYS2(ThreadCreate, z_cap_t, proc_cap, z_cap_t*, thread_cap);
|
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,
|
SYS4(ThreadStart, z_cap_t, thread_cap, uint64_t, entry, uint64_t, arg1,
|
||||||
|
|
|
@ -12,6 +12,7 @@ typedef uint64_t z_err_t;
|
||||||
// Process Calls.
|
// Process Calls.
|
||||||
const uint64_t kZionProcessExit = 0x1;
|
const uint64_t kZionProcessExit = 0x1;
|
||||||
const uint64_t kZionProcessSpawn = 0x2;
|
const uint64_t kZionProcessSpawn = 0x2;
|
||||||
|
const uint64_t kZionProcessWait = 0x3;
|
||||||
|
|
||||||
// Thread Calls.
|
// Thread Calls.
|
||||||
const uint64_t kZionThreadCreate = 0x10;
|
const uint64_t kZionThreadCreate = 0x10;
|
||||||
|
|
|
@ -79,7 +79,7 @@ extern "C" void interrupt_divide_by_zero(InterruptFrame* frame) {
|
||||||
StackUnwind(frame->rbp);
|
StackUnwind(frame->rbp);
|
||||||
|
|
||||||
if (IsUserSpace(frame->rip)) {
|
if (IsUserSpace(frame->rip)) {
|
||||||
gScheduler->CurrentProcess().Exit();
|
gScheduler->CurrentProcess().Exit(glcr::INTERNAL);
|
||||||
UNREACHABLE
|
UNREACHABLE
|
||||||
}
|
}
|
||||||
panic("DIV0");
|
panic("DIV0");
|
||||||
|
@ -91,7 +91,7 @@ extern "C" void interrupt_invalid_opcode(InterruptFrame* frame) {
|
||||||
StackUnwind(frame->rbp);
|
StackUnwind(frame->rbp);
|
||||||
|
|
||||||
if (IsUserSpace(frame->rip)) {
|
if (IsUserSpace(frame->rip)) {
|
||||||
gScheduler->CurrentProcess().Exit();
|
gScheduler->CurrentProcess().Exit(glcr::INTERNAL);
|
||||||
UNREACHABLE
|
UNREACHABLE
|
||||||
}
|
}
|
||||||
panic("INVALID OPCODE");
|
panic("INVALID OPCODE");
|
||||||
|
@ -117,7 +117,7 @@ extern "C" void interrupt_protection_fault(InterruptFrame* frame) {
|
||||||
StackUnwind(frame->rbp);
|
StackUnwind(frame->rbp);
|
||||||
|
|
||||||
if (IsUserSpace(frame->rip)) {
|
if (IsUserSpace(frame->rip)) {
|
||||||
gScheduler->CurrentProcess().Exit();
|
gScheduler->CurrentProcess().Exit(glcr::INTERNAL);
|
||||||
UNREACHABLE
|
UNREACHABLE
|
||||||
}
|
}
|
||||||
panic("GP");
|
panic("GP");
|
||||||
|
@ -159,7 +159,7 @@ extern "C" void interrupt_page_fault(InterruptFrame* frame) {
|
||||||
StackUnwind(frame->rbp);
|
StackUnwind(frame->rbp);
|
||||||
|
|
||||||
if (IsUserSpace(frame->rip)) {
|
if (IsUserSpace(frame->rip)) {
|
||||||
gScheduler->CurrentProcess().Exit();
|
gScheduler->CurrentProcess().Exit(glcr::INTERNAL);
|
||||||
UNREACHABLE
|
UNREACHABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ extern "C" void isr_fpe_fault();
|
||||||
extern "C" void interrupt_fpe_fault(InterruptFrame* frame) {
|
extern "C" void interrupt_fpe_fault(InterruptFrame* frame) {
|
||||||
dbgln("Floating point exception.");
|
dbgln("Floating point exception.");
|
||||||
if (IsUserSpace(frame->rip)) {
|
if (IsUserSpace(frame->rip)) {
|
||||||
gScheduler->CurrentProcess().Exit();
|
gScheduler->CurrentProcess().Exit(glcr::INTERNAL);
|
||||||
UNREACHABLE
|
UNREACHABLE
|
||||||
}
|
}
|
||||||
panic("Floating point exception");
|
panic("Floating point exception");
|
||||||
|
|
|
@ -59,10 +59,11 @@ uint64_t Process::AddExistingCapability(const glcr::RefPtr<Capability>& cap) {
|
||||||
return caps_.AddExistingCapability(cap);
|
return caps_.AddExistingCapability(cap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::Exit() {
|
void Process::Exit(uint64_t exit_code) {
|
||||||
// TODO: Check this state elsewhere to ensure that we don't for instance
|
// TODO: Check this state elsewhere to ensure that we don't for instance
|
||||||
// create a running thread on a finished process.
|
// create a running thread on a finished process.
|
||||||
state_ = CLEANUP;
|
state_ = CLEANUP;
|
||||||
|
exit_code_ = exit_code;
|
||||||
|
|
||||||
for (uint64_t i = 0; i < threads_.size(); i++) {
|
for (uint64_t i = 0; i < threads_.size(); i++) {
|
||||||
if (!threads_[i]->IsDying()) {
|
if (!threads_[i]->IsDying()) {
|
||||||
|
|
|
@ -57,10 +57,11 @@ class Process : public KernelObject {
|
||||||
uint64_t AddExistingCapability(const glcr::RefPtr<Capability>& cap);
|
uint64_t AddExistingCapability(const glcr::RefPtr<Capability>& cap);
|
||||||
|
|
||||||
State GetState() { return state_; }
|
State GetState() { return state_; }
|
||||||
|
uint64_t exit_code() { return exit_code_; }
|
||||||
|
|
||||||
// This stops all of the processes threads (they will no longer be scheduled)
|
// This stops all of the processes threads (they will no longer be scheduled)
|
||||||
// and flags the process for cleanup.
|
// and flags the process for cleanup.
|
||||||
void Exit();
|
void Exit(uint64_t code);
|
||||||
|
|
||||||
// This *should not* be called from a thread that belongs to this process.
|
// This *should not* be called from a thread that belongs to this process.
|
||||||
// Rather it should be called from the cleanup thread.
|
// Rather it should be called from the cleanup thread.
|
||||||
|
@ -76,6 +77,7 @@ class Process : public KernelObject {
|
||||||
uint64_t id_;
|
uint64_t id_;
|
||||||
glcr::RefPtr<AddressSpace> vmas_;
|
glcr::RefPtr<AddressSpace> vmas_;
|
||||||
State state_;
|
State state_;
|
||||||
|
uint64_t exit_code_ = -1;
|
||||||
|
|
||||||
uint64_t next_thread_id_ = 0;
|
uint64_t next_thread_id_ = 0;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
z_err_t ProcessExit(ZProcessExitReq* req) {
|
z_err_t ProcessExit(ZProcessExitReq* req) {
|
||||||
auto curr_thread = gScheduler->CurrentThread();
|
auto curr_thread = gScheduler->CurrentThread();
|
||||||
dbgln("Exit code: {}", static_cast<glcr::ErrorCode>(req->code));
|
dbgln("Exit code: {}", static_cast<glcr::ErrorCode>(req->code));
|
||||||
curr_thread->process().Exit();
|
curr_thread->process().Exit(req->code);
|
||||||
panic("Returned from thread exit");
|
panic("Returned from thread exit");
|
||||||
return glcr::UNIMPLEMENTED;
|
return glcr::UNIMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
@ -39,3 +39,17 @@ z_err_t ProcessSpawn(ZProcessSpawnReq* req) {
|
||||||
|
|
||||||
return glcr::OK;
|
return glcr::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
z_err_t ProcessWait(ZProcessWaitReq* req) {
|
||||||
|
auto& curr_proc = gScheduler->CurrentProcess();
|
||||||
|
auto cap = curr_proc.GetCapability(req->proc_cap);
|
||||||
|
RET_ERR(ValidateCapability<Process>(cap, kZionPerm_Read));
|
||||||
|
|
||||||
|
auto proc = cap->obj<Process>();
|
||||||
|
if (proc->id() == curr_proc.id()) {
|
||||||
|
return glcr::INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
proc->GetThread(0)->Wait();
|
||||||
|
*req->exit_code = proc->exit_code();
|
||||||
|
return glcr::OK;
|
||||||
|
}
|
||||||
|
|
|
@ -4,3 +4,4 @@
|
||||||
|
|
||||||
z_err_t ProcessExit(ZProcessExitReq* req);
|
z_err_t ProcessExit(ZProcessExitReq* req);
|
||||||
z_err_t ProcessSpawn(ZProcessSpawnReq* req);
|
z_err_t ProcessSpawn(ZProcessSpawnReq* req);
|
||||||
|
z_err_t ProcessWait(ZProcessWaitReq* req);
|
||||||
|
|
|
@ -53,6 +53,7 @@ extern "C" z_err_t SyscallHandler(uint64_t call_id, void* req) {
|
||||||
// syscall/process.h
|
// syscall/process.h
|
||||||
CASE(ProcessExit);
|
CASE(ProcessExit);
|
||||||
CASE(ProcessSpawn);
|
CASE(ProcessSpawn);
|
||||||
|
CASE(ProcessWait);
|
||||||
// syscall/thread.h
|
// syscall/thread.h
|
||||||
CASE(ThreadCreate);
|
CASE(ThreadCreate);
|
||||||
CASE(ThreadStart);
|
CASE(ThreadStart);
|
||||||
|
|
Loading…
Reference in New Issue