Add an initial fork() implementation
This commit is contained in:
parent
1624f0360d
commit
20cffdb66c
@ -18,6 +18,7 @@
|
|||||||
#define SYS_fcntl 13
|
#define SYS_fcntl 13
|
||||||
#define SYS_mprotect 14
|
#define SYS_mprotect 14
|
||||||
#define SYS_clock 15
|
#define SYS_clock 15
|
||||||
|
#define SYS_fork 16
|
||||||
|
|
||||||
namespace Syscall
|
namespace Syscall
|
||||||
{
|
{
|
||||||
@ -41,4 +42,5 @@ void sys_seek(Context* context, int fd, long offset, int whence);
|
|||||||
void sys_exec(Context* context, const char* pathname);
|
void sys_exec(Context* context, const char* pathname);
|
||||||
void sys_fcntl(Context* context, int fd, int command, uintptr_t arg);
|
void sys_fcntl(Context* context, int fd, int command, uintptr_t arg);
|
||||||
void sys_mprotect(Context* context, void* address, size_t size, int prot);
|
void sys_mprotect(Context* context, void* address, size_t size, int prot);
|
||||||
void sys_clock(Context* context);
|
void sys_clock(Context* context);
|
||||||
|
void sys_fork(Context* context);
|
@ -27,6 +27,7 @@ void Syscall::entry(Context* context)
|
|||||||
case SYS_fcntl: sys_fcntl(context, (int)context->rdi, (int)context->rsi, context->rdx); break;
|
case SYS_fcntl: sys_fcntl(context, (int)context->rdi, (int)context->rsi, context->rdx); break;
|
||||||
case SYS_mprotect: sys_mprotect(context, (void*)context->rdi, context->rsi, (int)context->rdx); break;
|
case SYS_mprotect: sys_mprotect(context, (void*)context->rdi, context->rsi, (int)context->rdx); break;
|
||||||
case SYS_clock: sys_clock(context); break;
|
case SYS_clock: sys_clock(context); break;
|
||||||
|
case SYS_fork: sys_fork(context); break;
|
||||||
default: context->rax = -ENOSYS; break;
|
default: context->rax = -ENOSYS; break;
|
||||||
}
|
}
|
||||||
VMM::exit_syscall_context();
|
VMM::exit_syscall_context();
|
||||||
|
@ -11,12 +11,43 @@
|
|||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
#include "sys/elf/ELFLoader.h"
|
#include "sys/elf/ELFLoader.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
|
#include "utils/Addresses.h"
|
||||||
|
|
||||||
|
void sys_fork(Context* context) // FIXME: Even though both processes's address spaces are the same in content, writing
|
||||||
|
// to one should not affect the other.
|
||||||
|
{
|
||||||
|
kinfoln("fork(): attempting fork");
|
||||||
|
|
||||||
|
Task* parent = Scheduler::current_task();
|
||||||
|
|
||||||
|
Task* child = Scheduler::create_user_task();
|
||||||
|
|
||||||
|
memcpy(&child->regs, &parent->regs, sizeof(Context));
|
||||||
|
if (parent->floating_saved)
|
||||||
|
{
|
||||||
|
memcpy(child->floating_region, parent->floating_region, sizeof(parent->floating_region));
|
||||||
|
child->floating_saved = true;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < TASK_MAX_FDS; i++) { child->files[i] = parent->files[i]; }
|
||||||
|
|
||||||
|
size_t stack_bytes = get_top_of_stack(parent->allocated_stack, TASK_PAGES_IN_STACK) - parent->regs.rsp;
|
||||||
|
|
||||||
|
child->regs.rsp -= stack_bytes;
|
||||||
|
|
||||||
|
memcpy((void*)child->regs.rsp, (void*)parent->regs.rsp, stack_bytes);
|
||||||
|
|
||||||
|
child->address_space = parent->address_space.clone();
|
||||||
|
|
||||||
|
child->regs.rax = 0;
|
||||||
|
context->rax = child->id;
|
||||||
|
|
||||||
|
kinfoln("fork(): forked parent %d into child %d", parent->id, child->id);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void sys_exec(Context* context, const char* pathname)
|
void sys_exec(Context* context, const char* pathname)
|
||||||
{
|
{
|
||||||
/*context->rax = -ENOSYS; // FIXME: Make exec() work under separate address spaces.
|
|
||||||
return;*/
|
|
||||||
|
|
||||||
char* kpathname = Syscall::strdup_from_user(pathname);
|
char* kpathname = Syscall::strdup_from_user(pathname);
|
||||||
if (!kpathname)
|
if (!kpathname)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user