mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Refactor process id allocation and accounting.
This commit is contained in:
parent
25e07a9083
commit
400eb2238f
9 changed files with 214 additions and 89 deletions
|
@ -89,8 +89,8 @@ dispmsg.o \
|
|||
dtable.o \
|
||||
elf.o \
|
||||
fcache.o \
|
||||
fsfunc.o \
|
||||
fs/full.o \
|
||||
fsfunc.o \
|
||||
fs/kram.o \
|
||||
fs/null.o \
|
||||
fs/user.o \
|
||||
|
@ -122,6 +122,7 @@ pci.o \
|
|||
pipe.o \
|
||||
poll.o \
|
||||
process.o \
|
||||
ptable.o \
|
||||
refcount.o \
|
||||
registers.o \
|
||||
resource.o \
|
||||
|
|
|
@ -50,6 +50,7 @@ class Process;
|
|||
class Descriptor;
|
||||
class DescriptorTable;
|
||||
class MountTable;
|
||||
class ProcessTable;
|
||||
struct ProcessSegment;
|
||||
struct ProcessTimer;
|
||||
struct ioctx_struct;
|
||||
|
@ -68,9 +69,6 @@ public:
|
|||
public:
|
||||
static void Init();
|
||||
|
||||
private:
|
||||
static pid_t AllocatePID();
|
||||
|
||||
public:
|
||||
char* string_table;
|
||||
size_t string_table_length;
|
||||
|
@ -97,6 +95,9 @@ private:
|
|||
Ref<MountTable> mtable;
|
||||
Ref<DescriptorTable> dtable;
|
||||
|
||||
public:
|
||||
Ref<ProcessTable> ptable;
|
||||
|
||||
public:
|
||||
kthread_mutex_t resource_limits_lock;
|
||||
struct rlimit resource_limits[RLIMIT_NUM_DECLARED];
|
||||
|
@ -110,8 +111,9 @@ public:
|
|||
public:
|
||||
void BootstrapTables(Ref<DescriptorTable> dtable, Ref<MountTable> mtable);
|
||||
void BootstrapDirectories(Ref<Descriptor> root);
|
||||
Ref<MountTable> GetMTable();
|
||||
Ref<DescriptorTable> GetDTable();
|
||||
Ref<MountTable> GetMTable();
|
||||
Ref<ProcessTable> GetPTable();
|
||||
Ref<Descriptor> GetRoot();
|
||||
Ref<Descriptor> GetCWD();
|
||||
Ref<Descriptor> GetDescriptor(int fd);
|
||||
|
@ -201,13 +203,6 @@ public:
|
|||
public:
|
||||
void ResetForExecute();
|
||||
|
||||
public:
|
||||
static Process* Get(pid_t pid);
|
||||
|
||||
private:
|
||||
static bool Put(Process* process);
|
||||
static void Remove(Process* process);
|
||||
|
||||
};
|
||||
|
||||
Process* CurrentProcess();
|
||||
|
|
63
kernel/include/sortix/kernel/ptable.h
Normal file
63
kernel/include/sortix/kernel/ptable.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2014.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix 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 General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
sortix/kernel/ptable.h
|
||||
Process table.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef INCLUDE_SORTIX_KERNEl_PTABLE_H
|
||||
#define INCLUDE_SORTIX_KERNEl_PTABLE_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <sortix/kernel/kthread.h>
|
||||
#include <sortix/kernel/refcount.h>
|
||||
|
||||
namespace Sortix {
|
||||
|
||||
class Process;
|
||||
|
||||
struct ptable_entry
|
||||
{
|
||||
pid_t pid;
|
||||
Process* process;
|
||||
};
|
||||
|
||||
class ProcessTable : public Refcountable
|
||||
{
|
||||
public:
|
||||
ProcessTable();
|
||||
virtual ~ProcessTable();
|
||||
Process* Get(pid_t pid);
|
||||
pid_t Allocate(Process* process);
|
||||
void Free(pid_t pid);
|
||||
|
||||
private:
|
||||
kthread_mutex_t ptablelock;
|
||||
pid_t next_pid;
|
||||
struct ptable_entry* entries;
|
||||
size_t entries_used;
|
||||
size_t entries_length;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Sortix
|
||||
|
||||
#endif
|
|
@ -53,6 +53,7 @@
|
|||
#include <sortix/kernel/panic.h>
|
||||
#include <sortix/kernel/pci.h>
|
||||
#include <sortix/kernel/process.h>
|
||||
#include <sortix/kernel/ptable.h>
|
||||
#include <sortix/kernel/refcount.h>
|
||||
#include <sortix/kernel/scheduler.h>
|
||||
#include <sortix/kernel/signal.h>
|
||||
|
@ -435,10 +436,16 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo)
|
|||
DisplayMessage::Init();
|
||||
|
||||
// Now that the base system has been loaded, it's time to go threaded. First
|
||||
// we create an object that represents this thread.
|
||||
// we create an object that represents this process.
|
||||
Ref<ProcessTable> ptable(new ProcessTable());
|
||||
if ( !ptable )
|
||||
Panic("Could not allocate the process table");
|
||||
Process* system = new Process;
|
||||
if ( !system )
|
||||
Panic("Could not allocate the system process");
|
||||
if ( (system->pid = (system->ptable = ptable)->Allocate(system)) < 0 )
|
||||
Panic("Could not allocate the system process a pid");
|
||||
ptable.Reset();
|
||||
system->addrspace = Memory::GetAddressSpace();
|
||||
system->group = system;
|
||||
system->groupprev = NULL;
|
||||
|
@ -658,7 +665,10 @@ static void BootThread(void* /*user*/)
|
|||
if ( !initaddrspace ) { Panic("Could not create init's address space"); }
|
||||
|
||||
Process* init = new Process;
|
||||
if ( !init ) { Panic("Could not allocate init process"); }
|
||||
if ( !init )
|
||||
Panic("Could not allocate init process");
|
||||
if ( (init->pid = (init->ptable = CurrentProcess()->ptable)->Allocate(init)) < 0 )
|
||||
Panic("Could not allocate init a pid");
|
||||
init->group = init;
|
||||
init->groupprev = NULL;
|
||||
init->groupnext = NULL;
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include <sortix/kernel/kthread.h>
|
||||
#include <sortix/kernel/poll.h>
|
||||
#include <sortix/kernel/process.h>
|
||||
#include <sortix/kernel/ptable.h>
|
||||
#include <sortix/kernel/refcount.h>
|
||||
#include <sortix/kernel/scheduler.h>
|
||||
|
||||
|
@ -145,7 +146,7 @@ int LogTerminal::tcgetwinsize(ioctx_t* ctx, struct winsize* ws)
|
|||
int LogTerminal::tcsetpgrp(ioctx_t* /*ctx*/, pid_t pgid)
|
||||
{
|
||||
ScopedLock lock(&termlock);
|
||||
Process* process = Process::Get(pgid);
|
||||
Process* process = CurrentProcess()->GetPTable()->Get(pgid);
|
||||
if ( !pgid || !process )
|
||||
return errno = ESRCH, -1;
|
||||
kthread_mutex_lock(&process->groupchildlock);
|
||||
|
@ -187,7 +188,7 @@ void LogTerminal::ProcessKeystroke(int kbkey)
|
|||
{
|
||||
while ( linebuffer.CanBackspace() )
|
||||
linebuffer.Backspace();
|
||||
if ( Process* process = Process::Get(foreground_pgid) )
|
||||
if ( Process* process = CurrentProcess()->GetPTable()->Get(foreground_pgid) )
|
||||
process->DeliverGroupSignal(SIGINT);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include <sortix/kernel/memorymanagement.h>
|
||||
#include <sortix/kernel/mtable.h>
|
||||
#include <sortix/kernel/process.h>
|
||||
#include <sortix/kernel/ptable.h>
|
||||
#include <sortix/kernel/refcount.h>
|
||||
#include <sortix/kernel/scheduler.h>
|
||||
#include <sortix/kernel/sortedlist.h>
|
||||
|
@ -81,7 +82,7 @@ Process::Process()
|
|||
symbol_table_length = 0;
|
||||
program_image_path = NULL;
|
||||
addrspace = 0;
|
||||
pid = AllocatePID();
|
||||
pid = 0;
|
||||
|
||||
nicelock = KTHREAD_MUTEX_INITIALIZER;
|
||||
nice = 0;
|
||||
|
@ -160,7 +161,6 @@ Process::Process()
|
|||
// child_system_clock initialized in member constructor.
|
||||
Time::InitializeProcessClocks(this);
|
||||
alarm_timer.Attach(Time::GetClock(CLOCK_MONOTONIC));
|
||||
Put(this);
|
||||
}
|
||||
|
||||
Process::~Process()
|
||||
|
@ -179,7 +179,9 @@ Process::~Process()
|
|||
assert(!cwd);
|
||||
assert(!root);
|
||||
|
||||
Remove(this);
|
||||
assert(ptable);
|
||||
ptable->Free(pid);
|
||||
ptable.Reset();
|
||||
}
|
||||
|
||||
void Process::BootstrapTables(Ref<DescriptorTable> dtable, Ref<MountTable> mtable)
|
||||
|
@ -588,6 +590,13 @@ Ref<DescriptorTable> Process::GetDTable()
|
|||
return dtable;
|
||||
}
|
||||
|
||||
Ref<ProcessTable> Process::GetPTable()
|
||||
{
|
||||
ScopedLock lock(&ptrlock);
|
||||
assert(ptable);
|
||||
return ptable;
|
||||
}
|
||||
|
||||
Ref<Descriptor> Process::GetRoot()
|
||||
{
|
||||
ScopedLock lock(&ptrlock);
|
||||
|
@ -634,6 +643,12 @@ Process* Process::Fork()
|
|||
if ( !clone )
|
||||
return NULL;
|
||||
|
||||
if ( (clone->pid = (clone->ptable = ptable)->Allocate(clone)) < 0 )
|
||||
{
|
||||
delete clone;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct segment* clone_segments = NULL;
|
||||
|
||||
// Fork the segment list.
|
||||
|
@ -1299,7 +1314,7 @@ static pid_t sys_getppid()
|
|||
|
||||
static pid_t sys_getpgid(pid_t pid)
|
||||
{
|
||||
Process* process = !pid ? CurrentProcess() : Process::Get(pid);
|
||||
Process* process = !pid ? CurrentProcess() : CurrentProcess()->GetPTable()->Get(pid);
|
||||
if ( !process )
|
||||
return errno = ESRCH, -1;
|
||||
|
||||
|
@ -1324,10 +1339,10 @@ static int sys_setpgid(pid_t pid, pid_t pgid)
|
|||
// group. This probably unlikely, but correctness over all!
|
||||
|
||||
// Find the processes in question.
|
||||
Process* process = !pid ? CurrentProcess() : Process::Get(pid);
|
||||
Process* process = !pid ? CurrentProcess() : CurrentProcess()->GetPTable()->Get(pid);
|
||||
if ( !process )
|
||||
return errno = ESRCH, -1;
|
||||
Process* group = !pgid ? process : Process::Get(pgid);
|
||||
Process* group = !pgid ? process : CurrentProcess()->GetPTable()->Get(pgid);
|
||||
if ( !group )
|
||||
return errno = ESRCH, -1;
|
||||
|
||||
|
@ -1372,60 +1387,6 @@ static int sys_setpgid(pid_t pid, pid_t pgid)
|
|||
return 0;
|
||||
}
|
||||
|
||||
pid_t nextpidtoallocate;
|
||||
kthread_mutex_t pidalloclock;
|
||||
|
||||
pid_t Process::AllocatePID()
|
||||
{
|
||||
ScopedLock lock(&pidalloclock);
|
||||
return nextpidtoallocate++;
|
||||
}
|
||||
|
||||
int ProcessCompare(Process* a, Process* b)
|
||||
{
|
||||
if ( a->pid < b->pid )
|
||||
return -1;
|
||||
if ( a->pid > b->pid )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ProcessPIDCompare(Process* a, pid_t pid)
|
||||
{
|
||||
if ( a->pid < pid )
|
||||
return -1;
|
||||
if ( a->pid > pid )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SortedList<Process*>* pidlist;
|
||||
|
||||
Process* Process::Get(pid_t pid)
|
||||
{
|
||||
ScopedLock lock(&pidalloclock);
|
||||
size_t index = pidlist->Search(ProcessPIDCompare, pid);
|
||||
if ( index == SIZE_MAX )
|
||||
return NULL;
|
||||
|
||||
return pidlist->Get(index);
|
||||
}
|
||||
|
||||
bool Process::Put(Process* process)
|
||||
{
|
||||
ScopedLock lock(&pidalloclock);
|
||||
return pidlist->Add(process);
|
||||
}
|
||||
|
||||
void Process::Remove(Process* process)
|
||||
{
|
||||
ScopedLock lock(&pidalloclock);
|
||||
size_t index = pidlist->Search(process);
|
||||
assert(index != SIZE_MAX);
|
||||
|
||||
pidlist->Remove(index);
|
||||
}
|
||||
|
||||
static void* sys_sbrk(intptr_t increment)
|
||||
{
|
||||
Process* process = CurrentProcess();
|
||||
|
@ -1516,13 +1477,6 @@ void Process::Init()
|
|||
Syscall::Register(SYSCALL_TFORK, (void*) sys_tfork);
|
||||
Syscall::Register(SYSCALL_UMASK, (void*) sys_umask);
|
||||
Syscall::Register(SYSCALL_WAITPID, (void*) sys_waitpid);
|
||||
|
||||
pidalloclock = KTHREAD_MUTEX_INITIALIZER;
|
||||
nextpidtoallocate = 0;
|
||||
|
||||
pidlist = new SortedList<Process*>(ProcessCompare);
|
||||
if ( !pidlist )
|
||||
Panic("could not allocate pidlist\n");
|
||||
}
|
||||
|
||||
} // namespace Sortix
|
||||
|
|
99
kernel/ptable.cpp
Normal file
99
kernel/ptable.cpp
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2014.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix 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 General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
ptable.cpp
|
||||
Process table.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sortix/kernel/kthread.h>
|
||||
#include <sortix/kernel/ptable.h>
|
||||
#include <sortix/kernel/refcount.h>
|
||||
|
||||
// TODO: Process memory ownership needs to be reference counted.
|
||||
// TODO: There is no proper way to iterate all the existing processes.
|
||||
// TODO: This implementation is rather run-time inefficient.
|
||||
// TODO: The Free method potentially leaks memory as the ptable is never shrunk.
|
||||
// TODO: The next_pid counter could potentially overflow.
|
||||
|
||||
namespace Sortix {
|
||||
|
||||
ProcessTable::ProcessTable()
|
||||
{
|
||||
ptablelock = KTHREAD_MUTEX_INITIALIZER;
|
||||
next_pid = 0;
|
||||
entries = NULL;
|
||||
entries_used = 0;
|
||||
entries_length = 0;
|
||||
}
|
||||
|
||||
ProcessTable::~ProcessTable()
|
||||
{
|
||||
delete[] entries;
|
||||
}
|
||||
|
||||
Process* ProcessTable::Get(pid_t pid)
|
||||
{
|
||||
ScopedLock lock(&ptablelock);
|
||||
for ( size_t i = 0; i < entries_used; i++ )
|
||||
if ( entries[i].pid == pid )
|
||||
return entries[i].process;
|
||||
return errno = ESRCH, (Process*) NULL;
|
||||
}
|
||||
|
||||
pid_t ProcessTable::Allocate(Process* process)
|
||||
{
|
||||
ScopedLock lock(&ptablelock);
|
||||
if ( entries_used == entries_length )
|
||||
{
|
||||
size_t new_length = entries_length ? 2 * entries_length : 64;
|
||||
struct ptable_entry* new_entries = new struct ptable_entry[new_length];
|
||||
if ( !new_entries )
|
||||
return -1;
|
||||
memcpy(new_entries, entries, sizeof(struct ptable_entry) * entries_length);
|
||||
delete[] entries;
|
||||
entries = new_entries;
|
||||
entries_length = new_length;
|
||||
}
|
||||
|
||||
struct ptable_entry* entry = &entries[entries_used++];
|
||||
entry->process = process;
|
||||
return entry->pid = next_pid++;
|
||||
}
|
||||
|
||||
void ProcessTable::Free(pid_t pid)
|
||||
{
|
||||
ScopedLock lock(&ptablelock);
|
||||
for ( size_t i = 0; i < entries_used; i++ )
|
||||
{
|
||||
if ( entries[i].pid != pid )
|
||||
continue;
|
||||
entries[i] = entries[--entries_used];
|
||||
return;
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
|
||||
} // namespace Sortix
|
|
@ -32,6 +32,7 @@
|
|||
#include <sortix/kernel/copy.h>
|
||||
#include <sortix/kernel/kernel.h>
|
||||
#include <sortix/kernel/process.h>
|
||||
#include <sortix/kernel/ptable.h>
|
||||
#include <sortix/kernel/syscall.h>
|
||||
|
||||
#include "resource.h"
|
||||
|
@ -45,7 +46,7 @@ static int GetProcessPriority(pid_t who)
|
|||
return errno = EINVAL, -1;
|
||||
// TODO: If who isn't the current process, then it could self-destruct at
|
||||
// any time while we use it; there is no safe way to do this yet.
|
||||
Process* process = who ? Process::Get(who) : CurrentProcess();
|
||||
Process* process = who ? CurrentProcess()->GetPTable()->Get(who) : CurrentProcess();
|
||||
if ( !process )
|
||||
return errno = ESRCH, -1;
|
||||
ScopedLock lock(&process->nicelock);
|
||||
|
@ -58,7 +59,7 @@ static int SetProcessPriority(pid_t who, int prio)
|
|||
return errno = EINVAL, -1;
|
||||
// TODO: If who isn't the current process, then it could self-destruct at
|
||||
// any time while we use it; there is no safe way to do this yet.
|
||||
Process* process = who ? Process::Get(who) : CurrentProcess();
|
||||
Process* process = who ? CurrentProcess()->GetPTable()->Get(who) : CurrentProcess();
|
||||
if ( !process )
|
||||
return errno = ESRCH, -1;
|
||||
ScopedLock lock(&process->nicelock);
|
||||
|
@ -81,7 +82,7 @@ static int GetProcessGroupPriority(pid_t who)
|
|||
return errno = EINVAL, -1;
|
||||
// TODO: If who isn't the current process, then it could self-destruct at
|
||||
// any time while we use it; there is no safe way to do this yet.
|
||||
Process* group = who ? Process::Get(who) : CurrentProcessGroup();
|
||||
Process* group = who ? CurrentProcess()->GetPTable()->Get(who) : CurrentProcessGroup();
|
||||
if ( !group )
|
||||
return errno = ESRCH, -1;
|
||||
int lowest = INT_MAX;
|
||||
|
@ -101,7 +102,7 @@ static int SetProcessGroupPriority(pid_t who, int prio)
|
|||
return errno = EINVAL, -1;
|
||||
// TODO: If who isn't the current process, then it could self-destruct at
|
||||
// any time while we use it; there is no safe way to do this yet.
|
||||
Process* group = who ? Process::Get(who) : CurrentProcessGroup();
|
||||
Process* group = who ? CurrentProcess()->GetPTable()->Get(who) : CurrentProcessGroup();
|
||||
if ( !group )
|
||||
return errno = ESRCH, -1;
|
||||
ScopedLock group_parent_lock(&group->groupparentlock);
|
||||
|
@ -161,7 +162,7 @@ int sys_prlimit(pid_t pid,
|
|||
return errno = EINVAL, -1;
|
||||
// TODO: If pid isn't the current process, then it could self-destruct at
|
||||
// any time while we use it; there is no safe way to do this yet.
|
||||
Process* process = pid ? Process::Get(pid) : CurrentProcess();
|
||||
Process* process = pid ? CurrentProcess()->GetPTable()->Get(pid) : CurrentProcess();
|
||||
if ( !process )
|
||||
return errno = ESRCH, -1;
|
||||
ScopedLock lock(&process->resource_limits_lock);
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include <sortix/kernel/interrupt.h>
|
||||
#include <sortix/kernel/kernel.h>
|
||||
#include <sortix/kernel/process.h>
|
||||
#include <sortix/kernel/ptable.h>
|
||||
#include <sortix/kernel/signal.h>
|
||||
#include <sortix/kernel/syscall.h>
|
||||
#include <sortix/kernel/thread.h>
|
||||
|
@ -277,7 +278,7 @@ static int sys_kill(pid_t pid, int signum)
|
|||
bool process_group = pid < 0 ? (pid = -pid, true) : false;
|
||||
|
||||
// TODO: Race condition: The process could be deleted while we use it.
|
||||
Process* process = Process::Get(pid);
|
||||
Process* process = CurrentProcess()->GetPTable()->Get(pid);
|
||||
if ( !process )
|
||||
return errno = ESRCH, -1;
|
||||
|
||||
|
|
Loading…
Reference in a new issue