Kernel: Add a pstat() system call

Not part of C or POSIX, but since there is no procfs right now, I thought it would be nice to have an interface to query process information.
It works like this: you pass the process ID and a pointer to a struct pstat (can be null).
If the process ID is -1, the kernel picks the process with the highest PID.
Then, if the pointer to a pstat struct is not null, the kernel fills it in with the process's information, and returns the process's PID.
This commit is contained in:
apio 2022-10-22 14:26:29 +02:00
parent 31e0f0efed
commit bcdcfc4b45
3 changed files with 52 additions and 2 deletions

View File

@ -23,8 +23,10 @@
#define SYS_waitpid 18
#define SYS_access 19
#define SYS_fstat 20
#define SYS_pstat 21
struct stat;
struct pstat;
namespace Syscall
{
@ -52,3 +54,4 @@ void sys_fork(Context* context);
void sys_waitpid(Context* context, long pid, int* wstatus, int options);
void sys_access(Context* context, const char* path, int amode);
void sys_fstat(Context* context, int fd, struct stat* buf);
void sys_pstat(Context* context, long pid, struct pstat* buf);

View File

@ -32,6 +32,7 @@ void Syscall::entry(Context* context)
case SYS_waitpid: sys_waitpid(context, (long)context->rdi, (int*)context->rsi, (int)context->rdx); break;
case SYS_access: sys_access(context, (const char*)context->rdi, (int)context->rsi); break;
case SYS_fstat: sys_fstat(context, (int)context->rdi, (struct stat*)context->rsi); break;
case SYS_pstat: sys_pstat(context, (long)context->rdi, (struct pstat*)context->rsi); break;
default: context->rax = -ENOSYS; break;
}
VMM::exit_syscall_context();

View File

@ -374,10 +374,10 @@ void Scheduler::task_tick(Context* context)
ASSERT(Interrupts::is_in_handler());
Interrupts::disable();
sched_decrement_sleep_times();
if (sched_current_task->id == 0) return task_yield(context);
sched_current_task->task_time -= frequency;
sched_current_task->cpu_time += frequency;
if (sched_current_task->task_time < 0)
if (sched_current_task->id == 0) return task_yield(context);
if (sched_current_task->task_time <= 0)
{
sched_current_task->task_time = 0;
task_yield(context);
@ -514,3 +514,49 @@ void sys_waitpid(Context* context, long pid, int* wstatus,
child->state = child->Exited;
context->rax = (long)child->id;
}
struct pstat
{
long pt_pid;
long pt_ppid;
char pt_name[128];
int pt_state;
long pt_time;
};
void sys_pstat(Context* context, long pid, struct pstat* buf)
{
Task* task;
if (pid == -1) task = Scheduler::find_by_pid(free_tid - 1);
else if (pid == 0)
task = &idle_task;
else
task = Scheduler::find_by_pid(pid);
if (!task)
{
context->rax = -ESRCH;
return;
}
if (task->state == task->Exited) // we're just waiting for the reaper to reap it
{
context->rax = -ESRCH;
return;
}
if (buf)
{
struct pstat* kpstat = obtain_user_ref(buf);
if (!kpstat)
{
context->rax = -EFAULT;
return;
}
kpstat->pt_pid = task->id;
kpstat->pt_ppid = task->ppid;
kpstat->pt_state = (int)task->state;
kpstat->pt_time = (long)task->cpu_time;
strlcpy(kpstat->pt_name, task->name, sizeof(kpstat->pt_name));
release_user_ref(kpstat);
}
context->rax = task->id;
return;
}