diff --git a/kernel/src/sys/sched.cpp b/kernel/src/sys/sched.cpp index 487239d7..2e197b01 100644 --- a/kernel/src/sys/sched.cpp +++ b/kernel/src/sys/sched.cpp @@ -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) @@ -20,24 +21,4 @@ void sys_sleep(Context* context, uint64_t ms) task->task_sleep = 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; } \ No newline at end of file diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 0c40af00..a8c0df88 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -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" @@ -422,4 +423,51 @@ void Scheduler::sleep(unsigned long ms) 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; } \ No newline at end of file