feat: implement new IPC layer
This commit is contained in:
+63
-26
@@ -7,8 +7,6 @@
|
||||
|
||||
#pragma once
|
||||
#include <Sched/Scheduler.hpp>
|
||||
#include <Memory/PageFrameAllocator.hpp>
|
||||
|
||||
#include "Syscall.hpp"
|
||||
#include "Common.hpp"
|
||||
#include "Path.hpp"
|
||||
@@ -19,53 +17,92 @@ namespace Montauk {
|
||||
char resolved[256];
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||
|
||||
int parentSlot = Ipc::CurrentSlot();
|
||||
int childPid = Sched::Spawn(resolved, args);
|
||||
if (childPid < 0) return -1;
|
||||
|
||||
auto* child = Sched::GetProcessByPid(childPid);
|
||||
if (child == nullptr) return -1;
|
||||
int childSlot = Ipc::SlotForPid(childPid);
|
||||
if (child == nullptr || childSlot < 0 || parentSlot < 0) return -1;
|
||||
|
||||
// Allocate ring buffers
|
||||
void* outPage = Memory::g_pfa->AllocateZeroed();
|
||||
void* inPage = Memory::g_pfa->AllocateZeroed();
|
||||
if (!outPage || !inPage) return -1;
|
||||
Ipc::Stream* outStream = Ipc::CreateStream();
|
||||
Ipc::Stream* inStream = Ipc::CreateStream();
|
||||
Ipc::Mailbox* keyMailbox = Ipc::CreateMailbox();
|
||||
if (outStream == nullptr || inStream == nullptr || keyMailbox == nullptr) {
|
||||
if (outStream != nullptr) Ipc::ReleaseStream(outStream, false, false);
|
||||
if (inStream != nullptr) Ipc::ReleaseStream(inStream, false, false);
|
||||
if (keyMailbox != nullptr) Ipc::ReleaseMailbox(keyMailbox, false, false);
|
||||
Sched::KillProcess(childPid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int parentOutHandle = Ipc::InstallHandleForSlot(
|
||||
parentSlot, (Ipc::Object*)outStream, Ipc::HandleType::Stream, Ipc::RightRead);
|
||||
int parentInHandle = Ipc::InstallHandleForSlot(
|
||||
parentSlot, (Ipc::Object*)inStream, Ipc::HandleType::Stream, Ipc::RightWrite);
|
||||
int parentKeyHandle = Ipc::InstallHandleForSlot(
|
||||
parentSlot, (Ipc::Object*)keyMailbox, Ipc::HandleType::Mailbox, Ipc::RightSend);
|
||||
|
||||
child->ioOutHandle = Ipc::InstallHandleForSlot(
|
||||
childSlot, (Ipc::Object*)outStream, Ipc::HandleType::Stream,
|
||||
Ipc::RightWrite | Ipc::RightWait | Ipc::RightDup);
|
||||
child->ioInHandle = Ipc::InstallHandleForSlot(
|
||||
childSlot, (Ipc::Object*)inStream, Ipc::HandleType::Stream,
|
||||
Ipc::RightRead | Ipc::RightWait | Ipc::RightDup);
|
||||
child->ioKeyHandle = Ipc::InstallHandleForSlot(
|
||||
childSlot, (Ipc::Object*)keyMailbox, Ipc::HandleType::Mailbox,
|
||||
Ipc::RightRecv | Ipc::RightWait | Ipc::RightDup);
|
||||
|
||||
if (parentOutHandle < 0 || parentInHandle < 0 || parentKeyHandle < 0 ||
|
||||
child->ioOutHandle < 0 || child->ioInHandle < 0 || child->ioKeyHandle < 0 ||
|
||||
!ConfigureRedirWaitsetForSlot(childSlot, child)) {
|
||||
if (parentOutHandle >= 0) Ipc::CloseHandleForSlot(parentSlot, parentOutHandle);
|
||||
if (parentInHandle >= 0) Ipc::CloseHandleForSlot(parentSlot, parentInHandle);
|
||||
if (parentKeyHandle >= 0) Ipc::CloseHandleForSlot(parentSlot, parentKeyHandle);
|
||||
if (child->ioOutHandle < 0) Ipc::ReleaseStream(outStream, false, false);
|
||||
if (child->ioInHandle < 0) Ipc::ReleaseStream(inStream, false, false);
|
||||
if (child->ioKeyHandle < 0) Ipc::ReleaseMailbox(keyMailbox, false, false);
|
||||
Sched::KillProcess(childPid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
child->outBuf = (uint8_t*)outPage;
|
||||
child->inBuf = (uint8_t*)inPage;
|
||||
child->outHead = 0;
|
||||
child->outTail = 0;
|
||||
child->inHead = 0;
|
||||
child->inTail = 0;
|
||||
child->keyHead = 0;
|
||||
child->keyTail = 0;
|
||||
child->redirected = true;
|
||||
child->parentPid = Sched::GetCurrentPid();
|
||||
child->termCols = 0;
|
||||
child->termRows = 0;
|
||||
|
||||
return childPid;
|
||||
}
|
||||
|
||||
static int Sys_ChildIoRead(int childPid, char* buf, int maxLen) {
|
||||
auto* child = Sched::GetProcessByPid(childPid);
|
||||
if (child == nullptr || !child->redirected || !child->outBuf) return -1;
|
||||
return RingRead(child->outBuf, child->outHead, child->outTail, Sched::Process::IoBufSize, (uint8_t*)buf, maxLen);
|
||||
Ipc::Stream* stream = GetRedirOutStream(child);
|
||||
if (child == nullptr || !child->redirected || stream == nullptr) return -1;
|
||||
return Ipc::StreamRead(stream, (uint8_t*)buf, maxLen, true);
|
||||
}
|
||||
|
||||
static int Sys_ChildIoWrite(int childPid, const char* data, int len) {
|
||||
auto* child = Sched::GetProcessByPid(childPid);
|
||||
if (child == nullptr || !child->redirected || !child->inBuf) return -1;
|
||||
for (int i = 0; i < len; i++) {
|
||||
RingWrite(child->inBuf, child->inHead, child->inTail, Sched::Process::IoBufSize, (uint8_t)data[i]);
|
||||
}
|
||||
return len;
|
||||
Ipc::Stream* stream = GetRedirInStream(child);
|
||||
if (child == nullptr || !child->redirected || stream == nullptr) return -1;
|
||||
return WriteAllToStream(stream, (const uint8_t*)data, len);
|
||||
}
|
||||
|
||||
static int Sys_ChildIoWriteKey(int childPid, const KeyEvent* key) {
|
||||
if (key == nullptr) return -1;
|
||||
auto* child = Sched::GetProcessByPid(childPid);
|
||||
if (child == nullptr || !child->redirected) return -1;
|
||||
child->keyBuf[child->keyHead] = *key;
|
||||
child->keyHead = (child->keyHead + 1) % 64;
|
||||
return 0;
|
||||
Ipc::Mailbox* mailbox = GetRedirKeyMailbox(child);
|
||||
if (child == nullptr || !child->redirected || mailbox == nullptr) return -1;
|
||||
|
||||
for (;;) {
|
||||
int rc = Ipc::MailboxSend(mailbox, 0, key, sizeof(KeyEvent));
|
||||
if (rc < 0) return -1;
|
||||
if (rc == 0) {
|
||||
Sched::BlockOnObject(mailbox, 0);
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int Sys_ChildIoSetTermsz(int childPid, int cols, int rows) {
|
||||
|
||||
Reference in New Issue
Block a user