From 8ee57c885a72854d1884a886de4db538a8468e07 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Fri, 6 May 2022 14:41:58 +0200 Subject: syscalls: merge fork() and fs_fork2() --- src/kernel/proc.c | 12 ++++++--- src/kernel/syscalls.c | 67 +++++++++++++++++++++++++++------------------------ 2 files changed, 44 insertions(+), 35 deletions(-) (limited to 'src/kernel') diff --git a/src/kernel/proc.c b/src/kernel/proc.c index ed257fd..7ef4579 100644 --- a/src/kernel/proc.c +++ b/src/kernel/proc.c @@ -44,7 +44,7 @@ struct process *process_seed(struct kmain_info *info) { struct process *process_fork(struct process *parent, int flags) { struct process *child = kmalloc(sizeof *child); - memcpy(child, parent, sizeof *child); + memcpy(child, parent, sizeof *child); // TODO manually set fields child->pages = pagedir_copy(parent->pages); child->sibling = parent->child; @@ -55,9 +55,13 @@ struct process *process_fork(struct process *parent, int flags) { parent->handled_req = NULL; // TODO control this with a flag - if (child->controlled) { - child->controlled->potential_handlers++; - child->controlled->refcount++; + if ((flags & FORK_NEWFS) == 0) { + if (child->controlled) { + child->controlled->potential_handlers++; + child->controlled->refcount++; + } + } else { + child->controlled = NULL; } for (handle_t h = 0; h < HANDLE_MAX; h++) { diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 3443b60..59358a8 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -39,9 +39,42 @@ int _syscall_await(void) { } } -int _syscall_fork(int flags) { - struct process *child = process_fork(process_current, flags); +int _syscall_fork(int flags, handle_t __user *fs_front) { + struct process *child; + handle_t front; + + if ((flags & FORK_NEWFS) && fs_front) { + /* we'll need to return a handle, check if that's possible */ + front = process_find_free_handle(process_current, 1); + if (front < 0) SYSCALL_RETURN(-1); + } + + child = process_fork(process_current, flags); regs_savereturn(&child->regs, 0); + + if ((flags & FORK_NEWFS) && fs_front) { + struct vfs_backend *backend = kmalloc(sizeof *backend); + + process_current->handles[front] = handle_init(HANDLE_FS_FRONT); + + backend->heap = true; + backend->is_user = true; + backend->potential_handlers = 1; + backend->refcount = 2; // child + handle + backend->user.handler = NULL; + backend->queue = NULL; + + child->controlled = backend; + + process_current->handles[front]->fs.backend = backend; + + if (fs_front) { + /* failure ignored. if you pass an invalid pointer to this function, + * you just don't receive the handle. you'll probably segfault + * trying to access it anyways */ + virt_cpy_to(process_current->pages, fs_front, &front, sizeof front); + } + } SYSCALL_RETURN(1); } @@ -179,32 +212,6 @@ int _syscall_close(handle_t hid) { SYSCALL_RETURN(0); } -handle_t _syscall_fs_fork2(void) { - struct vfs_backend *backend; - struct process *child; - handle_t front; - - front = process_find_free_handle(process_current, 1); - if (front < 0) SYSCALL_RETURN(-1); - process_current->handles[front] = handle_init(HANDLE_FS_FRONT); - - backend = kmalloc(sizeof *backend); - backend->heap = true; - backend->is_user = true; - backend->potential_handlers = 1; - backend->refcount = 2; // child + handle - backend->user.handler = NULL; - backend->queue = NULL; - - child = process_fork(process_current, 0); - if (child->controlled) vfs_backend_refdown(child->controlled); - child->controlled = backend; - regs_savereturn(&child->regs, 0); - - process_current->handles[front]->fs.backend = backend; - SYSCALL_RETURN(front); -} - int _syscall_fs_wait(char __user *buf, int max_len, struct fs_wait_response __user *res) { struct vfs_backend *backend = process_current->controlled; if (!backend) SYSCALL_RETURN(-1); @@ -267,7 +274,7 @@ int _syscall(int num, int a, int b, int c, int d) { case _SYSCALL_AWAIT: return _syscall_await(); case _SYSCALL_FORK: - return _syscall_fork(a); + return _syscall_fork(a, (userptr_t)b); case _SYSCALL_OPEN: return _syscall_open((userptr_t)a, b); case _SYSCALL_MOUNT: @@ -278,8 +285,6 @@ int _syscall(int num, int a, int b, int c, int d) { return _syscall_write(a, (userptr_t)b, c, d); case _SYSCALL_CLOSE: return _syscall_close(a); - case _SYSCALL_FS_FORK2: - return _syscall_fs_fork2(); case _SYSCALL_FS_WAIT: return _syscall_fs_wait((userptr_t)a, b, (userptr_t)c); case _SYSCALL_FS_RESPOND: -- cgit v1.2.3