Luna/kernel/src/sys/pstat.cpp

42 lines
1.5 KiB
C++

#include "memory/MemoryManager.h"
#include "sys/Syscall.h"
#include "thread/Scheduler.h"
#include <bits/pstat.h>
static void set_timespec(struct timespec& ts, u64 ticks)
{
ts.tv_sec = ticks / 1000;
ts.tv_nsec = (ticks % 1000) * 1000 * 1000;
}
Result<u64> sys_pstat(Registers*, SyscallArgs args)
{
pid_t pid = (pid_t)args[0];
struct process* ps = (struct process*)args[1];
// If pid == -1, return the PID of the last spawned thread.
if (pid == -1) return g_threads.expect_last()->id;
auto* thread = TRY(Result<Thread*>::from_option(Scheduler::find_by_pid(pid), ESRCH));
struct process proc;
proc.ps_pid = (pid_t)thread->id;
proc.ps_ppid = thread->parent ? (pid_t)thread->parent->id : 0;
proc.ps_uid = thread->auth.uid;
proc.ps_gid = thread->auth.gid;
proc.ps_euid = thread->auth.euid;
proc.ps_egid = thread->auth.egid;
proc.ps_state = (int)thread->state;
proc.ps_flags = thread->is_kernel ? PS_FLAG_KRNL : 0;
set_timespec(proc.ps_time, thread->user_ticks_self + thread->kernel_ticks_self);
set_timespec(proc.ps_ktime, thread->kernel_ticks_self);
set_timespec(proc.ps_utime, thread->kernel_ticks_children);
strlcpy(proc.ps_name, thread->name.chars(), sizeof(proc.ps_name));
strlcpy(proc.ps_cwd, thread->current_directory_path.is_empty() ? "/" : thread->current_directory_path.chars(),
sizeof(proc.ps_cwd));
if (!MemoryManager::copy_to_user_typed(ps, &proc)) return err(EFAULT);
return (u64)pid;
}