Compare commits
3 Commits
642fc4d80d
...
0b9f83b321
Author | SHA1 | Date |
---|---|---|
|
0b9f83b321 | |
|
8c5dd00443 | |
|
d9a4be6555 |
|
@ -6,6 +6,7 @@
|
|||
#include "glacier/container/linked_list.h"
|
||||
#include "glacier/container/pair.h"
|
||||
#include "glacier/status/error.h"
|
||||
#include "glacier/string/str_format.h"
|
||||
#include "glacier/string/string.h"
|
||||
#include "glacier/util/hash.h"
|
||||
|
||||
|
@ -53,6 +54,8 @@ class HashMap {
|
|||
|
||||
void Resize(uint64_t new_size);
|
||||
|
||||
void DebugIntoStr(StringBuilder& builder) const;
|
||||
|
||||
private:
|
||||
Array<LinkedList<Pair<K, V>>> data_;
|
||||
uint64_t size_ = 0;
|
||||
|
@ -211,4 +214,26 @@ void HashMap<K, V, H>::ResizeIfNecessary() {
|
|||
}
|
||||
}
|
||||
|
||||
template <typename K, typename V>
|
||||
void StrFormatValue(StringBuilder& builder, const HashMap<K, V>& value,
|
||||
StringView opts) {
|
||||
value.DebugIntoStr(builder);
|
||||
}
|
||||
|
||||
template <typename K, typename V, class H>
|
||||
void HashMap<K, V, H>::DebugIntoStr(StringBuilder& builder) const {
|
||||
for (uint64_t i = 0; i < data_.size(); i++) {
|
||||
if (data_[i].size() == 0) {
|
||||
continue;
|
||||
}
|
||||
StrFormatValue(builder, i, "");
|
||||
builder.PushBack(": ");
|
||||
auto& ll = data_[i];
|
||||
for (auto& item : ll) {
|
||||
StrFormatInternal(builder, "{},", item.first());
|
||||
}
|
||||
builder.PushBack('\n');
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace glcr
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "glacier/string/str_format.h"
|
||||
|
||||
namespace glcr {
|
||||
|
||||
template <typename T>
|
||||
|
@ -100,4 +102,10 @@ RefPtr<T> StaticCastRefPtr(const RefPtr<U>& ref) {
|
|||
return RefPtr(static_cast<T*>(ref.get()), RefPtr<T>::DontAdopt);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void StrFormatValue(StringBuilder& builder, const RefPtr<T>& value,
|
||||
StringView opts) {
|
||||
StrFormatValue(builder, (uint64_t)value.get(), opts);
|
||||
}
|
||||
|
||||
} // namespace glcr
|
||||
|
|
|
@ -103,7 +103,7 @@ uint64_t LoadElfProgram(uint64_t base, uint64_t as_cap) {
|
|||
|
||||
} // namespace
|
||||
|
||||
glcr::ErrorCode SpawnProcessFromElfRegion(uint64_t program,
|
||||
glcr::ErrorOr<z_cap_t> SpawnProcessFromElfRegion(uint64_t program,
|
||||
z_cap_t yellowstone_client) {
|
||||
uint64_t proc_cap;
|
||||
uint64_t as_cap;
|
||||
|
@ -130,7 +130,9 @@ glcr::ErrorCode SpawnProcessFromElfRegion(uint64_t program,
|
|||
uint64_t thread_cap;
|
||||
RET_ERR(ZThreadCreate(proc_cap, &thread_cap));
|
||||
|
||||
RET_ERR(pclient.WriteMessage<uint64_t>(Z_INIT_SELF_PROC, proc_cap));
|
||||
uint64_t dup_proc_cap;
|
||||
RET_ERR(ZCapDuplicate(proc_cap, kZionPerm_All, &dup_proc_cap));
|
||||
RET_ERR(pclient.WriteMessage<uint64_t>(Z_INIT_SELF_PROC, dup_proc_cap));
|
||||
RET_ERR(pclient.WriteMessage<uint64_t>(Z_INIT_SELF_VMAS, as_cap));
|
||||
RET_ERR(pclient.WriteMessage<uint64_t>(Z_INIT_ENDPOINT, yellowstone_client));
|
||||
|
||||
|
@ -139,7 +141,7 @@ glcr::ErrorCode SpawnProcessFromElfRegion(uint64_t program,
|
|||
#endif
|
||||
RET_ERR(ZThreadStart(thread_cap, entry_point, foreign_port_id, 0));
|
||||
|
||||
return glcr::OK;
|
||||
return proc_cap;
|
||||
}
|
||||
|
||||
} // namespace mmth
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/status/error.h>
|
||||
#include <glacier/status/error_or.h>
|
||||
#include <stdint.h>
|
||||
#include <ztypes.h>
|
||||
|
||||
namespace mmth {
|
||||
|
||||
glcr::ErrorCode SpawnProcessFromElfRegion(uint64_t program,
|
||||
glcr::ErrorOr<z_cap_t> SpawnProcessFromElfRegion(uint64_t program,
|
||||
z_cap_t yellowstone_client);
|
||||
|
||||
} // namespace mmth
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <glacier/string/str_split.h>
|
||||
#include <mammoth/file/file.h>
|
||||
#include <mammoth/proc/process.h>
|
||||
#include <mammoth/util/debug.h>
|
||||
#include <mammoth/util/init.h>
|
||||
|
||||
void Terminal::HandleCharacter(char c) {
|
||||
|
@ -68,7 +69,19 @@ void Terminal::ExecuteCommand(const glcr::String& command) {
|
|||
auto file = mmth::File::Open(tokens[1]);
|
||||
|
||||
// TODO: Wait until the process exits.
|
||||
mmth::SpawnProcessFromElfRegion((uint64_t)file.raw_ptr(), gInitEndpointCap);
|
||||
auto error_or_cap = mmth::SpawnProcessFromElfRegion(
|
||||
(uint64_t)file.raw_ptr(), gInitEndpointCap);
|
||||
if (!error_or_cap.ok()) {
|
||||
console_.WriteString(
|
||||
glcr::StrFormat("Error: {}\n", error_or_cap.error()));
|
||||
return;
|
||||
}
|
||||
uint64_t err_code;
|
||||
check(ZProcessWait(error_or_cap.value(), &err_code));
|
||||
if (err_code != 0) {
|
||||
console_.WriteString(glcr::StrFormat(
|
||||
"Process Error: {}\n", static_cast<glcr::ErrorCode>(err_code)));
|
||||
}
|
||||
|
||||
} else {
|
||||
console_.WriteString("Unknown command: ");
|
||||
|
|
|
@ -15,7 +15,12 @@
|
|||
glcr::ErrorCode SpawnProcess(z_cap_t vmmo_cap, z_cap_t yellowstone_cap) {
|
||||
mmth::OwnedMemoryRegion region =
|
||||
mmth::OwnedMemoryRegion::FromCapability(vmmo_cap);
|
||||
return mmth::SpawnProcessFromElfRegion(region.vaddr(), yellowstone_cap);
|
||||
auto error_or =
|
||||
mmth::SpawnProcessFromElfRegion(region.vaddr(), yellowstone_cap);
|
||||
if (error_or.ok()) {
|
||||
return glcr::OK;
|
||||
}
|
||||
return error_or.error();
|
||||
}
|
||||
|
||||
uint64_t main(uint64_t port_cap) {
|
||||
|
@ -48,8 +53,11 @@ uint64_t main(uint64_t port_cap) {
|
|||
mmth::File::Open(glcr::StrFormat("/bin/{}", files[i]));
|
||||
|
||||
ASSIGN_OR_RETURN(client_cap, server->CreateClientCap());
|
||||
check(mmth::SpawnProcessFromElfRegion((uint64_t)binary.raw_ptr(),
|
||||
client_cap));
|
||||
auto error_or = mmth::SpawnProcessFromElfRegion(
|
||||
(uint64_t)binary.raw_ptr(), client_cap);
|
||||
if (!error_or.ok()) {
|
||||
check(error_or.error());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ z_err_t SysCall1(uint64_t code, const void* req);
|
|||
SYS1(ProcessExit, uint64_t, code);
|
||||
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);
|
||||
SYS2(ProcessWait, z_cap_t, proc_cap, z_err_t*, exit_code);
|
||||
|
||||
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,
|
||||
|
|
|
@ -12,6 +12,7 @@ typedef uint64_t z_err_t;
|
|||
// Process Calls.
|
||||
const uint64_t kZionProcessExit = 0x1;
|
||||
const uint64_t kZionProcessSpawn = 0x2;
|
||||
const uint64_t kZionProcessWait = 0x3;
|
||||
|
||||
// Thread Calls.
|
||||
const uint64_t kZionThreadCreate = 0x10;
|
||||
|
|
|
@ -79,7 +79,7 @@ extern "C" void interrupt_divide_by_zero(InterruptFrame* frame) {
|
|||
StackUnwind(frame->rbp);
|
||||
|
||||
if (IsUserSpace(frame->rip)) {
|
||||
gScheduler->CurrentProcess().Exit();
|
||||
gScheduler->CurrentProcess().Exit(glcr::INTERNAL);
|
||||
UNREACHABLE
|
||||
}
|
||||
panic("DIV0");
|
||||
|
@ -91,7 +91,7 @@ extern "C" void interrupt_invalid_opcode(InterruptFrame* frame) {
|
|||
StackUnwind(frame->rbp);
|
||||
|
||||
if (IsUserSpace(frame->rip)) {
|
||||
gScheduler->CurrentProcess().Exit();
|
||||
gScheduler->CurrentProcess().Exit(glcr::INTERNAL);
|
||||
UNREACHABLE
|
||||
}
|
||||
panic("INVALID OPCODE");
|
||||
|
@ -117,7 +117,7 @@ extern "C" void interrupt_protection_fault(InterruptFrame* frame) {
|
|||
StackUnwind(frame->rbp);
|
||||
|
||||
if (IsUserSpace(frame->rip)) {
|
||||
gScheduler->CurrentProcess().Exit();
|
||||
gScheduler->CurrentProcess().Exit(glcr::INTERNAL);
|
||||
UNREACHABLE
|
||||
}
|
||||
panic("GP");
|
||||
|
@ -159,7 +159,7 @@ extern "C" void interrupt_page_fault(InterruptFrame* frame) {
|
|||
StackUnwind(frame->rbp);
|
||||
|
||||
if (IsUserSpace(frame->rip)) {
|
||||
gScheduler->CurrentProcess().Exit();
|
||||
gScheduler->CurrentProcess().Exit(glcr::INTERNAL);
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,7 @@ extern "C" void isr_fpe_fault();
|
|||
extern "C" void interrupt_fpe_fault(InterruptFrame* frame) {
|
||||
dbgln("Floating point exception.");
|
||||
if (IsUserSpace(frame->rip)) {
|
||||
gScheduler->CurrentProcess().Exit();
|
||||
gScheduler->CurrentProcess().Exit(glcr::INTERNAL);
|
||||
UNREACHABLE
|
||||
}
|
||||
panic("Floating point exception");
|
||||
|
|
|
@ -59,10 +59,11 @@ uint64_t Process::AddExistingCapability(const glcr::RefPtr<Capability>& 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
|
||||
// create a running thread on a finished process.
|
||||
state_ = CLEANUP;
|
||||
exit_code_ = exit_code;
|
||||
|
||||
for (uint64_t i = 0; i < threads_.size(); i++) {
|
||||
if (!threads_[i]->IsDying()) {
|
||||
|
|
|
@ -57,10 +57,11 @@ class Process : public KernelObject {
|
|||
uint64_t AddExistingCapability(const glcr::RefPtr<Capability>& cap);
|
||||
|
||||
State GetState() { return state_; }
|
||||
uint64_t exit_code() { return exit_code_; }
|
||||
|
||||
// This stops all of the processes threads (they will no longer be scheduled)
|
||||
// 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.
|
||||
// Rather it should be called from the cleanup thread.
|
||||
|
@ -76,6 +77,7 @@ class Process : public KernelObject {
|
|||
uint64_t id_;
|
||||
glcr::RefPtr<AddressSpace> vmas_;
|
||||
State state_;
|
||||
uint64_t exit_code_ = -1;
|
||||
|
||||
uint64_t next_thread_id_ = 0;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
z_err_t ProcessExit(ZProcessExitReq* req) {
|
||||
auto curr_thread = gScheduler->CurrentThread();
|
||||
dbgln("Exit code: {}", static_cast<glcr::ErrorCode>(req->code));
|
||||
curr_thread->process().Exit();
|
||||
curr_thread->process().Exit(req->code);
|
||||
panic("Returned from thread exit");
|
||||
return glcr::UNIMPLEMENTED;
|
||||
}
|
||||
|
@ -39,3 +39,17 @@ z_err_t ProcessSpawn(ZProcessSpawnReq* req) {
|
|||
|
||||
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 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
|
||||
CASE(ProcessExit);
|
||||
CASE(ProcessSpawn);
|
||||
CASE(ProcessWait);
|
||||
// syscall/thread.h
|
||||
CASE(ThreadCreate);
|
||||
CASE(ThreadStart);
|
||||
|
|
Loading…
Reference in New Issue