summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordzwdz2022-05-05 22:12:55 +0200
committerdzwdz2022-05-05 22:12:55 +0200
commit9900cc737988f25db30b5876f066a78e73389205 (patch)
tree1bba6cfbe118855ba3d338aa3d881da3aa15ca9e
parent740cacba5befeba212935b00f8ae95008f564293 (diff)
kernel: syscalls now have to explicitly save the return value
thus they can opt out of doing that so the calls which might return immediately but can return later don't have to both regs_savereturn and return to the caller. and because of that, the return values of a lot of VFS things have just got way saner
-rw-r--r--src/kernel/arch/i386/driver/ps2.c12
-rw-r--r--src/kernel/arch/i386/driver/ps2.h2
-rw-r--r--src/kernel/arch/i386/driver/serial.c15
-rw-r--r--src/kernel/arch/i386/driver/serial.h2
-rw-r--r--src/kernel/arch/i386/registers.h3
-rw-r--r--src/kernel/arch/i386/sysenter.c1
-rw-r--r--src/kernel/syscalls.c55
-rw-r--r--src/kernel/vfs/request.c26
-rw-r--r--src/kernel/vfs/request.h17
-rw-r--r--src/kernel/vfs/root.c8
-rw-r--r--src/kernel/vfs/root.h2
11 files changed, 74 insertions, 69 deletions
diff --git a/src/kernel/arch/i386/driver/ps2.c b/src/kernel/arch/i386/driver/ps2.c
index 666fa76..8955100 100644
--- a/src/kernel/arch/i386/driver/ps2.c
+++ b/src/kernel/arch/i386/driver/ps2.c
@@ -28,14 +28,15 @@ size_t ps2_read(uint8_t *buf, size_t len) {
return ring_get((void*)&backlog, buf, len);
}
-int vfs_ps2_accept(struct vfs_request *req) {
+void vfs_ps2_accept(struct vfs_request *req) {
// when you fix something here go also fix it in the COM1 driver
static uint8_t buf[32]; // pretty damn stupid
int ret;
switch (req->type) {
case VFSOP_OPEN:
// allows opening /ps2/anything, TODO don't
- return vfsreq_finish(req, 0); // fake file handle, whatever
+ vfsreq_finish(req, 0); // fake file handle, whatever
+ break;
case VFSOP_READ:
if (ps2_ready()) {
// TODO FUKKEN MESS
@@ -48,13 +49,14 @@ int vfs_ps2_accept(struct vfs_request *req) {
ret = ps2_read(buf, ret);
virt_cpy_to(req->caller->pages, req->output.buf, buf, ret);
} else ret = -1;
- return vfsreq_finish(req, ret);
+ vfsreq_finish(req, ret);
} else {
blocked_on = req;
- return -1;
}
+ break;
default:
- return vfsreq_finish(req, -1);
+ vfsreq_finish(req, -1);
+ break;
}
}
diff --git a/src/kernel/arch/i386/driver/ps2.h b/src/kernel/arch/i386/driver/ps2.h
index 1bbc2f1..c5d0ce1 100644
--- a/src/kernel/arch/i386/driver/ps2.h
+++ b/src/kernel/arch/i386/driver/ps2.h
@@ -8,5 +8,5 @@ bool ps2_ready(void);
void ps2_recv(uint8_t scancode);
size_t ps2_read(uint8_t *buf, size_t max_len);
-int vfs_ps2_accept(struct vfs_request *);
+void vfs_ps2_accept(struct vfs_request *);
bool vfs_ps2_ready(struct vfs_backend *);
diff --git a/src/kernel/arch/i386/driver/serial.c b/src/kernel/arch/i386/driver/serial.c
index 4e274d8..170cc4d 100644
--- a/src/kernel/arch/i386/driver/serial.c
+++ b/src/kernel/arch/i386/driver/serial.c
@@ -69,12 +69,13 @@ void serial_write(const char *buf, size_t len) {
}
-int vfs_com1_accept(struct vfs_request *req) {
+void vfs_com1_accept(struct vfs_request *req) {
static uint8_t buf[32];
int ret;
switch (req->type) {
case VFSOP_OPEN:
- return vfsreq_finish(req, 0);
+ vfsreq_finish(req, 0);
+ break;
case VFSOP_READ:
if (serial_ready()) {
if (req->caller) {
@@ -86,11 +87,11 @@ int vfs_com1_accept(struct vfs_request *req) {
ret = serial_read(buf, ret);
virt_cpy_to(req->caller->pages, req->output.buf, buf, ret);
} else ret = -1;
- return vfsreq_finish(req, ret);
+ vfsreq_finish(req, ret);
} else {
blocked_on = req;
- return -1;
}
+ break;
case VFSOP_WRITE:
if (req->caller) {
struct virt_iter iter;
@@ -100,9 +101,11 @@ int vfs_com1_accept(struct vfs_request *req) {
serial_write(iter.frag, iter.frag_len);
ret = iter.prior;
} else ret = -1;
- return vfsreq_finish(req, ret);
+ vfsreq_finish(req, ret);
+ break;
default:
- return vfsreq_finish(req, -1);
+ vfsreq_finish(req, -1);
+ break;
}
}
diff --git a/src/kernel/arch/i386/driver/serial.h b/src/kernel/arch/i386/driver/serial.h
index e7f9b7c..6aff142 100644
--- a/src/kernel/arch/i386/driver/serial.h
+++ b/src/kernel/arch/i386/driver/serial.h
@@ -11,5 +11,5 @@ size_t serial_read(char *buf, size_t len);
void serial_write(const char *buf, size_t len);
-int vfs_com1_accept(struct vfs_request *);
+void vfs_com1_accept(struct vfs_request *);
bool vfs_com1_ready(struct vfs_backend *);
diff --git a/src/kernel/arch/i386/registers.h b/src/kernel/arch/i386/registers.h
index 8bd090d..9f481d3 100644
--- a/src/kernel/arch/i386/registers.h
+++ b/src/kernel/arch/i386/registers.h
@@ -14,7 +14,8 @@ struct registers {
} __attribute__((__packed__));
// saves a return value according to the SysV ABI
-static inline void regs_savereturn(struct registers *regs, uint64_t value) {
+static inline uint64_t regs_savereturn(struct registers *regs, uint64_t value) {
regs->eax = value;
regs->edx = value >> 32;
+ return value;
}
diff --git a/src/kernel/arch/i386/sysenter.c b/src/kernel/arch/i386/sysenter.c
index 1d2a333..71dfbe9 100644
--- a/src/kernel/arch/i386/sysenter.c
+++ b/src/kernel/arch/i386/sysenter.c
@@ -23,6 +23,5 @@ _Noreturn void sysenter_stage2(void) {
val = _syscall(regs->eax, regs->ebx,
regs->esi, regs->edi, (uintptr_t)regs->ebp);
- regs_savereturn(&process_current->regs, val);
process_switch_any();
}
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index c5e25b7..aa2d45f 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -9,6 +9,8 @@
#include <shared/syscalls.h>
#include <stdint.h>
+#define SYSCALL_RETURN(val) return regs_savereturn(&process_current->regs, val)
+
_Noreturn void _syscall_exit(int ret) {
process_kill(process_current, ret);
process_switch_any();
@@ -22,23 +24,23 @@ int _syscall_await(void) {
for (struct process *iter = process_current->child;
iter; iter = iter->sibling) {
if (iter->state == PS_DEAD && !iter->noreap)
- return process_try2collect(iter);
+ SYSCALL_RETURN(process_try2collect(iter));
if (iter->state != PS_DEADER)
has_children = true;
}
if (!has_children) {
process_transition(process_current, PS_RUNNING);
- return ~0; // TODO errno
+ SYSCALL_RETURN(~0); // TODO errno
} else {
- return -1;
+ SYSCALL_RETURN(-1);
}
}
int _syscall_fork(int flags) {
struct process *child = process_fork(process_current, flags);
regs_savereturn(&child->regs, 0);
- return 1;
+ SYSCALL_RETURN(1);
}
handle_t _syscall_open(const char __user *path, int len) {
@@ -46,9 +48,9 @@ handle_t _syscall_open(const char __user *path, int len) {
char *path_buf = NULL;
if (PATH_MAX < len)
- return -1;
+ SYSCALL_RETURN(-1);
if (process_find_handle(process_current, 0) < 0)
- return -1;
+ SYSCALL_RETURN(-1);
path_buf = virt_cpy2kmalloc(process_current->pages, path, len);
if (!path_buf) goto fail;
@@ -66,7 +68,7 @@ handle_t _syscall_open(const char __user *path, int len) {
memcpy(path_buf, path_buf + mount->prefix_len, len);
}
- return vfsreq_create((struct vfs_request) {
+ vfsreq_create((struct vfs_request) {
.type = VFSOP_OPEN,
.input = {
.kern = true,
@@ -76,9 +78,10 @@ handle_t _syscall_open(const char __user *path, int len) {
.caller = process_current,
.backend = mount->backend,
});
+ return -1; // dummy
fail:
kfree(path_buf);
- return -1;
+ SYSCALL_RETURN(-1);
}
int _syscall_mount(handle_t hid, const char __user *path, int len) {
@@ -86,7 +89,8 @@ int _syscall_mount(handle_t hid, const char __user *path, int len) {
struct vfs_backend *backend = NULL;
char *path_buf = NULL;
- if (PATH_MAX < len) return -1;
+ if (PATH_MAX < len)
+ SYSCALL_RETURN(-1);
// copy the path to the kernel to simplify it
path_buf = virt_cpy2kmalloc(process_current->pages, path, len);
@@ -122,18 +126,18 @@ int _syscall_mount(handle_t hid, const char __user *path, int len) {
kmalloc_sanity(mount);
kmalloc_sanity(mount->prefix);
- return 0;
+ SYSCALL_RETURN(0);
fail:
kfree(path_buf);
kfree(mount);
- return -1;
+ SYSCALL_RETURN(-1);
}
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) return -1;
- return vfsreq_create((struct vfs_request) {
+ if (!handle) SYSCALL_RETURN(-1);
+ vfsreq_create((struct vfs_request) {
.type = VFSOP_READ,
.output = {
.buf = (userptr_t) buf,
@@ -144,12 +148,13 @@ int _syscall_read(handle_t handle_num, void __user *buf, size_t len, int offset)
.caller = process_current,
.backend = handle->file.backend,
});
+ 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) return -1;
- return vfsreq_create((struct vfs_request) {
+ if (!handle) SYSCALL_RETURN(-1);
+ vfsreq_create((struct vfs_request) {
.type = VFSOP_WRITE,
.input = {
.buf = (userptr_t) buf,
@@ -160,15 +165,16 @@ int _syscall_write(handle_t handle_num, const void __user *buf, size_t len, int
.caller = process_current,
.backend = handle->file.backend,
});
+ return -1; // dummy
}
int _syscall_close(handle_t hid) {
if (hid < 0 || hid >= HANDLE_MAX) return -1;
struct handle **h = &process_current->handles[hid];
- if (!*h) return -1;
+ if (!*h) SYSCALL_RETURN(-1);
handle_close(*h);
*h = NULL;
- return 0;
+ SYSCALL_RETURN(0);
}
handle_t _syscall_fs_fork2(void) {
@@ -177,7 +183,7 @@ handle_t _syscall_fs_fork2(void) {
handle_t front;
front = process_find_handle(process_current, 1);
- if (front < 0) return -1;
+ if (front < 0) SYSCALL_RETURN(-1);
process_current->handles[front] = handle_init(HANDLE_FS_FRONT);
backend = kmalloc(sizeof *backend); // TODO never freed
@@ -193,12 +199,12 @@ handle_t _syscall_fs_fork2(void) {
regs_savereturn(&child->regs, 0);
process_current->handles[front]->fs.backend = backend;
- return front;
+ 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) return -1;
+ if (!backend) SYSCALL_RETURN(-1);
process_transition(process_current, PS_WAITS4REQUEST);
assert(!backend->user.handler); // TODO allow multiple processes to wait on the same backend
@@ -209,12 +215,13 @@ int _syscall_fs_wait(char __user *buf, int max_len, struct fs_wait_response __us
process_current->awaited_req.max_len = max_len;
process_current->awaited_req.res = res;
- return vfs_backend_tryaccept(backend);
+ vfs_backend_tryaccept(backend); // sets return value
+ return -1; // dummy
}
int _syscall_fs_respond(char __user *buf, int ret) {
struct vfs_request *req = process_current->handled_req;
- if (!req) return -1;
+ if (!req) SYSCALL_RETURN(-1);
if (req->output.len > 0 && ret > 0) {
// if this vfsop outputs data and ret is positive, it's the length of the buffer
@@ -228,7 +235,7 @@ int _syscall_fs_respond(char __user *buf, int ret) {
process_current->handled_req = NULL;
vfsreq_finish(req, ret);
- return 0;
+ SYSCALL_RETURN(0);
}
int _syscall_memflag(void __user *addr, size_t len, int flags) {
@@ -247,7 +254,7 @@ int _syscall_memflag(void __user *addr, size_t len, int flags) {
}
}
- return -1;
+ SYSCALL_RETURN(-1);
}
int _syscall(int num, int a, int b, int c, int d) {
diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c
index f463b86..3e7c9f0 100644
--- a/src/kernel/vfs/request.c
+++ b/src/kernel/vfs/request.c
@@ -6,7 +6,7 @@
#include <kernel/vfs/root.h>
#include <shared/mem.h>
-int vfsreq_create(struct vfs_request req_) {
+void vfsreq_create(struct vfs_request req_) {
struct vfs_request *req = kmalloc(sizeof *req); // freed in vfsreq_finish
memcpy(req, &req_, sizeof *req);
@@ -19,17 +19,17 @@ int vfsreq_create(struct vfs_request req_) {
}
if (!req->backend || !req->backend->potential_handlers)
- return vfsreq_finish(req, -1);
+ vfsreq_finish(req, -1);
struct vfs_request **iter = &req->backend->queue;
while (*iter != NULL) // find free spot in queue
iter = &(*iter)->queue_next;
*iter = req;
- return vfs_backend_tryaccept(req->backend);
+ vfs_backend_tryaccept(req->backend);
}
-int vfsreq_finish(struct vfs_request *req, int ret) {
+void vfsreq_finish(struct vfs_request *req, int ret) {
if (req->type == VFSOP_OPEN && ret >= 0) {
// open() calls need special handling
// we need to wrap the id returned by the VFS in a handle passed to
@@ -63,32 +63,32 @@ int vfsreq_finish(struct vfs_request *req, int ret) {
vfs_backend_refdown(req->backend);
kfree(req);
- return ret;
+ return;
}
-int vfs_backend_tryaccept(struct vfs_backend *backend) {
+void vfs_backend_tryaccept(struct vfs_backend *backend) {
struct vfs_request *req = backend->queue;
- if (!req) return -1;
+ if (!req) return;
/* ensure backend is ready to accept request */
if (backend->is_user) {
- if (!backend->user.handler) return -1;
+ if (!backend->user.handler) return;
} else {
assert(backend->kern.ready);
- if (!backend->kern.ready(backend)) return -1;
+ if (!backend->kern.ready(backend)) return;
}
backend->queue = req->queue_next;
if (backend->is_user) {
- return vfs_backend_user_accept(req);
+ vfs_backend_user_accept(req);
} else {
assert(backend->kern.accept);
- return backend->kern.accept(req);
+ backend->kern.accept(req);
}
}
-int vfs_backend_user_accept(struct vfs_request *req) {
+void vfs_backend_user_accept(struct vfs_request *req) {
struct process *handler;
struct fs_wait_response res = {0};
int len = 0;
@@ -123,7 +123,7 @@ int vfs_backend_user_accept(struct vfs_request *req) {
handler->handled_req = req;
req->backend->user.handler = NULL;
regs_savereturn(&handler->regs, 0);
- return 0;
+ return;
fail:
panic_unimplemented(); // TODO
}
diff --git a/src/kernel/vfs/request.h b/src/kernel/vfs/request.h
index b4624fa..9dc6088 100644
--- a/src/kernel/vfs/request.h
+++ b/src/kernel/vfs/request.h
@@ -25,10 +25,7 @@ struct vfs_backend {
} user;
struct {
bool (*ready)(struct vfs_backend *);
-
- // return value might be passed to caller
- // TODO make return void
- int (*accept)(struct vfs_request *);
+ void (*accept)(struct vfs_request *);
} kern;
};
};
@@ -59,13 +56,11 @@ struct vfs_request {
};
/** Assigns the vfs_request to the caller, and dispatches the call */
-int vfsreq_create(struct vfs_request);
-int vfsreq_finish(struct vfs_request *, int ret);
+void vfsreq_create(struct vfs_request);
+void vfsreq_finish(struct vfs_request *, int ret);
-/** Try to accept an enqueued request
- * @return same as _syscall_fs_wait, passed to it. except on calls to kern backend, where it returns the result of the fs op - also gets directly passed to caller. it's a mess */
-// TODO fix the return value mess
-int vfs_backend_tryaccept(struct vfs_backend *);
-int vfs_backend_user_accept(struct vfs_request *req);
+/** Try to accept an enqueued request */
+void vfs_backend_tryaccept(struct vfs_backend *);
+void vfs_backend_user_accept(struct vfs_request *req);
void vfs_backend_refdown(struct vfs_backend *);
diff --git a/src/kernel/vfs/root.c b/src/kernel/vfs/root.c
index c7bd717..989c77e 100644
--- a/src/kernel/vfs/root.c
+++ b/src/kernel/vfs/root.c
@@ -130,17 +130,15 @@ static int handle(struct vfs_request *req, bool *ready) {
}
}
-int vfs_root_accept(struct vfs_request *req) {
+void vfs_root_accept(struct vfs_request *req) {
if (req->caller) {
bool ready = true;
int ret = handle(req, &ready);
if (ready) {
- return vfsreq_finish(req, ret);
- } else {
- return -1;
+ vfsreq_finish(req, ret);
}
} else {
- return vfsreq_finish(req, -1);
+ vfsreq_finish(req, -1);
}
}
diff --git a/src/kernel/vfs/root.h b/src/kernel/vfs/root.h
index f10fb85..3db958d 100644
--- a/src/kernel/vfs/root.h
+++ b/src/kernel/vfs/root.h
@@ -1,5 +1,5 @@
#pragma once
#include <kernel/vfs/request.h>
-int vfs_root_accept(struct vfs_request *);
+void vfs_root_accept(struct vfs_request *);
bool vfs_root_ready(struct vfs_backend *);