Added the _exit() system call.

exit() will not call _exit() yet, we need support for wait() in the shell.
This commit is contained in:
Jonas 'Sortie' Termansen 2011-11-05 18:52:11 +01:00
parent 09b1252821
commit cfd7648ca9
8 changed files with 136 additions and 10 deletions

View File

@ -45,9 +45,8 @@ typedef int div_t, ldiv_t, lldiv_t;
/* TODO: WEXITSTATUS, WIFEXITED, WIFSIGNALED, WIFSTOPPED, WNOHANG, WSTOPSIG, WTERMSIG, WUNTRACED is missing here */
/* TODO: _Exit(int) is missing here */
void exit(int);
void _Exit(int status);
void free(void*);
void* malloc(size_t);

View File

@ -86,7 +86,6 @@ char* crypt(const char*, const char*);
char* ctermid(char*);
int dup(int);
int dup2(int, int);
void _exit(int);
void encrypt(char [64], int);
int execl(const char*, const char*, ...);
int execle(const char*, const char*, ...);
@ -163,6 +162,7 @@ extern char* optarg;
extern int opterr, optind, optopt;
#endif
void _exit(int);
pid_t fork(void);
pid_t getpid(void);
pid_t getppid(void);

View File

@ -30,6 +30,7 @@ namespace Maxsi
{
namespace Process
{
DEFN_SYSCALL1_VOID(SysExit, 1, int);
DEFN_SYSCALL3(int, SysExecute, 10, const char*, int, const char**);
DEFN_SYSCALL0_VOID(SysPrintPathFiles, 11);
DEFN_SYSCALL0(pid_t, SysFork, 12);
@ -66,16 +67,21 @@ namespace Maxsi
extern "C" void abort() { return Abort(); }
void Exit(int code)
extern "C" void _exit(int status)
{
SysExit(status);
}
DUAL_FUNCTION(void, exit, Exit, (int status))
{
// TODO: Once wait() works and is used in the shell, call _exit!
//_exit(status);
const char* sh = "sh";
const char* argv[] = { sh };
Execute("sh", 1, argv);
while(true);
}
extern "C" void exit(int code) { return Exit(code); }
DUAL_FUNCTION(pid_t, fork, Fork, ())
{
return SysFork();

View File

@ -28,6 +28,7 @@
#include <libmaxsi/sortedlist.h>
#include "thread.h"
#include "process.h"
#include "scheduler.h"
#include "memorymanagement.h"
#include "initrd.h"
#include "elf.h"
@ -345,12 +346,94 @@ namespace Sortix
pidlist->Remove(index);
}
void SysExit(int status)
{
// Status codes can only contain 8 bits according to ISO C and POSIX.
status %= 256;
Process* process = CurrentProcess();
Process* init = Scheduler::GetInitProcess();
if ( process->pid == 0 ) { Panic("System idle process exited"); }
// If the init process terminated successfully, time to halt.
if ( process == init )
{
switch ( status )
{
case 0: CPU::ShutDown();
case 1: CPU::Reboot();
default: PanicF("The init process exited abnormally with status code %u\n", status);
}
}
// Take care of the orphans, so give them to init.
while ( process->firstchild )
{
Process* orphan = process->firstchild;
process->firstchild = orphan->nextsibling;
if ( process->firstchild ) { process->firstchild->prevsibling = NULL; }
orphan->parent = init;
orphan->prevsibling = NULL;
orphan->nextsibling = init->firstchild;
if ( orphan->nextsibling ) { orphan->nextsibling->prevsibling = orphan; }
init->firstchild = orphan;
}
// Remove the current process from the family tree.
if ( !process->prevsibling )
{
process->parent->firstchild = process->nextsibling;
}
else
{
process->prevsibling->nextsibling = process->nextsibling;
}
if ( process->nextsibling )
{
process->nextsibling->prevsibling = process->prevsibling;
}
// TODO: Close all the file descriptors!
// Make all threads belonging to process unrunnable.
for ( Thread* t = process->firstthread; t; t = t->nextsibling )
{
Scheduler::EarlyWakeUp(t);
Scheduler::SetThreadState(t, Thread::State::NONE);
}
// Delete the threads.
while ( process->firstthread )
{
Thread* todelete = process->firstthread;
process->firstthread = process->firstthread->nextsibling;
delete todelete;
}
// Now clean up the address space.
process->ResetAddressSpace();
// TODO: Actually delete the address space. This is a small memory leak
// of a couple pages.
// TODO: Zombification!
delete process;
// And so, the process had vanished from existence. But as fate would
// have it, soon a replacement took its place.
Scheduler::ProcessTerminated(Syscall::InterruptRegs());
Syscall::AsIs();
}
void Process::Init()
{
Syscall::Register(SYSCALL_EXEC, (void*) SysExecute);
Syscall::Register(SYSCALL_FORK, (void*) SysFork);
Syscall::Register(SYSCALL_GETPID, (void*) SysGetPID);
Syscall::Register(SYSCALL_GETPPID, (void*) SysGetParentPID);
Syscall::Register(SYSCALL_EXIT, (void*) SysExit);
nextpidtoallocate = 0;

View File

@ -132,6 +132,12 @@ namespace Sortix
LogEndContextSwitch(currentthread, regs);
}
void ProcessTerminated(CPU::InterruptRegisters* regs)
{
currentthread = dummythread;
Switch(regs);
}
const bool DEBUG_BEGINCTXSWITCH = false;
const bool DEBUG_CTXSWITCH = false;
const bool DEBUG_ENDCTXSWITCH = false;
@ -240,6 +246,32 @@ namespace Sortix
}
}
void EarlyWakeUp(Thread* thread)
{
uintmax_t now = Time::MicrosecondsSinceBoot();
if ( thread->sleepuntil < now ) { return; }
thread->sleepuntil = now;
SetThreadState(thread, Thread::State::RUNNABLE);
if ( firstsleepingthread == thread )
{
firstsleepingthread = thread->nextsleepingthread;
thread->nextsleepingthread = NULL;
return;
}
for ( Thread* tmp = firstsleepingthread; tmp->nextsleepingthread != NULL; tmp = tmp->nextsleepingthread )
{
if ( tmp->nextsleepingthread == thread )
{
tmp->nextsleepingthread = thread->nextsleepingthread;
thread->nextsleepingthread = NULL;
return;
}
}
}
void WakeSleeping()
{
uintmax_t now = Time::MicrosecondsSinceBoot();
@ -247,7 +279,9 @@ namespace Sortix
while ( firstsleepingthread && firstsleepingthread->sleepuntil < now )
{
SetThreadState(firstsleepingthread, Thread::State::RUNNABLE);
firstsleepingthread = firstsleepingthread->nextsleepingthread;
Thread* next = firstsleepingthread->nextsleepingthread;
firstsleepingthread->nextsleepingthread = NULL;
firstsleepingthread = next;
}
}

View File

@ -34,6 +34,7 @@ namespace Sortix
void Init();
void MainLoop() SORTIX_NORETURN;
void Switch(CPU::InterruptRegisters* regs);
void ProcessTerminated(CPU::InterruptRegisters* regs);
void SetIdleThread(Thread* thread);
void SetDummyThreadOwner(Process* process);
void SetInitProcess(Process* init);
@ -42,6 +43,7 @@ namespace Sortix
void SetThreadState(Thread* thread, Thread::State state);
Thread::State GetThreadState(Thread* thread);
void PutThreadToSleep(Thread* thread, uintmax_t usecs);
void EarlyWakeUp(Thread* thread);
void SigIntHack();
}

View File

@ -39,8 +39,7 @@ namespace Sortix
prevsibling = NULL;
nextsibling = NULL;
sleepuntil = 0;
nextsleepingthread = 0;
schedulerlist = NULL;
nextsleepingthread = NULL;
schedulerlistprev = NULL;
schedulerlistnext = NULL;
state = NONE;
@ -60,11 +59,15 @@ namespace Sortix
ready = false;
stackpos = forkfrom->stackpos;
stacksize = forkfrom->stacksize;
nextsleepingthread = NULL;
schedulerlistprev = NULL;
schedulerlistnext = NULL;
}
Thread::~Thread()
{
ASSERT(CurrentProcess() == process);
ASSERT(nextsleepingthread == NULL);
Memory::UnmapRangeUser(stackpos, stacksize);
}

View File

@ -57,7 +57,6 @@ namespace Sortix
// These are some things used internally by the scheduler and should not be
// touched by anything but it. Consider it private.
public:
Thread** schedulerlist;
Thread* schedulerlistprev;
Thread* schedulerlistnext;
State state;