diff options
-rw-r--r-- | src/kernel/pipe.c | 18 | ||||
-rw-r--r-- | src/kernel/pipe.h | 6 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 104 |
3 files changed, 55 insertions, 73 deletions
diff --git a/src/kernel/pipe.c b/src/kernel/pipe.c index 2dc98fe..bf775b8 100644 --- a/src/kernel/pipe.c +++ b/src/kernel/pipe.c @@ -3,12 +3,20 @@ #include <kernel/pipe.h> #include <kernel/util.h> -bool pipe_joinqueue(struct handle *h, bool wants_write, +static void pipe_trytransfer(struct handle *h); + +void pipe_joinqueue(struct handle *h, bool wants_write, struct process *proc, void __user *pbuf, size_t pbuflen) { assert(h && h->type == HANDLE_PIPE); - if (wants_write == h->pipe.write_end) return false; - if (!h->pipe.sister) return false; + if (wants_write == h->pipe.write_end) { + regs_savereturn(&proc->regs, -1); + return; + } + if (!h->pipe.sister) { + regs_savereturn(&proc->regs, -1); + return; + } struct process **slot = &h->pipe.queued; while (*slot) { @@ -22,10 +30,10 @@ bool pipe_joinqueue(struct handle *h, bool wants_write, proc->waits4pipe.buf = pbuf; proc->waits4pipe.len = pbuflen; proc->waits4pipe.next = NULL; - return true; + pipe_trytransfer(h); } -void pipe_trytransfer(struct handle *h) { +static void pipe_trytransfer(struct handle *h) { struct process *rdr, *wtr; struct virt_cpy_error cpyerr; int len; diff --git a/src/kernel/pipe.h b/src/kernel/pipe.h index 9040ab1..2a90738 100644 --- a/src/kernel/pipe.h +++ b/src/kernel/pipe.h @@ -2,10 +2,8 @@ #include <kernel/proc.h> #include <stdbool.h> -/* returns false on failure */ -bool pipe_joinqueue(struct handle *h, bool wants_write, +/* eventually transitions to PS_RUNNING */ +void pipe_joinqueue(struct handle *h, bool wants_write, struct process *proc, void __user *pbuf, size_t pbuflen); -void pipe_trytransfer(struct handle *h); - void pipe_invalidate_end(struct handle *h); diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 242be2d..7bc018d 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -202,78 +202,54 @@ handle_t _syscall_dup(handle_t from, handle_t to, int flags) { SYSCALL_RETURN(to); } -long _syscall_read(handle_t handle_num, void __user *buf, size_t len, long offset) { - struct handle *h = process_handle_get(process_current, handle_num); +static long simple_vfsop( + enum vfs_operation vfsop, handle_t hid, void __user *buf, + size_t len, long offset, int flags) +{ + assert(vfsop != VFSOP_OPEN && vfsop != VFSOP_CLOSE); + struct handle *h = process_handle_get(process_current, hid); if (!h) SYSCALL_RETURN(-1); - switch (h->type) { - case 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, - }); - break; - case HANDLE_PIPE: - if (pipe_joinqueue(h, true, process_current, buf, len)) - pipe_trytransfer(h); - else - SYSCALL_RETURN(-1); - break; - default: - SYSCALL_RETURN(-1); - } - return -1; // dummy + if (h->type == HANDLE_FILE) { + struct vfs_request req = (struct vfs_request){ + .type = vfsop, + .backend = h->backend, + .id = h->file_id, + .caller = process_current, + .offset = offset, + .flags = flags, + }; + if (vfsop == VFSOP_READ) { + req.output.buf = buf; + req.output.len = len; + } + if (vfsop == VFSOP_WRITE) { + req.input.buf = buf; + req.input.len = len; + } + vfsreq_create(req); + } else if (h->type == HANDLE_PIPE) { + if (vfsop == VFSOP_READ || vfsop == VFSOP_WRITE) { + pipe_joinqueue(h, vfsop == VFSOP_READ, process_current, buf, len); + } else SYSCALL_RETURN(-ENOSYS); + } else SYSCALL_RETURN(-ENOSYS); + return 0; } -long _syscall_write(handle_t handle_num, const void __user *buf, size_t len, long offset, int flags) { - struct handle *h = process_handle_get(process_current, handle_num); - if (!h) SYSCALL_RETURN(-1); +long _syscall_read(handle_t hid, void __user *buf, size_t len, long offset) { + simple_vfsop(VFSOP_READ, hid, buf, len, offset, 0); + return 0; +} + +long _syscall_write(handle_t hid, const void __user *buf, size_t len, long offset, int flags) { if (flags & ~(WRITE_TRUNCATE)) SYSCALL_RETURN(-ENOSYS); - switch (h->type) { - case 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, - .flags = flags - }); - break; - case HANDLE_PIPE: - if (pipe_joinqueue(h, false, process_current, (void __user *)buf, len)) - pipe_trytransfer(h); - else - SYSCALL_RETURN(-1); - break; - default: - SYSCALL_RETURN(-1); - } - return -1; // dummy + simple_vfsop(VFSOP_WRITE, hid, (userptr_t)buf, len, offset, flags); + return 0; } long _syscall_getsize(handle_t hid) { - struct handle *h = process_handle_get(process_current, hid); - if (!h) SYSCALL_RETURN(-1); - if (h->type != HANDLE_FILE) SYSCALL_RETURN(-ENOSYS); - vfsreq_create((struct vfs_request) { - .type = VFSOP_GETSIZE, - .id = h->file_id, - .caller = process_current, - .backend = h->backend, - }); - return -1; // dummy + simple_vfsop(VFSOP_GETSIZE, hid, NULL, 0, 0, 0); + return 0; } long _syscall_remove(handle_t hid) { |