summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/kernel/proc.c9
-rw-r--r--src/kernel/proc.h6
-rw-r--r--src/kernel/vfs/request.c44
-rw-r--r--src/kernel/vfs/request.h2
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;