209 lines
6.7 KiB
C++
209 lines
6.7 KiB
C++
/*
|
|
* Process.hpp
|
|
* SYS_EXIT, SYS_YIELD, SYS_SLEEP_MS, SYS_GETPID,
|
|
* SYS_WAITPID, SYS_SPAWN, SYS_GETARGS, SYS_PROCLIST, SYS_KILL syscalls
|
|
* Copyright (c) 2026 Daniel Hammer
|
|
*/
|
|
|
|
#pragma once
|
|
#include <Sched/Scheduler.hpp>
|
|
#include <Timekeeping/ApicTimer.hpp>
|
|
#include <Memory/Paging.hpp>
|
|
#include <Memory/PageFrameAllocator.hpp>
|
|
#include <Memory/HHDM.hpp>
|
|
#include <Fs/Vfs.hpp>
|
|
|
|
#include "Syscall.hpp"
|
|
#include "Common.hpp"
|
|
#include "WinServer.hpp"
|
|
#include "Path.hpp"
|
|
|
|
namespace montauk::abi {
|
|
static void Sys_Exit(int exitCode) {
|
|
(void)exitCode;
|
|
Sched::ExitProcess();
|
|
}
|
|
|
|
static void Sys_Yield() {
|
|
Sched::Schedule();
|
|
}
|
|
|
|
static void Sys_SleepMs(uint64_t ms) {
|
|
Sched::BlockForSleep(ms);
|
|
}
|
|
|
|
static int Sys_GetPid() {
|
|
return Sched::GetCurrentPid();
|
|
}
|
|
|
|
static void Sys_WaitPid(int pid) {
|
|
Sched::BlockOnPid(pid);
|
|
}
|
|
|
|
static int Sys_Spawn(const char* path, const char* args) {
|
|
char resolved[256];
|
|
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
|
|
|
auto* parent = Sched::GetCurrentProcessPtr();
|
|
int parentSlot = Ipc::CurrentSlot();
|
|
bool inheritRedirection = parent && parent->redirected;
|
|
int childPid = Sched::Spawn(resolved, args, !inheritRedirection);
|
|
if (childPid < 0) return childPid;
|
|
|
|
if (inheritRedirection) {
|
|
auto* child = Sched::GetProcessByPid(childPid);
|
|
int childSlot = Ipc::SlotForPid(childPid);
|
|
if (child == nullptr || childSlot < 0 || parentSlot < 0) {
|
|
Sched::KillProcess(childPid);
|
|
return -1;
|
|
}
|
|
|
|
child->ioOutHandle = DuplicateHandleBetweenSlots(parentSlot, parent->ioOutHandle, childSlot);
|
|
child->ioInHandle = DuplicateHandleBetweenSlots(parentSlot, parent->ioInHandle, childSlot);
|
|
child->ioKeyHandle = DuplicateHandleBetweenSlots(parentSlot, parent->ioKeyHandle, childSlot);
|
|
|
|
if (child->ioOutHandle < 0 || child->ioInHandle < 0 || child->ioKeyHandle < 0 ||
|
|
!ConfigureRedirWaitsetForSlot(childSlot, child)) {
|
|
Sched::KillProcess(childPid);
|
|
return -1;
|
|
}
|
|
|
|
child->redirected = true;
|
|
child->parentPid = parent->pid;
|
|
child->termCols = parent->termCols;
|
|
child->termRows = parent->termRows;
|
|
if (Sched::StartProcess(childPid) < 0) {
|
|
Sched::KillProcess(childPid);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return childPid;
|
|
}
|
|
|
|
static int Sys_GetArgs(char* buf, uint64_t maxLen) {
|
|
auto* proc = Sched::GetCurrentProcessPtr();
|
|
if (proc == nullptr || buf == nullptr || maxLen == 0) return -1;
|
|
int i = 0;
|
|
for (; i < (int)maxLen - 1 && proc->args[i]; i++) {
|
|
buf[i] = proc->args[i];
|
|
}
|
|
buf[i] = '\0';
|
|
return i;
|
|
}
|
|
|
|
static int Sys_ProcList(ProcInfo* buf, int maxCount) {
|
|
if (buf == nullptr || maxCount <= 0) return 0;
|
|
int count = 0;
|
|
for (int i = 0; i < Sched::MaxProcesses && count < maxCount; i++) {
|
|
auto* proc = Sched::GetProcessSlot(i);
|
|
if (!proc || proc->state == Sched::ProcessState::Free) continue;
|
|
// Skip sibling-thread slots; only show one entry per process.
|
|
if (proc->primarySlot != i) continue;
|
|
|
|
buf[count].pid = (int32_t)proc->pid;
|
|
buf[count].parentPid = (int32_t)proc->parentPid;
|
|
buf[count].state = (uint8_t)proc->state;
|
|
buf[count]._pad[0] = 0;
|
|
buf[count]._pad[1] = 0;
|
|
buf[count]._pad[2] = 0;
|
|
{
|
|
int j = 0;
|
|
for (; j < 63 && proc->name[j]; j++)
|
|
buf[count].name[j] = proc->name[j];
|
|
buf[count].name[j] = '\0';
|
|
}
|
|
buf[count].heapUsed = Sched::g_allocatedPages[i] * 0x1000;
|
|
buf[count].cpuTimeMs = proc->cpuTimeMs;
|
|
count++;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
static int Sys_Kill(int pid) {
|
|
return Sched::KillProcess(pid);
|
|
}
|
|
|
|
static int Sys_SetUser(int pid, const char* name) {
|
|
if (name == nullptr) return -1;
|
|
auto* target = Sched::GetProcessByPid(pid);
|
|
if (target == nullptr) return -1;
|
|
int i = 0;
|
|
for (; i < 31 && name[i]; i++)
|
|
target->user[i] = name[i];
|
|
target->user[i] = '\0';
|
|
return 0;
|
|
}
|
|
|
|
static int Sys_GetUser(char* buf, uint64_t maxLen) {
|
|
auto* proc = Sched::GetCurrentProcessPtr();
|
|
if (proc == nullptr || buf == nullptr || maxLen == 0) return -1;
|
|
int i = 0;
|
|
for (; i < (int)maxLen - 1 && proc->user[i]; i++)
|
|
buf[i] = proc->user[i];
|
|
buf[i] = '\0';
|
|
return i;
|
|
}
|
|
|
|
static int Sys_GetCwd(char* buf, uint64_t maxLen) {
|
|
auto* proc = Sched::GetCurrentProcessPtr();
|
|
if (proc == nullptr || buf == nullptr || maxLen == 0) return -1;
|
|
|
|
const char* cwd = proc->cwd[0] ? proc->cwd : "0:/";
|
|
int i = 0;
|
|
for (; i < (int)maxLen - 1 && cwd[i]; i++) buf[i] = cwd[i];
|
|
buf[i] = '\0';
|
|
return i;
|
|
}
|
|
|
|
// ====================================================================
|
|
// Threading
|
|
// ====================================================================
|
|
static int Sys_ThreadSpawn(uint64_t entry, uint64_t arg, uint64_t userStackTop) {
|
|
return Sched::SpawnThread(entry, arg, userStackTop);
|
|
}
|
|
|
|
[[noreturn]] static void Sys_ThreadExit(int exitCode) {
|
|
Sched::ExitCurrentThread(exitCode);
|
|
}
|
|
|
|
static int Sys_ThreadJoin(int tid, int* outExitCode) {
|
|
return Sched::JoinThread(tid, outExitCode);
|
|
}
|
|
|
|
static int Sys_ThreadSelf() {
|
|
return Sched::GetCurrentTid();
|
|
}
|
|
|
|
static int Sys_Chdir(const char* path) {
|
|
auto* proc = Sched::GetCurrentProcessPtr();
|
|
if (proc == nullptr || path == nullptr) return -1;
|
|
|
|
char resolved[256];
|
|
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
|
|
|
bool isDriveRoot = false;
|
|
{
|
|
int prefixLen = 0;
|
|
if (ParseDrivePrefix(resolved, &prefixLen) >= 0 &&
|
|
resolved[prefixLen] == '/' && resolved[prefixLen + 1] == '\0') {
|
|
isDriveRoot = true;
|
|
}
|
|
}
|
|
|
|
if (isDriveRoot) {
|
|
const char* entries[1];
|
|
if (Fs::Vfs::VfsReadDir(resolved, entries, 1) < 0) return -1;
|
|
} else {
|
|
Fs::Vfs::BackendFile file = {-1, -1, 0};
|
|
if (Fs::Vfs::OpenBackendFile(resolved, file) < 0) return -1;
|
|
Fs::Vfs::CloseBackendFile(file);
|
|
}
|
|
|
|
int i = 0;
|
|
for (; i < 255 && resolved[i]; i++) proc->cwd[i] = resolved[i];
|
|
proc->cwd[i] = '\0';
|
|
return 0;
|
|
}
|
|
};
|