summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/kernel/pipe.c18
-rw-r--r--src/kernel/pipe.h6
-rw-r--r--src/kernel/syscalls.c104
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) {