Update sortix/process.cpp coding style.
This commit is contained in:
parent
8d420c9de7
commit
2cb3f2860a
|
@ -22,45 +22,46 @@
|
||||||
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sortix/clock.h>
|
||||||
|
#include <sortix/fcntl.h>
|
||||||
|
#include <sortix/fork.h>
|
||||||
|
#include <sortix/mman.h>
|
||||||
|
#include <sortix/signal.h>
|
||||||
|
#include <sortix/stat.h>
|
||||||
|
#include <sortix/unistd.h>
|
||||||
|
#include <sortix/wait.h>
|
||||||
|
|
||||||
#include <sortix/kernel/platform.h>
|
#include <sortix/kernel/platform.h>
|
||||||
#include <sortix/kernel/kthread.h>
|
|
||||||
#include <sortix/kernel/refcount.h>
|
|
||||||
#include <sortix/kernel/ioctx.h>
|
|
||||||
#include <sortix/kernel/copy.h>
|
#include <sortix/kernel/copy.h>
|
||||||
#include <sortix/kernel/descriptor.h>
|
#include <sortix/kernel/descriptor.h>
|
||||||
#include <sortix/kernel/dtable.h>
|
#include <sortix/kernel/dtable.h>
|
||||||
#include <sortix/kernel/mtable.h>
|
#include <sortix/kernel/ioctx.h>
|
||||||
#include <sortix/kernel/worker.h>
|
#include <sortix/kernel/kthread.h>
|
||||||
#include <sortix/kernel/memorymanagement.h>
|
#include <sortix/kernel/memorymanagement.h>
|
||||||
#include <sortix/kernel/string.h>
|
#include <sortix/kernel/mtable.h>
|
||||||
#include <sortix/kernel/syscall.h>
|
|
||||||
#include <sortix/kernel/sortedlist.h>
|
|
||||||
#include <sortix/kernel/scheduler.h>
|
|
||||||
#include <sortix/kernel/symbol.h>
|
|
||||||
#include <sortix/kernel/process.h>
|
#include <sortix/kernel/process.h>
|
||||||
|
#include <sortix/kernel/refcount.h>
|
||||||
|
#include <sortix/kernel/scheduler.h>
|
||||||
|
#include <sortix/kernel/sortedlist.h>
|
||||||
|
#include <sortix/kernel/string.h>
|
||||||
|
#include <sortix/kernel/symbol.h>
|
||||||
|
#include <sortix/kernel/syscall.h>
|
||||||
#include <sortix/kernel/thread.h>
|
#include <sortix/kernel/thread.h>
|
||||||
#include <sortix/kernel/time.h>
|
#include <sortix/kernel/time.h>
|
||||||
|
#include <sortix/kernel/worker.h>
|
||||||
|
|
||||||
#include <sortix/clock.h>
|
|
||||||
#include <sortix/signal.h>
|
|
||||||
#include <sortix/unistd.h>
|
|
||||||
#include <sortix/fcntl.h>
|
|
||||||
#include <sortix/stat.h>
|
|
||||||
#include <sortix/fork.h>
|
|
||||||
#include <sortix/mman.h>
|
|
||||||
#include <sortix/wait.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "initrd.h"
|
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
|
#include "initrd.h"
|
||||||
|
|
||||||
namespace Sortix
|
namespace Sortix {
|
||||||
|
|
||||||
|
bool ProcessSegment::Intersects(ProcessSegment* segments)
|
||||||
{
|
{
|
||||||
bool ProcessSegment::Intersects(ProcessSegment* segments)
|
|
||||||
{
|
|
||||||
for ( ProcessSegment* tmp = segments; tmp != NULL; tmp = tmp->next )
|
for ( ProcessSegment* tmp = segments; tmp != NULL; tmp = tmp->next )
|
||||||
{
|
{
|
||||||
if ( tmp->position < position + size &&
|
if ( tmp->position < position + size &&
|
||||||
|
@ -73,10 +74,10 @@ namespace Sortix
|
||||||
if ( next ) { return next->Intersects(segments); }
|
if ( next ) { return next->Intersects(segments); }
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessSegment* ProcessSegment::Fork()
|
ProcessSegment* ProcessSegment::Fork()
|
||||||
{
|
{
|
||||||
ProcessSegment* nextclone = NULL;
|
ProcessSegment* nextclone = NULL;
|
||||||
if ( next )
|
if ( next )
|
||||||
{
|
{
|
||||||
|
@ -104,10 +105,10 @@ namespace Sortix
|
||||||
clone->size = size;
|
clone->size = size;
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
Process::Process()
|
Process::Process()
|
||||||
{
|
{
|
||||||
string_table = NULL;
|
string_table = NULL;
|
||||||
string_table_length = 0;
|
string_table_length = 0;
|
||||||
symbol_table = NULL;
|
symbol_table = NULL;
|
||||||
|
@ -140,10 +141,10 @@ namespace Sortix
|
||||||
Time::InitializeProcessClocks(this);
|
Time::InitializeProcessClocks(this);
|
||||||
alarm_timer.Attach(Time::GetClock(CLOCK_MONOTONIC));
|
alarm_timer.Attach(Time::GetClock(CLOCK_MONOTONIC));
|
||||||
Put(this);
|
Put(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Process::~Process()
|
Process::~Process()
|
||||||
{
|
{
|
||||||
delete[] string_table;
|
delete[] string_table;
|
||||||
delete[] symbol_table;
|
delete[] symbol_table;
|
||||||
if ( alarm_timer.IsAttached() )
|
if ( alarm_timer.IsAttached() )
|
||||||
|
@ -160,30 +161,30 @@ namespace Sortix
|
||||||
assert(!root);
|
assert(!root);
|
||||||
|
|
||||||
Remove(this);
|
Remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::BootstrapTables(Ref<DescriptorTable> dtable, Ref<MountTable> mtable)
|
void Process::BootstrapTables(Ref<DescriptorTable> dtable, Ref<MountTable> mtable)
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptrlock);
|
||||||
assert(!this->dtable);
|
assert(!this->dtable);
|
||||||
assert(!this->mtable);
|
assert(!this->mtable);
|
||||||
this->dtable = dtable;
|
this->dtable = dtable;
|
||||||
this->mtable = mtable;
|
this->mtable = mtable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::BootstrapDirectories(Ref<Descriptor> root)
|
void Process::BootstrapDirectories(Ref<Descriptor> root)
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptrlock);
|
||||||
assert(!this->root);
|
assert(!this->root);
|
||||||
assert(!this->cwd);
|
assert(!this->cwd);
|
||||||
this->root = root;
|
this->root = root;
|
||||||
this->cwd = root;
|
this->cwd = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process__OnLastThreadExit(void* user);
|
void Process__OnLastThreadExit(void* user);
|
||||||
|
|
||||||
void Process::OnThreadDestruction(Thread* thread)
|
void Process::OnThreadDestruction(Thread* thread)
|
||||||
{
|
{
|
||||||
assert(thread->process == this);
|
assert(thread->process == this);
|
||||||
kthread_mutex_lock(&threadlock);
|
kthread_mutex_lock(&threadlock);
|
||||||
if ( thread->prevsibling )
|
if ( thread->prevsibling )
|
||||||
|
@ -202,41 +203,41 @@ namespace Sortix
|
||||||
// we handle the situation by killing ourselves.
|
// we handle the situation by killing ourselves.
|
||||||
if ( !threadsleft )
|
if ( !threadsleft )
|
||||||
ScheduleDeath();
|
ScheduleDeath();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::ScheduleDeath()
|
void Process::ScheduleDeath()
|
||||||
{
|
{
|
||||||
// All our threads must have exited at this point.
|
// All our threads must have exited at this point.
|
||||||
assert(!firstthread);
|
assert(!firstthread);
|
||||||
Worker::Schedule(Process__OnLastThreadExit, this);
|
Worker::Schedule(Process__OnLastThreadExit, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Useful for killing a partially constructed process without waiting for
|
// Useful for killing a partially constructed process without waiting for
|
||||||
// it to die and garbage collect its zombie. It is not safe to access this
|
// it to die and garbage collect its zombie. It is not safe to access this
|
||||||
// process after this call as another thread may garbage collect it.
|
// process after this call as another thread may garbage collect it.
|
||||||
void Process::AbortConstruction()
|
void Process::AbortConstruction()
|
||||||
{
|
{
|
||||||
nozombify = true;
|
nozombify = true;
|
||||||
ScheduleDeath();
|
ScheduleDeath();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process__OnLastThreadExit(void* user)
|
void Process__OnLastThreadExit(void* user)
|
||||||
{
|
{
|
||||||
return ((Process*) user)->OnLastThreadExit();
|
return ((Process*) user)->OnLastThreadExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::OnLastThreadExit()
|
void Process::OnLastThreadExit()
|
||||||
{
|
{
|
||||||
LastPrayer();
|
LastPrayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SwitchCurrentAddrspace(addr_t addrspace, void* user)
|
static void SwitchCurrentAddrspace(addr_t addrspace, void* user)
|
||||||
{
|
{
|
||||||
((Thread*) user)->SwitchAddressSpace(addrspace);
|
((Thread*) user)->SwitchAddressSpace(addrspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::DeleteTimers()
|
void Process::DeleteTimers()
|
||||||
{
|
{
|
||||||
for ( timer_t i = 0; i < PROCESS_TIMER_NUM_MAX; i++ )
|
for ( timer_t i = 0; i < PROCESS_TIMER_NUM_MAX; i++ )
|
||||||
{
|
{
|
||||||
if ( user_timers[i].timer.IsAttached() )
|
if ( user_timers[i].timer.IsAttached() )
|
||||||
|
@ -245,10 +246,10 @@ namespace Sortix
|
||||||
user_timers[i].timer.Detach();
|
user_timers[i].timer.Detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::LastPrayer()
|
void Process::LastPrayer()
|
||||||
{
|
{
|
||||||
assert(this);
|
assert(this);
|
||||||
// This must never be called twice.
|
// This must never be called twice.
|
||||||
assert(!iszombie);
|
assert(!iszombie);
|
||||||
|
@ -344,10 +345,10 @@ namespace Sortix
|
||||||
// If nobody is waiting for us, then simply commit suicide.
|
// If nobody is waiting for us, then simply commit suicide.
|
||||||
if ( !zombify )
|
if ( !zombify )
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::ResetAddressSpace()
|
void Process::ResetAddressSpace()
|
||||||
{
|
{
|
||||||
assert(Memory::GetAddressSpace() == addrspace);
|
assert(Memory::GetAddressSpace() == addrspace);
|
||||||
ProcessSegment* tmp = segments;
|
ProcessSegment* tmp = segments;
|
||||||
while ( tmp != NULL )
|
while ( tmp != NULL )
|
||||||
|
@ -359,10 +360,10 @@ namespace Sortix
|
||||||
}
|
}
|
||||||
|
|
||||||
segments = NULL;
|
segments = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::NotifyChildExit(Process* child, bool zombify)
|
void Process::NotifyChildExit(Process* child, bool zombify)
|
||||||
{
|
{
|
||||||
kthread_mutex_lock(&childlock);
|
kthread_mutex_lock(&childlock);
|
||||||
|
|
||||||
if ( child->prevsibling )
|
if ( child->prevsibling )
|
||||||
|
@ -387,25 +388,26 @@ namespace Sortix
|
||||||
|
|
||||||
if ( zombify )
|
if ( zombify )
|
||||||
NotifyNewZombies();
|
NotifyNewZombies();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::NotifyNewZombies()
|
void Process::NotifyNewZombies()
|
||||||
{
|
{
|
||||||
ScopedLock lock(&childlock);
|
ScopedLock lock(&childlock);
|
||||||
// TODO: Send SIGCHLD here?
|
// TODO: Send SIGCHLD here?
|
||||||
if ( zombiewaiting )
|
if ( zombiewaiting )
|
||||||
kthread_cond_broadcast(&zombiecond);
|
kthread_cond_broadcast(&zombiecond);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t Process::Wait(pid_t thepid, int* status, int options)
|
pid_t Process::Wait(pid_t thepid, int* status, int options)
|
||||||
{
|
{
|
||||||
// TODO: Process groups are not supported yet.
|
// TODO: Process groups are not supported yet.
|
||||||
if ( thepid < -1 || thepid == 0 ) { errno = ENOSYS; return -1; }
|
if ( thepid < -1 || thepid == 0 ) { errno = ENOSYS; return -1; }
|
||||||
|
|
||||||
ScopedLock lock(&childlock);
|
ScopedLock lock(&childlock);
|
||||||
|
|
||||||
// A process can only wait if it has children.
|
// A process can only wait if it has children.
|
||||||
if ( !firstchild && !zombiechild ) { errno = ECHILD; return -1; }
|
if ( !firstchild && !zombiechild )
|
||||||
|
return errno = ECHILD, -1;
|
||||||
|
|
||||||
// Processes can only wait for their own children to exit.
|
// Processes can only wait for their own children to exit.
|
||||||
if ( 0 < thepid )
|
if ( 0 < thepid )
|
||||||
|
@ -419,7 +421,8 @@ namespace Sortix
|
||||||
for ( Process* p = zombiechild; !found && p; p = p->nextsibling )
|
for ( Process* p = zombiechild; !found && p; p = p->nextsibling )
|
||||||
if ( p->pid == thepid )
|
if ( p->pid == thepid )
|
||||||
found = true;
|
found = true;
|
||||||
if ( !found ) { errno = ECHILD; return -1; }
|
if ( !found )
|
||||||
|
return errno = ECHILD, -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Process* zombie = NULL;
|
Process* zombie = NULL;
|
||||||
|
@ -435,7 +438,8 @@ namespace Sortix
|
||||||
zombiewaiting++;
|
zombiewaiting++;
|
||||||
unsigned long r = kthread_cond_wait_signal(&zombiecond, &childlock);
|
unsigned long r = kthread_cond_wait_signal(&zombiecond, &childlock);
|
||||||
zombiewaiting--;
|
zombiewaiting--;
|
||||||
if ( !r ) { errno = EINTR; return -1; }
|
if ( !r )
|
||||||
|
return errno = EINTR, -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( zombie->prevsibling )
|
if ( zombie->prevsibling )
|
||||||
|
@ -466,15 +470,15 @@ namespace Sortix
|
||||||
delete zombie;
|
delete zombie;
|
||||||
|
|
||||||
return thepid;
|
return thepid;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t SysWait(pid_t pid, int* status, int options)
|
pid_t sys_waitpid(pid_t pid, int* status, int options)
|
||||||
{
|
{
|
||||||
return CurrentProcess()->Wait(pid, status, options);
|
return CurrentProcess()->Wait(pid, status, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::Exit(int status)
|
void Process::Exit(int status)
|
||||||
{
|
{
|
||||||
ScopedLock lock(&threadlock);
|
ScopedLock lock(&threadlock);
|
||||||
// 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.
|
||||||
if ( exitstatus == -1 )
|
if ( exitstatus == -1 )
|
||||||
|
@ -486,25 +490,24 @@ namespace Sortix
|
||||||
// destroyed by SIGKILL once the system call returns.
|
// destroyed by SIGKILL once the system call returns.
|
||||||
for ( Thread* t = firstthread; t; t = t->nextsibling )
|
for ( Thread* t = firstthread; t; t = t->nextsibling )
|
||||||
t->DeliverSignal(SIGKILL);
|
t->DeliverSignal(SIGKILL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SysExit(int status)
|
int sys_exit(int status)
|
||||||
{
|
{
|
||||||
CurrentProcess()->Exit(status);
|
CurrentProcess()->Exit(status);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Process::DeliverSignal(int signum)
|
bool Process::DeliverSignal(int signum)
|
||||||
{
|
{
|
||||||
// TODO: How to handle signals that kill the process?
|
// TODO: How to handle signals that kill the process?
|
||||||
if ( firstthread )
|
if ( firstthread )
|
||||||
return firstthread->DeliverSignal(signum);
|
return firstthread->DeliverSignal(signum);
|
||||||
errno = EINIT;
|
return errno = EINIT, false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void Process::AddChildProcess(Process* child)
|
void Process::AddChildProcess(Process* child)
|
||||||
{
|
{
|
||||||
ScopedLock mylock(&childlock);
|
ScopedLock mylock(&childlock);
|
||||||
ScopedLock itslock(&child->parentlock);
|
ScopedLock itslock(&child->parentlock);
|
||||||
assert(!child->parent);
|
assert(!child->parent);
|
||||||
|
@ -516,63 +519,64 @@ namespace Sortix
|
||||||
if ( firstchild )
|
if ( firstchild )
|
||||||
firstchild->prevsibling = child;
|
firstchild->prevsibling = child;
|
||||||
firstchild = child;
|
firstchild = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<MountTable> Process::GetMTable()
|
Ref<MountTable> Process::GetMTable()
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptrlock);
|
||||||
assert(mtable);
|
assert(mtable);
|
||||||
return mtable;
|
return mtable;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<DescriptorTable> Process::GetDTable()
|
Ref<DescriptorTable> Process::GetDTable()
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptrlock);
|
||||||
assert(dtable);
|
assert(dtable);
|
||||||
return dtable;
|
return dtable;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Descriptor> Process::GetRoot()
|
Ref<Descriptor> Process::GetRoot()
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptrlock);
|
||||||
assert(root);
|
assert(root);
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Descriptor> Process::GetCWD()
|
Ref<Descriptor> Process::GetCWD()
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptrlock);
|
||||||
assert(cwd);
|
assert(cwd);
|
||||||
return cwd;
|
return cwd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::SetRoot(Ref<Descriptor> newroot)
|
void Process::SetRoot(Ref<Descriptor> newroot)
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptrlock);
|
||||||
assert(newroot);
|
assert(newroot);
|
||||||
root = newroot;
|
root = newroot;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::SetCWD(Ref<Descriptor> newcwd)
|
void Process::SetCWD(Ref<Descriptor> newcwd)
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptrlock);
|
||||||
assert(newcwd);
|
assert(newcwd);
|
||||||
cwd = newcwd;
|
cwd = newcwd;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Descriptor> Process::GetDescriptor(int fd)
|
Ref<Descriptor> Process::GetDescriptor(int fd)
|
||||||
{
|
{
|
||||||
ScopedLock lock(&ptrlock);
|
ScopedLock lock(&ptrlock);
|
||||||
assert(dtable);
|
assert(dtable);
|
||||||
return dtable->Get(fd);
|
return dtable->Get(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
Process* Process::Fork()
|
Process* Process::Fork()
|
||||||
{
|
{
|
||||||
assert(CurrentProcess() == this);
|
assert(CurrentProcess() == this);
|
||||||
|
|
||||||
Process* clone = new Process;
|
Process* clone = new Process;
|
||||||
if ( !clone ) { return NULL; }
|
if ( !clone )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
ProcessSegment* clonesegments = NULL;
|
ProcessSegment* clonesegments = NULL;
|
||||||
|
|
||||||
|
@ -657,7 +661,6 @@ namespace Sortix
|
||||||
clone->symbol_table_length = symbol_table_length;
|
clone->symbol_table_length = symbol_table_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( pid == 1)
|
if ( pid == 1)
|
||||||
assert(dtable->Get(1));
|
assert(dtable->Get(1));
|
||||||
|
|
||||||
|
@ -674,10 +677,10 @@ namespace Sortix
|
||||||
}
|
}
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::ResetForExecute()
|
void Process::ResetForExecute()
|
||||||
{
|
{
|
||||||
// TODO: Delete all threads and their stacks.
|
// TODO: Delete all threads and their stacks.
|
||||||
|
|
||||||
string_table_length = 0;
|
string_table_length = 0;
|
||||||
|
@ -688,14 +691,13 @@ namespace Sortix
|
||||||
DeleteTimers();
|
DeleteTimers();
|
||||||
|
|
||||||
ResetAddressSpace();
|
ResetAddressSpace();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Process::Execute(const char* programname, const uint8_t* program,
|
int Process::Execute(const char* programname, const uint8_t* program,
|
||||||
size_t programsize, int argc, const char* const* argv,
|
size_t programsize, int argc, const char* const* argv,
|
||||||
int envc, const char* const* envp,
|
int envc, const char* const* envp,
|
||||||
CPU::InterruptRegisters* regs)
|
CPU::InterruptRegisters* regs)
|
||||||
{
|
{
|
||||||
(void) programname;
|
|
||||||
assert(CurrentProcess() == this);
|
assert(CurrentProcess() == this);
|
||||||
|
|
||||||
char* programname_clone = String::Clone(programname);
|
char* programname_clone = String::Clone(programname);
|
||||||
|
@ -730,7 +732,8 @@ namespace Sortix
|
||||||
|
|
||||||
stackargv[argc] = NULL;
|
stackargv[argc] = NULL;
|
||||||
|
|
||||||
if ( argvsize % 16UL ) { argvsize += 16 - (argvsize % 16UL); }
|
if ( argvsize % 16UL )
|
||||||
|
argvsize += 16 - argvsize % 16UL;
|
||||||
|
|
||||||
// And then move envp onto the stack.
|
// And then move envp onto the stack.
|
||||||
addr_t envppos = argvpos - argvsize - sizeof(char*) * (envc+1);
|
addr_t envppos = argvpos - argvsize - sizeof(char*) * (envc+1);
|
||||||
|
@ -748,7 +751,8 @@ namespace Sortix
|
||||||
|
|
||||||
stackenvp[envc] = NULL;
|
stackenvp[envc] = NULL;
|
||||||
|
|
||||||
if ( envpsize % 16UL ) { envpsize += 16 - (envpsize % 16UL); }
|
if ( envpsize % 16UL )
|
||||||
|
envpsize += 16 - envpsize % 16UL;
|
||||||
|
|
||||||
stackpos = envppos - envpsize;
|
stackpos = envppos - envpsize;
|
||||||
|
|
||||||
|
@ -757,19 +761,19 @@ namespace Sortix
|
||||||
ExecuteCPU(argc, stackargv, envc, stackenvp, stackpos, entry, regs);
|
ExecuteCPU(argc, stackargv, envc, stackenvp, stackpos, entry, regs);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO. This is a hack. Please remove this when execve is moved to another
|
// TODO. This is a hack. Please remove this when execve is moved to another
|
||||||
// file/class, it doesn't belong here, it's a program loader ffs!
|
// file/class, it doesn't belong here, it's a program loader ffs!
|
||||||
Ref<Descriptor> Process::Open(ioctx_t* ctx, const char* path, int flags, mode_t mode)
|
Ref<Descriptor> Process::Open(ioctx_t* ctx, const char* path, int flags, mode_t mode)
|
||||||
{
|
{
|
||||||
// TODO: Locking the root/cwd pointers. How should that be arranged?
|
// TODO: Locking the root/cwd pointers. How should that be arranged?
|
||||||
Ref<Descriptor> dir = path[0] == '/' ? root : cwd;
|
Ref<Descriptor> dir = path[0] == '/' ? root : cwd;
|
||||||
return dir->open(ctx, path, flags, mode);
|
return dir->open(ctx, path, flags, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SysExecVE(const char* _filename, char* const _argv[], char* const _envp[])
|
int sys_execve(const char* _filename, char* const _argv[], char* const _envp[])
|
||||||
{
|
{
|
||||||
char* filename;
|
char* filename;
|
||||||
int argc;
|
int argc;
|
||||||
int envc;
|
int envc;
|
||||||
|
@ -838,29 +842,33 @@ namespace Sortix
|
||||||
result = process->Execute(filename, buffer, count, argc, argv, envc,
|
result = process->Execute(filename, buffer, count, argc, argv, envc,
|
||||||
envp, ®s);
|
envp, ®s);
|
||||||
|
|
||||||
cleanup_buffer:
|
cleanup_buffer:
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
cleanup_desc:
|
cleanup_desc:
|
||||||
desc.Reset();
|
desc.Reset();
|
||||||
cleanup_envp:
|
cleanup_envp:
|
||||||
for ( int i = 0; i < envc; i++) { delete[] envp[i]; }
|
for ( int i = 0; i < envc; i++)
|
||||||
|
delete[] envp[i];
|
||||||
delete[] envp;
|
delete[] envp;
|
||||||
cleanup_argv:
|
cleanup_argv:
|
||||||
for ( int i = 0; i < argc; i++) { delete[] argv[i]; }
|
for ( int i = 0; i < argc; i++)
|
||||||
|
delete[] argv[i];
|
||||||
delete[] argv;
|
delete[] argv;
|
||||||
cleanup_filename:
|
cleanup_filename:
|
||||||
delete[] filename;
|
delete[] filename;
|
||||||
cleanup_done:
|
cleanup_done:
|
||||||
if ( !result ) { CPU::LoadRegisters(®s); }
|
if ( !result ) { CPU::LoadRegisters(®s); }
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t SysTFork(int flags, tforkregs_t* regs)
|
pid_t sys_tfork(int flags, tforkregs_t* regs)
|
||||||
{
|
{
|
||||||
if ( Signal::IsPending() ) { errno = EINTR; return -1; }
|
if ( Signal::IsPending() )
|
||||||
|
return errno = EINTR, -1;
|
||||||
|
|
||||||
// TODO: Properly support tfork(2).
|
// TODO: Properly support tfork(2).
|
||||||
if ( flags != SFFORK ) { errno = ENOSYS; return -1; }
|
if ( flags != SFFORK )
|
||||||
|
return errno = ENOSYS, -1;
|
||||||
|
|
||||||
CPU::InterruptRegisters cpuregs;
|
CPU::InterruptRegisters cpuregs;
|
||||||
InitializeThreadRegisters(&cpuregs, regs);
|
InitializeThreadRegisters(&cpuregs, regs);
|
||||||
|
@ -868,7 +876,8 @@ namespace Sortix
|
||||||
// TODO: Is it a hack to create a new kernel stack here?
|
// TODO: Is it a hack to create a new kernel stack here?
|
||||||
Thread* curthread = CurrentThread();
|
Thread* curthread = CurrentThread();
|
||||||
uint8_t* newkernelstack = new uint8_t[curthread->kernelstacksize];
|
uint8_t* newkernelstack = new uint8_t[curthread->kernelstacksize];
|
||||||
if ( !newkernelstack ) { return -1; }
|
if ( !newkernelstack )
|
||||||
|
return -1;
|
||||||
|
|
||||||
Process* clone = CurrentProcess()->Fork();
|
Process* clone = CurrentProcess()->Fork();
|
||||||
if ( !clone ) { delete[] newkernelstack; return -1; }
|
if ( !clone ) { delete[] newkernelstack; return -1; }
|
||||||
|
@ -892,38 +901,38 @@ namespace Sortix
|
||||||
StartKernelThread(thread);
|
StartKernelThread(thread);
|
||||||
|
|
||||||
return clone->pid;
|
return clone->pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t SysGetPID()
|
pid_t sys_getpid()
|
||||||
{
|
{
|
||||||
return CurrentProcess()->pid;
|
return CurrentProcess()->pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t Process::GetParentProcessId()
|
pid_t Process::GetParentProcessId()
|
||||||
{
|
{
|
||||||
ScopedLock lock(&parentlock);
|
ScopedLock lock(&parentlock);
|
||||||
if( !parent )
|
if( !parent )
|
||||||
return 0;
|
return 0;
|
||||||
return parent->pid;
|
return parent->pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t SysGetParentPID()
|
pid_t sys_getppid()
|
||||||
{
|
{
|
||||||
return CurrentProcess()->GetParentProcessId();
|
return CurrentProcess()->GetParentProcessId();
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t nextpidtoallocate;
|
pid_t nextpidtoallocate;
|
||||||
kthread_mutex_t pidalloclock;
|
kthread_mutex_t pidalloclock;
|
||||||
|
|
||||||
pid_t Process::AllocatePID()
|
pid_t Process::AllocatePID()
|
||||||
{
|
{
|
||||||
ScopedLock lock(&pidalloclock);
|
ScopedLock lock(&pidalloclock);
|
||||||
return nextpidtoallocate++;
|
return nextpidtoallocate++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This is not thread safe.
|
// TODO: This is not thread safe.
|
||||||
pid_t Process::HackGetForegroundProcess()
|
pid_t Process::HackGetForegroundProcess()
|
||||||
{
|
{
|
||||||
for ( pid_t i = nextpidtoallocate; 1 <= i; i-- )
|
for ( pid_t i = nextpidtoallocate; 1 <= i; i-- )
|
||||||
{
|
{
|
||||||
Process* process = Get(i);
|
Process* process = Get(i);
|
||||||
|
@ -936,62 +945,71 @@ namespace Sortix
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ProcessCompare(Process* a, Process* b)
|
int ProcessCompare(Process* a, Process* b)
|
||||||
{
|
{
|
||||||
if ( a->pid < b->pid ) { return -1; }
|
if ( a->pid < b->pid )
|
||||||
if ( a->pid > b->pid ) { return 1; }
|
return -1;
|
||||||
|
if ( a->pid > b->pid )
|
||||||
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ProcessPIDCompare(Process* a, pid_t pid)
|
int ProcessPIDCompare(Process* a, pid_t pid)
|
||||||
{
|
{
|
||||||
if ( a->pid < pid ) { return -1; }
|
if ( a->pid < pid )
|
||||||
if ( a->pid > pid ) { return 1; }
|
return -1;
|
||||||
|
if ( a->pid > pid )
|
||||||
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SortedList<Process*>* pidlist;
|
SortedList<Process*>* pidlist;
|
||||||
|
|
||||||
Process* Process::Get(pid_t pid)
|
Process* Process::Get(pid_t pid)
|
||||||
{
|
{
|
||||||
ScopedLock lock(&pidalloclock);
|
ScopedLock lock(&pidalloclock);
|
||||||
size_t index = pidlist->Search(ProcessPIDCompare, pid);
|
size_t index = pidlist->Search(ProcessPIDCompare, pid);
|
||||||
if ( index == SIZE_MAX ) { return NULL; }
|
if ( index == SIZE_MAX )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
return pidlist->Get(index);
|
return pidlist->Get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Process::Put(Process* process)
|
bool Process::Put(Process* process)
|
||||||
{
|
{
|
||||||
ScopedLock lock(&pidalloclock);
|
ScopedLock lock(&pidalloclock);
|
||||||
return pidlist->Add(process);
|
return pidlist->Add(process);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::Remove(Process* process)
|
void Process::Remove(Process* process)
|
||||||
{
|
{
|
||||||
ScopedLock lock(&pidalloclock);
|
ScopedLock lock(&pidalloclock);
|
||||||
size_t index = pidlist->Search(process);
|
size_t index = pidlist->Search(process);
|
||||||
assert(index != SIZE_MAX);
|
assert(index != SIZE_MAX);
|
||||||
|
|
||||||
pidlist->Remove(index);
|
pidlist->Remove(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* SysSbrk(intptr_t increment)
|
void* sys_sbrk(intptr_t increment)
|
||||||
{
|
{
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
ProcessSegment* dataseg = NULL;
|
ProcessSegment* dataseg = NULL;
|
||||||
for ( ProcessSegment* iter = process->segments; iter; iter = iter->next )
|
for ( ProcessSegment* iter = process->segments; iter; iter = iter->next )
|
||||||
{
|
{
|
||||||
if ( !iter->type == SEG_DATA ) { continue; }
|
if ( !iter->type == SEG_DATA )
|
||||||
if ( dataseg && iter->position < dataseg->position ) { continue; }
|
continue;
|
||||||
|
if ( dataseg && iter->position < dataseg->position )
|
||||||
|
continue;
|
||||||
dataseg = iter;
|
dataseg = iter;
|
||||||
}
|
}
|
||||||
if ( !dataseg ) { errno = ENOMEM; return (void*) -1UL; }
|
if ( !dataseg )
|
||||||
|
return errno = ENOMEM, (void*) -1UL;
|
||||||
addr_t currentend = dataseg->position + dataseg->size;
|
addr_t currentend = dataseg->position + dataseg->size;
|
||||||
addr_t newend = currentend + increment;
|
addr_t newend = currentend + increment;
|
||||||
if ( newend < dataseg->position ) { errno = EINVAL; return (void*) -1UL; }
|
if ( newend < dataseg->position )
|
||||||
|
return errno = EINVAL, (void*) -1UL;
|
||||||
if ( newend < currentend )
|
if ( newend < currentend )
|
||||||
{
|
{
|
||||||
addr_t unmapfrom = Page::AlignUp(newend);
|
addr_t unmapfrom = Page::AlignUp(newend);
|
||||||
|
@ -1011,50 +1029,50 @@ namespace Sortix
|
||||||
size_t mapbytes = Page::AlignUp(newend - mapfrom);
|
size_t mapbytes = Page::AlignUp(newend - mapfrom);
|
||||||
int prot = PROT_FORK | PROT_READ | PROT_WRITE | PROT_KREAD | PROT_KWRITE;
|
int prot = PROT_FORK | PROT_READ | PROT_WRITE | PROT_KREAD | PROT_KWRITE;
|
||||||
if ( !Memory::MapRange(mapfrom, mapbytes, prot) )
|
if ( !Memory::MapRange(mapfrom, mapbytes, prot) )
|
||||||
{
|
|
||||||
return (void*) -1UL;
|
return (void*) -1UL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
dataseg->size += increment;
|
dataseg->size += increment;
|
||||||
return (void*) newend;
|
return (void*) newend;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SysGetPageSize()
|
size_t sys_getpagesize()
|
||||||
{
|
{
|
||||||
return Page::Size();
|
return Page::Size();
|
||||||
}
|
}
|
||||||
|
|
||||||
mode_t sys_umask(mode_t newmask)
|
mode_t sys_umask(mode_t newmask)
|
||||||
{
|
{
|
||||||
Process* process = CurrentProcess();
|
Process* process = CurrentProcess();
|
||||||
ScopedLock lock(&process->idlock);
|
ScopedLock lock(&process->idlock);
|
||||||
mode_t oldmask = process->umask;
|
mode_t oldmask = process->umask;
|
||||||
process->umask = newmask & 0666;
|
process->umask = newmask & 0666;
|
||||||
return oldmask;
|
return oldmask;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::Init()
|
void Process::Init()
|
||||||
{
|
{
|
||||||
Syscall::Register(SYSCALL_EXEC, (void*) SysExecVE);
|
Syscall::Register(SYSCALL_EXEC, (void*) sys_execve);
|
||||||
Syscall::Register(SYSCALL_TFORK, (void*) SysTFork);
|
Syscall::Register(SYSCALL_EXIT, (void*) sys_exit);
|
||||||
Syscall::Register(SYSCALL_GETPID, (void*) SysGetPID);
|
Syscall::Register(SYSCALL_GET_PAGE_SIZE, (void*) sys_getpagesize);
|
||||||
Syscall::Register(SYSCALL_GETPPID, (void*) SysGetParentPID);
|
Syscall::Register(SYSCALL_GETPID, (void*) sys_getpid);
|
||||||
Syscall::Register(SYSCALL_EXIT, (void*) SysExit);
|
Syscall::Register(SYSCALL_GETPPID, (void*) sys_getppid);
|
||||||
|
Syscall::Register(SYSCALL_SBRK, (void*) sys_sbrk);
|
||||||
|
Syscall::Register(SYSCALL_TFORK, (void*) sys_tfork);
|
||||||
Syscall::Register(SYSCALL_UMASK, (void*) sys_umask);
|
Syscall::Register(SYSCALL_UMASK, (void*) sys_umask);
|
||||||
Syscall::Register(SYSCALL_WAIT, (void*) SysWait);
|
Syscall::Register(SYSCALL_WAIT, (void*) sys_waitpid);
|
||||||
Syscall::Register(SYSCALL_SBRK, (void*) SysSbrk);
|
|
||||||
Syscall::Register(SYSCALL_GET_PAGE_SIZE, (void*) SysGetPageSize);
|
|
||||||
|
|
||||||
pidalloclock = KTHREAD_MUTEX_INITIALIZER;
|
pidalloclock = KTHREAD_MUTEX_INITIALIZER;
|
||||||
nextpidtoallocate = 0;
|
nextpidtoallocate = 0;
|
||||||
|
|
||||||
pidlist = new SortedList<Process*>(ProcessCompare);
|
pidlist = new SortedList<Process*>(ProcessCompare);
|
||||||
if ( !pidlist ) { Panic("could not allocate pidlist\n"); }
|
if ( !pidlist )
|
||||||
}
|
Panic("could not allocate pidlist\n");
|
||||||
|
|
||||||
addr_t Process::AllocVirtualAddr(size_t size)
|
|
||||||
{
|
|
||||||
return (mmapfrom -= size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addr_t Process::AllocVirtualAddr(size_t size)
|
||||||
|
{
|
||||||
|
return mmapfrom -= size;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Sortix
|
||||||
|
|
Loading…
Reference in New Issue