Kernel: waitpid: support -1 as PID (wait for any child)

This commit is contained in:
apio 2022-10-19 17:15:30 +02:00
parent 48d4a5910a
commit a29f7f8df2
2 changed files with 49 additions and 20 deletions

View File

@ -1,5 +1,6 @@
#include "errno.h"
#include "memory/VMM.h"
#include "sys/UserMemory.h"
#include "thread/Scheduler.h"
void sys_exit(Context* context, int status)
@ -21,23 +22,3 @@ void sys_sleep(Context* context, uint64_t ms)
task->state = task->Sleeping;
Scheduler::task_yield(context);
}
void sys_waitpid(Context* context, long pid, int* wstatus,
int) // FIXME: Use the value in options and block if WNOHANG has not been specified.
{
Task* child = Scheduler::find_by_pid(pid); // FIXME: Wait for any child process if PID is -1.
if (!child)
{
context->rax = -ESRCH;
return;
}
if (child->state != child->Dying) // FIXME: This should block if WNOHANG has not been specified.
{
context->rax = 0;
return;
}
uint64_t phys = VMM::get_physical((uint64_t)wstatus);
if (phys != (uint64_t)-1) { *(int*)phys = (int)(child->exit_status & 0xff); }
child->state = child->Exited;
context->rax = (long)child->id;
}

View File

@ -13,6 +13,7 @@
#include "panic/Panic.h"
#include "std/stdlib.h"
#include "std/string.h"
#include "sys/UserMemory.h"
#include "sys/elf/ELFLoader.h"
#include "thread/PIT.h"
#include "thread/Task.h"
@ -423,3 +424,50 @@ Task* Scheduler::current_task()
{
return sched_current_task;
}
void sys_waitpid(Context* context, long pid, int* wstatus,
int) // FIXME: Use the value in options and block if WNOHANG has not been specified.
{
Task* child = nullptr;
if (pid == -1)
{
sched_for_each_task([&](Task* task) {
if (task->state == task->Dying && task->ppid == sched_current_task->id)
{
child = task;
return false;
}
return true;
});
if (!child)
{
context->rax = 0; // No child has exited, let's return 0.
return;
}
}
else
{
child = Scheduler::find_by_pid(pid);
if (!child)
{
context->rax = -ESRCH;
return;
}
}
if (child->state != child->Dying) // FIXME: This should block if WNOHANG has not been specified.
{
context->rax = 0;
return;
}
if (wstatus)
{
int* kwstatus = obtain_user_ref(wstatus);
if (kwstatus)
{
*kwstatus = (int)(child->exit_status & 0xff);
release_user_ref(kwstatus);
}
}
child->state = child->Exited;
context->rax = (long)child->id;
}