diff options
-rw-r--r-- | src/kernel/proc.c | 9 | ||||
-rw-r--r-- | src/kernel/proc.h | 6 | ||||
-rw-r--r-- | src/kernel/vfs/request.c | 44 | ||||
-rw-r--r-- | src/kernel/vfs/request.h | 2 |
4 files changed, 34 insertions, 27 deletions
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 @@ -36,9 +36,6 @@ struct process { union { int death_msg; // PS_DEAD struct { - struct vfs_request *req; - } waits4fs; // PS_WAITS4FS - struct { char __user *buf; size_t max_len; struct fs_wait_response __user *res; @@ -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 <shared/mem.h> 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; |