From 1506331872d713eea24e775c8be34fe83233fb27 Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 18 May 2023 21:48:47 +0200 Subject: [PATCH] kernel+libc: Add the pstat() system call Luna-specific, but I like it. --- kernel/CMakeLists.txt | 1 + kernel/src/sys/pstat.cpp | 41 ++++++++++++++++++++++++++++++++++ libc/CMakeLists.txt | 1 + libc/include/bits/pstat.h | 34 ++++++++++++++++++++++++++++ libc/include/sys/pstat.h | 23 +++++++++++++++++++ libc/src/sys/pstat.cpp | 26 +++++++++++++++++++++ libluna/include/luna/Syscall.h | 2 +- 7 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 kernel/src/sys/pstat.cpp create mode 100644 libc/include/bits/pstat.h create mode 100644 libc/include/sys/pstat.h create mode 100644 libc/src/sys/pstat.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index ff1e593c..e7f79232 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -31,6 +31,7 @@ set(SOURCES src/sys/file.cpp src/sys/id.cpp src/sys/mkdir.cpp + src/sys/pstat.cpp src/sys/waitpid.cpp src/sys/getdents.cpp src/sys/stat.cpp diff --git a/kernel/src/sys/pstat.cpp b/kernel/src/sys/pstat.cpp new file mode 100644 index 00000000..5e9fd584 --- /dev/null +++ b/kernel/src/sys/pstat.cpp @@ -0,0 +1,41 @@ +#include "memory/MemoryManager.h" +#include "sys/Syscall.h" +#include "thread/Scheduler.h" +#include + +static void set_timespec(struct timespec& ts, u64 ticks) +{ + ts.tv_sec = ticks / 1000; + ts.tv_nsec = (ticks % 1000) * 1000 * 1000; +} + +Result 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::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->ticks); + set_timespec(proc.ps_ktime, thread->ticks_in_kernel); + set_timespec(proc.ps_utime, thread->ticks_in_user); + 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; +} diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index e781678e..1123601d 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -25,6 +25,7 @@ set(SOURCES src/sys/ioctl.cpp src/sys/utsname.cpp src/sys/mount.cpp + src/sys/pstat.cpp ) if(${LUNA_ARCH} STREQUAL "x86_64") diff --git a/libc/include/bits/pstat.h b/libc/include/bits/pstat.h new file mode 100644 index 00000000..043b3136 --- /dev/null +++ b/libc/include/bits/pstat.h @@ -0,0 +1,34 @@ +/* bits/pstat.h: The process structure and flags for the pstat() system call. */ + +#ifndef _BITS_PSTAT_H +#define _BITS_PSTAT_H + +#include +#include + +#define PS_IDLE 1 +#define PS_RUNNABLE 2 +#define PS_SLEEPING 3 +#define PS_WAITING 4 +#define PS_ENDED 5 + +#define PS_FLAG_KRNL 1 + +struct process +{ + pid_t ps_pid; + pid_t ps_ppid; + uid_t ps_uid; + uid_t ps_euid; + gid_t ps_gid; + gid_t ps_egid; + int ps_state; + int ps_flags; + struct timespec ps_time; + struct timespec ps_ktime; + struct timespec ps_utime; + char ps_name[129]; + char ps_cwd[256]; +}; + +#endif diff --git a/libc/include/sys/pstat.h b/libc/include/sys/pstat.h new file mode 100644 index 00000000..6d278b28 --- /dev/null +++ b/libc/include/sys/pstat.h @@ -0,0 +1,23 @@ +/* sys/pstat.h: The pstat() system call. */ + +#ifndef _SYS_PSTAT_H +#define _SYS_PSTAT_H + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* Retrieve information about a process. */ + pid_t pstat(pid_t pid, struct process* ps); + + /* Get a string representing a process' state. */ + const char* ps_state_name(int state); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libc/src/sys/pstat.cpp b/libc/src/sys/pstat.cpp new file mode 100644 index 00000000..9aa97fae --- /dev/null +++ b/libc/src/sys/pstat.cpp @@ -0,0 +1,26 @@ +#include +#include +#include +#include + +extern "C" +{ + pid_t pstat(pid_t pid, struct process* ps) + { + long rc = syscall(SYS_pstat, pid, ps); + __errno_return(rc, pid_t); + } + + const char* ps_state_name(int state) + { + switch (state) + { + case PS_IDLE: return "Idle"; + case PS_RUNNABLE: return "Running"; + case PS_SLEEPING: return "Sleeping"; + case PS_WAITING: return "Waiting"; + case PS_ENDED: return "Zombie"; + default: return "???"; + } + } +} diff --git a/libluna/include/luna/Syscall.h b/libluna/include/luna/Syscall.h index 763ed8e5..a219df64 100644 --- a/libluna/include/luna/Syscall.h +++ b/libluna/include/luna/Syscall.h @@ -5,7 +5,7 @@ _e(lseek) _e(mkdir) _e(execve) _e(fork) _e(waitpid) _e(getppid) _e(fcntl) _e(getdents) _e(getuid) _e(geteuid) \ _e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(fchmodat) _e(fchownat) _e(ioctl) \ _e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) _e(mount) \ - _e(umount) + _e(umount) _e(pstat) enum Syscalls {