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 | |
parent | b16ab3edc8d3f3d5bcbe0afc8dec3e9ed822a224 (diff) |
kernel: initial partial pipe support
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/handle.c | 5 | ||||
-rw-r--r-- | src/kernel/handle.h | 8 | ||||
-rw-r--r-- | src/kernel/proc.c | 1 | ||||
-rw-r--r-- | src/kernel/proc.h | 6 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 107 |
5 files changed, 98 insertions, 29 deletions
diff --git a/src/kernel/handle.c b/src/kernel/handle.c index ac8db1f..70830ff 100644 --- a/src/kernel/handle.c +++ b/src/kernel/handle.c @@ -3,9 +3,11 @@ #include <kernel/panic.h> #include <kernel/proc.h> #include <kernel/vfs/request.h> +#include <shared/mem.h> struct handle *handle_init(enum handle_type type) { struct handle *h = kmalloc(sizeof *h); + memset(h, 0, sizeof *h); h->type = type; h->refcount = 1; return h; @@ -25,7 +27,8 @@ void handle_close(struct handle *h) { }); } - vfs_backend_refdown(h->backend); + if (h->backend) + vfs_backend_refdown(h->backend); // TODO sanity check to check if refcount is true. handle_sanity? diff --git a/src/kernel/handle.h b/src/kernel/handle.h index 088ff93..d644521 100644 --- a/src/kernel/handle.h +++ b/src/kernel/handle.h @@ -9,14 +9,18 @@ enum handle_type; // forward declaration for proc.h enum handle_type { HANDLE_INVALID = 0, HANDLE_FILE, - + HANDLE_PIPE, HANDLE_FS_FRONT, }; struct handle { enum handle_type type; - struct vfs_backend *backend; + struct vfs_backend *backend; // HANDLE_FILE | HANDLE_FS_FRONT int file_id; // only applicable to HANDLE_FILE + struct { + struct process *stuck; + bool wants_write; // refers to the waiting process + } pipe; size_t refcount; }; diff --git a/src/kernel/proc.c b/src/kernel/proc.c index 90e24f7..717af11 100644 --- a/src/kernel/proc.c +++ b/src/kernel/proc.c @@ -263,6 +263,7 @@ void process_transition(struct process *p, enum process_state state) { case PS_WAITS4CHILDDEATH: case PS_WAITS4FS: case PS_WAITS4REQUEST: + case PS_WAITS4PIPE: assert(last == PS_RUNNING); break; diff --git a/src/kernel/proc.h b/src/kernel/proc.h index 93044d2..eb5bd6b 100644 --- a/src/kernel/proc.h +++ b/src/kernel/proc.h @@ -14,6 +14,7 @@ enum process_state { PS_WAITS4CHILDDEATH, PS_WAITS4FS, PS_WAITS4REQUEST, + PS_WAITS4PIPE, PS_LAST, }; @@ -42,6 +43,11 @@ struct process { size_t max_len; struct fs_wait_response __user *res; } awaited_req; // PS_WAITS4REQUEST + struct { + struct handle *pipe; + char __user *buf; + size_t len; + } waits4pipe; }; struct vfs_request *handled_req; 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; |