Kernel: waitpid: support -1 as PID (wait for any child)
This commit is contained in:
parent
48d4a5910a
commit
a29f7f8df2
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user