summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/proc.c33
-rw-r--r--src/kernel/proc.h2
-rw-r--r--src/kernel/syscalls.c6
-rw-r--r--src/kernel/vfs/request.c9
-rw-r--r--src/kernel/vfs/root.c2
5 files changed, 38 insertions, 14 deletions
diff --git a/src/kernel/proc.c b/src/kernel/proc.c
index e97d5cf..3024957 100644
--- a/src/kernel/proc.c
+++ b/src/kernel/proc.c
@@ -162,9 +162,34 @@ handle_t process_find_handle(struct process *proc) {
return handle;
}
+void process_transition(struct process *p, enum process_state state) {
+ enum process_state last = p->state;
+ p->state = state;
+ switch (state) {
+ case PS_RUNNING:
+ assert(last != PS_DEAD && last != PS_DEADER);
+ break;
+ case PS_DEAD:
+ assert(last == PS_RUNNING);
+ break;
+ case PS_DEADER:
+ assert(last == PS_DEAD);
+ process_free(p);
+ break;
+ case PS_WAITS4CHILDDEATH:
+ case PS_WAITS4FS:
+ case PS_WAITS4REQUEST:
+ assert(last == PS_RUNNING);
+ break;
+ case PS_WAITS4IRQ:
+ assert(last == PS_WAITS4FS);
+ break;
+ }
+}
+
void process_kill(struct process *proc, int ret) {
// TODO kill children
- proc->state = PS_DEAD;
+ process_transition(proc, PS_DEAD);
proc->death_msg = ret;
process_try2collect(proc);
if (proc == process_first) {
@@ -184,10 +209,8 @@ int process_try2collect(struct process *dead) {
case PS_WAITS4CHILDDEATH:
ret = dead->death_msg;
regs_savereturn(&parent->regs, ret);
- parent->state = PS_RUNNING;
-
- dead->state = PS_DEADER;
- process_free(dead);
+ process_transition(parent, PS_RUNNING);
+ process_transition(dead, PS_DEADER);
return ret;
diff --git a/src/kernel/proc.h b/src/kernel/proc.h
index 5daef31..18d4ec9 100644
--- a/src/kernel/proc.h
+++ b/src/kernel/proc.h
@@ -74,6 +74,8 @@ size_t process_find_multiple(enum process_state, struct process **buf, size_t ma
handle_t process_find_handle(struct process *proc); // finds the first free handle
+void process_transition(struct process *, enum process_state);
+
void process_kill(struct process *proc, int ret);
/** Tries to transistion from PS_DEAD to PS_DEADER.
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index 0a25a63..217fa77 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -16,7 +16,7 @@ _Noreturn void _syscall_exit(int ret) {
int _syscall_await(void) {
bool has_children = false;
- process_current->state = PS_WAITS4CHILDDEATH;
+ process_transition(process_current, PS_WAITS4CHILDDEATH);
// find any already dead children
for (struct process *iter = process_current->child;
@@ -28,7 +28,7 @@ int _syscall_await(void) {
}
if (!has_children) {
- process_current->state = PS_RUNNING;
+ process_transition(process_current, PS_RUNNING);
return ~0; // TODO errno
} else {
return -1;
@@ -204,7 +204,7 @@ int _syscall_fs_wait(char __user *buf, int max_len, struct fs_wait_response __us
struct vfs_backend *backend = process_current->controlled;
if (!backend) return -1;
- process_current->state = PS_WAITS4REQUEST;
+ process_transition(process_current, PS_WAITS4REQUEST);
backend->handler = process_current;
/* checking the validity of those pointers here would make
* vfs_request_accept simpler. TODO? */
diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c
index 0ac0b3a..687f456 100644
--- a/src/kernel/vfs/request.c
+++ b/src/kernel/vfs/request.c
@@ -7,8 +7,7 @@
int vfs_request_create(struct vfs_request req_) {
struct vfs_request *req;
- assert(process_current->state == PS_RUNNING);
- process_current->state = PS_WAITS4FS;
+ process_transition(process_current, PS_WAITS4FS);
process_current->waits4fs.queue_next = NULL;
// the request is owned by the caller
@@ -64,7 +63,7 @@ int vfs_request_accept(struct vfs_request *req) {
handler->awaited_req.res, &res, sizeof res))
goto fail; // can't copy response struct
- handler->state = PS_RUNNING;
+ process_transition(handler, PS_RUNNING);
handler->handled_req = req;
regs_savereturn(&handler->regs, 0);
return 0;
@@ -92,8 +91,8 @@ int vfs_request_finish(struct vfs_request *req, int ret) {
if (req->input.kern) kfree(req->input.buf_kern);
- assert(req->caller->state = PS_WAITS4FS);
- req->caller->state = PS_RUNNING;
+ assert(req->caller->state == PS_WAITS4FS || req->caller->state == PS_WAITS4IRQ);
+ process_transition(req->caller, PS_RUNNING);
regs_savereturn(&req->caller->regs, ret);
return ret;
}
diff --git a/src/kernel/vfs/root.c b/src/kernel/vfs/root.c
index cdc388f..11d5f64 100644
--- a/src/kernel/vfs/root.c
+++ b/src/kernel/vfs/root.c
@@ -56,7 +56,7 @@ static void wait_callback(struct process *proc) {
static bool wait_setup(struct vfs_request *req, bool *ready, bool (*ready_fn)()) {
if (!ready_fn()) {
*ready = false;
- req->caller->state = PS_WAITS4IRQ;
+ process_transition(req->caller, PS_WAITS4IRQ);
req->caller->waits4irq.req = *req;
req->caller->waits4irq.ready = ready_fn;
req->caller->waits4irq.callback = wait_callback;