From d9da70c7c6230b9698dc4a1dbc4d7f05794d2740 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Wed, 3 Aug 2022 12:42:52 +0200 Subject: kernel: reuse a single allocation for all vfs_requests of a process $ iostress 32 512 0 > /vtty # before 512 calls, 0 bytes. avg 121133 $ iostress 32 512 0 > /vtty # after 512 calls, 0 bytes. avg 103540 103540/121133 = ~85% I think the tiny bit of added complexity is worth it here. --- src/kernel/proc.c | 9 +++++++-- src/kernel/proc.h | 6 +++--- src/kernel/vfs/request.c | 44 ++++++++++++++++++++++---------------------- src/kernel/vfs/request.h | 2 ++ 4 files changed, 34 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/kernel/proc.c b/src/kernel/proc.c index a8cf303..e7a5ed6 100644 --- a/src/kernel/proc.c +++ b/src/kernel/proc.c @@ -114,8 +114,13 @@ void process_kill(struct process *p, int ret) { p->controlled = NULL; } - if (p->state == PS_WAITS4FS) - p->waits4fs.req->caller = NULL; + if (p->state == PS_WAITS4FS) { + assert(p->reqslot); + p->reqslot->caller = NULL; /* transfer ownership */ + p->reqslot = NULL; + } else if (p->reqslot) { + kfree(p->reqslot); + } if (p->state == PS_WAITS4PIPE) { struct process **iter = &p->waits4pipe.pipe->pipe.queued; diff --git a/src/kernel/proc.h b/src/kernel/proc.h index c7e885a..d6f84bd 100644 --- a/src/kernel/proc.h +++ b/src/kernel/proc.h @@ -35,9 +35,6 @@ struct process { // saved value, meaning depends on .state union { int death_msg; // PS_DEAD - struct { - struct vfs_request *req; - } waits4fs; // PS_WAITS4FS struct { char __user *buf; size_t max_len; @@ -52,6 +49,9 @@ struct process { }; struct vfs_request *handled_req; + /* allocated once, the requests from WAITS4FS get stored here */ + struct vfs_request *reqslot; + /* vfs_backend controlled (not exclusively) by this process */ struct vfs_backend *controlled; diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c index 0164dfd..d942fba 100644 --- a/src/kernel/vfs/request.c +++ b/src/kernel/vfs/request.c @@ -8,29 +8,30 @@ #include void vfsreq_create(struct vfs_request req_) { - struct vfs_request *req = kmalloc(sizeof *req); // freed in vfsreq_finish + struct vfs_request *req; + if (req_.caller) { + process_transition(req_.caller, PS_WAITS4FS); + if (!req_.caller->reqslot) + req_.caller->reqslot = kmalloc(sizeof *req); + req = req_.caller->reqslot; + /* (re)using a single allocation for all request a process makes */ + } else { + req = kmalloc(sizeof *req); + } memcpy(req, &req_, sizeof *req); if (req->backend) req->backend->refcount++; - if (req->caller) { - // TODO after running `run_tests` from vga, this is entered with state == PS_WAITS4FS - process_transition(req->caller, PS_WAITS4FS); - req->caller->waits4fs.req = req; - } - - if (!req->backend || !req->backend->potential_handlers) { + if (req->backend && req->backend->potential_handlers) { + struct vfs_request **iter = &req->backend->queue; + while (*iter != NULL) // find free spot in queue + iter = &(*iter)->queue_next; + *iter = req; + vfs_backend_tryaccept(req->backend); + } else { vfsreq_finish_short(req, -1); - return; } - - struct vfs_request **iter = &req->backend->queue; - while (*iter != NULL) // find free spot in queue - iter = &(*iter)->queue_next; - *iter = req; - - vfs_backend_tryaccept(req->backend); } void vfsreq_finish(struct vfs_request *req, char __user *stored, long ret, @@ -70,17 +71,16 @@ void vfsreq_finish(struct vfs_request *req, char __user *stored, long ret, if (req->input.kern) kfree(req->input.buf_kern); + if (req->backend) + vfs_backend_refdown(req->backend); + if (req->caller) { assert(req->caller->state == PS_WAITS4FS); regs_savereturn(&req->caller->regs, ret); process_transition(req->caller, PS_RUNNING); + } else { + kfree(req); } - - if (req->backend) - vfs_backend_refdown(req->backend); - - kfree(req); - return; } void vfs_backend_tryaccept(struct vfs_backend *backend) { diff --git a/src/kernel/vfs/request.h b/src/kernel/vfs/request.h index cb560c9..ee33623 100644 --- a/src/kernel/vfs/request.h +++ b/src/kernel/vfs/request.h @@ -51,6 +51,8 @@ struct vfs_request { long offset; int flags; + /* if caller != NULL, owned by it - don't free, the allocation will be reused + * if caller == NULL, free on finish */ struct process *caller; struct vfs_backend *backend; -- cgit v1.2.3