Added the wait() and waitpid() system call.
This commit is contained in:
parent
851ee78903
commit
024f1581ea
|
@ -41,6 +41,7 @@ c/h/features.h \
|
||||||
c/h/string.h \
|
c/h/string.h \
|
||||||
c/h/sys/stat.h \
|
c/h/sys/stat.h \
|
||||||
c/h/sys/types.h \
|
c/h/sys/types.h \
|
||||||
|
c/h/sys/wait.h \
|
||||||
c/h/stdio.h \
|
c/h/stdio.h \
|
||||||
|
|
||||||
COMMONOBJS=c++.o memory.o string.o error.o format.o
|
COMMONOBJS=c++.o memory.o string.o error.o format.o
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||||
|
|
||||||
|
This file is part of LibMaxsi.
|
||||||
|
|
||||||
|
LibMaxsi is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
LibMaxsi is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
sys/wait.h
|
||||||
|
Declarations for waiting.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
// TODO: Make this header comply with POSIX-1.2008
|
||||||
|
|
||||||
|
#ifndef _SYS_WAIT_H
|
||||||
|
#define _SYS_WAIT_H 1
|
||||||
|
|
||||||
|
#include <features.h>
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
@include(pid_t.h)
|
||||||
|
|
||||||
|
/* TODO: These are not implemented in libmaxsi/sortix yet. */
|
||||||
|
#ifndef SORTIX_UNIMPLEMENTED
|
||||||
|
int waitid(idtype_t, id_t, siginfo_t*, int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pid_t wait(int* stat_loc);
|
||||||
|
pid_t waitpid(pid_t pid, int *stat_loc, int options);
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -38,6 +38,7 @@ namespace Maxsi
|
||||||
DEFN_SYSCALL0(pid_t, SysGetParentPID, 14);
|
DEFN_SYSCALL0(pid_t, SysGetParentPID, 14);
|
||||||
DEFN_SYSCALL2(int, SysGetFileInfo, 15, size_t, FileInfo*);
|
DEFN_SYSCALL2(int, SysGetFileInfo, 15, size_t, FileInfo*);
|
||||||
DEFN_SYSCALL0(size_t, SysGetNumFiles, 16);
|
DEFN_SYSCALL0(size_t, SysGetNumFiles, 16);
|
||||||
|
DEFN_SYSCALL3(pid_t, SysWait, 17, pid_t, int*, int);
|
||||||
|
|
||||||
int Execute(const char* filepath, int argc, const char** argv)
|
int Execute(const char* filepath, int argc, const char** argv)
|
||||||
{
|
{
|
||||||
|
@ -96,6 +97,16 @@ namespace Maxsi
|
||||||
{
|
{
|
||||||
return SysGetParentPID();
|
return SysGetParentPID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" pid_t waitpid(pid_t pid, int* status, int options)
|
||||||
|
{
|
||||||
|
return SysWait(pid, status, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" pid_t wait(int* status)
|
||||||
|
{
|
||||||
|
return waitpid(-1, status, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,8 +93,10 @@ namespace Sortix
|
||||||
prevsibling = NULL;
|
prevsibling = NULL;
|
||||||
nextsibling = NULL;
|
nextsibling = NULL;
|
||||||
firstchild = NULL;
|
firstchild = NULL;
|
||||||
|
zombiechild = NULL;
|
||||||
firstthread = NULL;
|
firstthread = NULL;
|
||||||
mmapfrom = 0x80000000UL;
|
mmapfrom = 0x80000000UL;
|
||||||
|
exitstatus = -1;
|
||||||
pid = AllocatePID();
|
pid = AllocatePID();
|
||||||
Put(this);
|
Put(this);
|
||||||
}
|
}
|
||||||
|
@ -346,12 +348,26 @@ namespace Sortix
|
||||||
pidlist->Remove(index);
|
pidlist->Remove(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Process::OnChildProcessExit(Process* process)
|
||||||
|
{
|
||||||
|
ASSERT(process->parent == this);
|
||||||
|
|
||||||
|
for ( Thread* thread = firstthread; thread; thread = thread->nextsibling )
|
||||||
|
{
|
||||||
|
if ( thread->onchildprocessexit )
|
||||||
|
{
|
||||||
|
thread->onchildprocessexit(thread, process);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SysExit(int status)
|
void SysExit(int status)
|
||||||
{
|
{
|
||||||
// Status codes can only contain 8 bits according to ISO C and POSIX.
|
// Status codes can only contain 8 bits according to ISO C and POSIX.
|
||||||
status %= 256;
|
status %= 256;
|
||||||
|
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
|
Process* parent = process->parent;
|
||||||
Process* init = Scheduler::GetInitProcess();
|
Process* init = Scheduler::GetInitProcess();
|
||||||
|
|
||||||
if ( process->pid == 0 ) { Panic("System idle process exited"); }
|
if ( process->pid == 0 ) { Panic("System idle process exited"); }
|
||||||
|
@ -383,7 +399,7 @@ namespace Sortix
|
||||||
// Remove the current process from the family tree.
|
// Remove the current process from the family tree.
|
||||||
if ( !process->prevsibling )
|
if ( !process->prevsibling )
|
||||||
{
|
{
|
||||||
process->parent->firstchild = process->nextsibling;
|
parent->firstchild = process->nextsibling;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -418,8 +434,13 @@ namespace Sortix
|
||||||
// TODO: Actually delete the address space. This is a small memory leak
|
// TODO: Actually delete the address space. This is a small memory leak
|
||||||
// of a couple pages.
|
// of a couple pages.
|
||||||
|
|
||||||
// TODO: Zombification!
|
process->exitstatus = status;
|
||||||
delete process;
|
process->nextsibling = parent->zombiechild;
|
||||||
|
if ( parent->zombiechild ) { parent->zombiechild->prevsibling = process; }
|
||||||
|
parent->zombiechild = process;
|
||||||
|
|
||||||
|
// Notify the parent process that the child has become a zombie.
|
||||||
|
parent->OnChildProcessExit(process);
|
||||||
|
|
||||||
// And so, the process had vanished from existence. But as fate would
|
// And so, the process had vanished from existence. But as fate would
|
||||||
// have it, soon a replacement took its place.
|
// have it, soon a replacement took its place.
|
||||||
|
@ -427,6 +448,84 @@ namespace Sortix
|
||||||
Syscall::AsIs();
|
Syscall::AsIs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SysWait_t
|
||||||
|
{
|
||||||
|
union { size_t align1; pid_t pid; };
|
||||||
|
union { size_t align2; int* status; };
|
||||||
|
union { size_t align3; int options; };
|
||||||
|
};
|
||||||
|
|
||||||
|
STATIC_ASSERT(sizeof(SysWait_t) <= sizeof(Thread::scstate));
|
||||||
|
|
||||||
|
void SysWaitCallback(Thread* thread, Process* exitee)
|
||||||
|
{
|
||||||
|
// See if this process matches what we are looking for.
|
||||||
|
SysWait_t* state = (SysWait_t*) thread->scstate;
|
||||||
|
if ( state->pid != -1 && state->pid != exitee->pid ) { return; }
|
||||||
|
|
||||||
|
thread->onchildprocessexit = NULL;
|
||||||
|
|
||||||
|
Syscall::ScheduleResumption(thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t SysWait(pid_t pid, int* status, int options)
|
||||||
|
{
|
||||||
|
Thread* thread = CurrentThread();
|
||||||
|
Process* process = thread->process;
|
||||||
|
|
||||||
|
if ( pid != -1 )
|
||||||
|
{
|
||||||
|
Process* waitingfor = Process::Get(pid);
|
||||||
|
if ( !waitingfor ) { return -1; /* TODO: ECHILD*/ }
|
||||||
|
if ( waitingfor->parent != process ) { return -1; /* TODO: ECHILD*/ }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find any zombie children matching the search description.
|
||||||
|
for ( Process* zombie = process->zombiechild; zombie; zombie = zombie->nextsibling )
|
||||||
|
{
|
||||||
|
if ( pid != -1 && pid != zombie->pid ) { continue; }
|
||||||
|
|
||||||
|
pid = zombie->pid;
|
||||||
|
// TODO: Validate that status is a valid user-space int!
|
||||||
|
if ( status ) { *status = zombie->exitstatus; }
|
||||||
|
|
||||||
|
if ( zombie == process->zombiechild )
|
||||||
|
{
|
||||||
|
process->zombiechild = zombie->nextsibling;
|
||||||
|
if ( zombie->nextsibling ) { zombie->nextsibling->prevsibling = NULL; }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
zombie->prevsibling->nextsibling = zombie->nextsibling;
|
||||||
|
if ( zombie->nextsibling ) { zombie->nextsibling->prevsibling = zombie->prevsibling; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// And so, the process was fully deleted.
|
||||||
|
delete zombie;
|
||||||
|
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The process needs to have children, otherwise we are waiting for
|
||||||
|
// nothing to happen.
|
||||||
|
if ( !process->firstchild ) { return -1; /* TODO: ECHILD*/ }
|
||||||
|
|
||||||
|
// Resumes this system call when the wait condition has been met.
|
||||||
|
thread->onchildprocessexit = SysWaitCallback;
|
||||||
|
|
||||||
|
// Resume the system call with these parameters.
|
||||||
|
thread->scfunc = (void*) SysWait;
|
||||||
|
SysWait_t* state = (SysWait_t*) thread->scstate;
|
||||||
|
state->pid = pid;
|
||||||
|
state->status = status;
|
||||||
|
state->options = options;
|
||||||
|
thread->scsize = sizeof(SysWait_t);
|
||||||
|
|
||||||
|
// Now go do something else.
|
||||||
|
Syscall::Incomplete();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void Process::Init()
|
void Process::Init()
|
||||||
{
|
{
|
||||||
Syscall::Register(SYSCALL_EXEC, (void*) SysExecute);
|
Syscall::Register(SYSCALL_EXEC, (void*) SysExecute);
|
||||||
|
@ -434,6 +533,7 @@ namespace Sortix
|
||||||
Syscall::Register(SYSCALL_GETPID, (void*) SysGetPID);
|
Syscall::Register(SYSCALL_GETPID, (void*) SysGetPID);
|
||||||
Syscall::Register(SYSCALL_GETPPID, (void*) SysGetParentPID);
|
Syscall::Register(SYSCALL_GETPPID, (void*) SysGetParentPID);
|
||||||
Syscall::Register(SYSCALL_EXIT, (void*) SysExit);
|
Syscall::Register(SYSCALL_EXIT, (void*) SysExit);
|
||||||
|
Syscall::Register(SYSCALL_WAIT, (void*) SysWait);
|
||||||
|
|
||||||
nextpidtoallocate = 0;
|
nextpidtoallocate = 0;
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ namespace Sortix
|
||||||
|
|
||||||
public:
|
public:
|
||||||
addr_t addrspace;
|
addr_t addrspace;
|
||||||
|
int exitstatus;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
@ -76,6 +77,7 @@ namespace Sortix
|
||||||
Process* prevsibling;
|
Process* prevsibling;
|
||||||
Process* nextsibling;
|
Process* nextsibling;
|
||||||
Process* firstchild;
|
Process* firstchild;
|
||||||
|
Process* zombiechild;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Thread* firstthread;
|
Thread* firstthread;
|
||||||
|
@ -111,6 +113,9 @@ namespace Sortix
|
||||||
public:
|
public:
|
||||||
addr_t AllocVirtualAddr(size_t size);
|
addr_t AllocVirtualAddr(size_t size);
|
||||||
|
|
||||||
|
public:
|
||||||
|
void OnChildProcessExit(Process* process);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Process* Get(pid_t pid);
|
static Process* Get(pid_t pid);
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,8 @@
|
||||||
#define SYSCALL_GETPPID 14
|
#define SYSCALL_GETPPID 14
|
||||||
#define SYSCALL_GET_FILEINFO 15
|
#define SYSCALL_GET_FILEINFO 15
|
||||||
#define SYSCALL_GET_NUM_FILES 16
|
#define SYSCALL_GET_NUM_FILES 16
|
||||||
#define SYSCALL_MAX_NUM 17 /* index of highest constant + 1 */
|
#define SYSCALL_WAIT 17
|
||||||
|
#define SYSCALL_MAX_NUM 18 /* index of highest constant + 1 */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ namespace Sortix
|
||||||
Maxsi::Memory::Set(®isters, 0, sizeof(registers));
|
Maxsi::Memory::Set(®isters, 0, sizeof(registers));
|
||||||
ready = false;
|
ready = false;
|
||||||
scfunc = NULL;
|
scfunc = NULL;
|
||||||
|
ResetCallbacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread::Thread(const Thread* forkfrom)
|
Thread::Thread(const Thread* forkfrom)
|
||||||
|
@ -64,6 +65,12 @@ namespace Sortix
|
||||||
schedulerlistprev = NULL;
|
schedulerlistprev = NULL;
|
||||||
schedulerlistnext = NULL;
|
schedulerlistnext = NULL;
|
||||||
scfunc = NULL;
|
scfunc = NULL;
|
||||||
|
ResetCallbacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Thread::ResetCallbacks()
|
||||||
|
{
|
||||||
|
onchildprocessexit = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread::~Thread()
|
Thread::~Thread()
|
||||||
|
|
|
@ -44,6 +44,7 @@ namespace Sortix
|
||||||
private:
|
private:
|
||||||
Thread();
|
Thread();
|
||||||
Thread(const Thread* forkfrom);
|
Thread(const Thread* forkfrom);
|
||||||
|
void ResetCallbacks();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~Thread();
|
~Thread();
|
||||||
|
@ -88,6 +89,9 @@ namespace Sortix
|
||||||
void* scfunc;
|
void* scfunc;
|
||||||
size_t scsize;
|
size_t scsize;
|
||||||
size_t scstate[8];
|
size_t scstate[8];
|
||||||
|
|
||||||
|
public:
|
||||||
|
void (*onchildprocessexit)(Thread*, Process*);
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue