diff options
author | dzwdz | 2022-07-05 22:51:21 +0200 |
---|---|---|
committer | dzwdz | 2022-07-05 22:51:21 +0200 |
commit | a89984d7200381d7b8035c48124d93105d59cf24 (patch) | |
tree | 01e788518dca3c5cdb269e82b6a272612ab51970 /src/kernel/syscalls.c | |
parent | b16ab3edc8d3f3d5bcbe0afc8dec3e9ed822a224 (diff) |
kernel: initial partial pipe support
Diffstat (limited to 'src/kernel/syscalls.c')
-rw-r--r-- | src/kernel/syscalls.c | 107 |
1 files changed, 81 insertions, 26 deletions
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index efa1d54..4a59811 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -173,36 +173,78 @@ fail: } int _syscall_read(handle_t handle_num, void __user *buf, size_t len, int offset) { - struct handle *handle = process_handle_get(process_current, handle_num, HANDLE_FILE); - if (!handle) SYSCALL_RETURN(-1); - vfsreq_create((struct vfs_request) { - .type = VFSOP_READ, - .output = { - .buf = (userptr_t) buf, - .len = len, - }, - .id = handle->file_id, - .offset = offset, - .caller = process_current, - .backend = handle->backend, - }); + struct handle *h; + // TODO get rid of the type argument in process_handle_get + if ((h = process_handle_get(process_current, handle_num, HANDLE_FILE))) { + vfsreq_create((struct vfs_request) { + .type = VFSOP_READ, + .output = { + .buf = (userptr_t) buf, + .len = len, + }, + .id = h->file_id, + .offset = offset, + .caller = process_current, + .backend = h->backend, + }); + } else if ((h = process_handle_get(process_current, handle_num, HANDLE_PIPE))) { + if (h->pipe.stuck && h->pipe.wants_write) + panic_unimplemented(); // TODO pipe queue + + if (h->pipe.stuck) { + assert(h->pipe.stuck->state == PS_WAITS4PIPE); + panic_unimplemented(); + } else { + process_transition(process_current, PS_WAITS4PIPE); + h->pipe.stuck = process_current; + h->pipe.wants_write = true; + process_current->waits4pipe.pipe = h; + process_current->waits4pipe.buf = buf; + process_current->waits4pipe.len = len; + } + } else { + SYSCALL_RETURN(-1); + } return -1; // dummy } int _syscall_write(handle_t handle_num, const void __user *buf, size_t len, int offset) { - struct handle *handle = process_handle_get(process_current, handle_num, HANDLE_FILE); - if (!handle) SYSCALL_RETURN(-1); - vfsreq_create((struct vfs_request) { - .type = VFSOP_WRITE, - .input = { - .buf = (userptr_t) buf, - .len = len, - }, - .id = handle->file_id, - .offset = offset, - .caller = process_current, - .backend = handle->backend, - }); + struct handle *h; + if ((h = process_handle_get(process_current, handle_num, HANDLE_FILE))) { + vfsreq_create((struct vfs_request) { + .type = VFSOP_WRITE, + .input = { + .buf = (userptr_t) buf, + .len = len, + }, + .id = h->file_id, + .offset = offset, + .caller = process_current, + .backend = h->backend, + }); + } else if ((h = process_handle_get(process_current, handle_num, HANDLE_PIPE))) { + if (h->pipe.stuck && !h->pipe.wants_write) + panic_unimplemented(); // TODO pipe queue + + if (h->pipe.stuck) { + struct process *p = h->pipe.stuck; + assert(p->state == PS_WAITS4PIPE); + if (len <= p->waits4pipe.len) { + bool succ = virt_cpy( + p->pages, p->waits4pipe.buf, + process_current->pages, buf, len); + if (!succ) panic_unimplemented(); + process_transition(p, PS_RUNNING); + regs_savereturn(&p->regs, len); + + SYSCALL_RETURN(len); + } else panic_unimplemented(); + } else { + panic_unimplemented(); + } + } else { + SYSCALL_RETURN(-1); + } return -1; // dummy } @@ -289,6 +331,16 @@ ret: // the macro is too stupid to handle returning pointers return addr; } +handle_t _syscall_pipe(int flags) { + if (flags) return -1; + + handle_t h = process_find_free_handle(process_current, 0); + if (h < 0) return -1; + process_current->handles[h] = handle_init(HANDLE_PIPE); + assert(process_current->handles[h]->pipe.stuck == NULL); + SYSCALL_RETURN(h); +} + void _syscall_debug_klog(const void __user *buf, size_t len) { (void)buf; (void)len; // static char kbuf[256]; @@ -333,6 +385,9 @@ int _syscall(int num, int a, int b, int c, int d) { case _SYSCALL_MEMFLAG: _syscall_memflag((userptr_t)a, b, c); break; + case _SYSCALL_PIPE: + _syscall_pipe(a); + break; case _SYSCALL_DEBUG_KLOG: _syscall_debug_klog((userptr_t)a, b); break; |