diff options
author | dzwdz | 2022-04-14 22:11:36 +0200 |
---|---|---|
committer | dzwdz | 2022-04-14 22:11:36 +0200 |
commit | 6613d7e5f3c2e704a6812b0fbcaf79ade8d19980 (patch) | |
tree | c83241169567f857bc03cb3e730a4eee4de64d13 /src/kernel | |
parent | 0d59c8d11173b28f958413128eb792655568a365 (diff) |
kernel/proc: only change state through `process_transition`
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/proc.c | 33 | ||||
-rw-r--r-- | src/kernel/proc.h | 2 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 6 | ||||
-rw-r--r-- | src/kernel/vfs/request.c | 9 | ||||
-rw-r--r-- | src/kernel/vfs/root.c | 2 |
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; |