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 "errno.h"
|
||||||
#include "memory/VMM.h"
|
#include "memory/VMM.h"
|
||||||
|
#include "sys/UserMemory.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
|
|
||||||
void sys_exit(Context* context, int status)
|
void sys_exit(Context* context, int status)
|
||||||
@ -21,23 +22,3 @@ void sys_sleep(Context* context, uint64_t ms)
|
|||||||
task->state = task->Sleeping;
|
task->state = task->Sleeping;
|
||||||
Scheduler::task_yield(context);
|
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 "panic/Panic.h"
|
||||||
#include "std/stdlib.h"
|
#include "std/stdlib.h"
|
||||||
#include "std/string.h"
|
#include "std/string.h"
|
||||||
|
#include "sys/UserMemory.h"
|
||||||
#include "sys/elf/ELFLoader.h"
|
#include "sys/elf/ELFLoader.h"
|
||||||
#include "thread/PIT.h"
|
#include "thread/PIT.h"
|
||||||
#include "thread/Task.h"
|
#include "thread/Task.h"
|
||||||
@ -423,3 +424,50 @@ Task* Scheduler::current_task()
|
|||||||
{
|
{
|
||||||
return sched_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