| 1 | #include <sch/sched.h> |
| 2 | #include <thread/io_wait.h> |
| 3 | #include <thread/thread.h> |
| 4 | |
| 5 | void io_wait_begin(struct io_wait_token *out, |
| 6 | struct thread_wait_header *request) { |
| 7 | struct thread *t = thread_get_current(); |
| 8 | enforce(!out->active); |
| 9 | out->active = true; |
| 10 | list_head_push_back(h: &t->io_wait_tokens, n: &out->list); |
| 11 | |
| 12 | thread_wait_header_init(header: request); |
| 13 | const struct thread_wait_object object = {.header = request, |
| 14 | .object = request}; |
| 15 | thread_wait_prepare(objects: &object, count: 1, storage: &out->block, type: THREAD_WAIT_UNINTERRUPTIBLE, |
| 16 | reason: THREAD_BLOCK_REASON_IO); |
| 17 | } |
| 18 | |
| 19 | void io_wait_complete(struct io_wait_token *t) { |
| 20 | enforce(t->active && t->block.thread == thread_get_current()); |
| 21 | enforce(thread_get_current()->active_wait_blocks == &t->block); |
| 22 | thread_wait_complete(); |
| 23 | } |
| 24 | |
| 25 | void io_wait_signal(struct thread_wait_header *request) { |
| 26 | thread_wait_header_satisfy(hdr: request, reason: THREAD_WAKE_REASON_BLOCKING_IO, NULL); |
| 27 | } |
| 28 | |
| 29 | void io_wait_end(struct io_wait_token *t, enum io_wait_end_action act) { |
| 30 | struct thread *c = thread_get_current(); |
| 31 | enforce(t->active && t->block.thread == c); |
| 32 | |
| 33 | /* submission failures can end registrations without yielding */ |
| 34 | if (c->active_wait_blocks == &t->block) |
| 35 | thread_wait_cancel(); |
| 36 | |
| 37 | list_node_delete_init(n: &t->list); |
| 38 | t->active = false; |
| 39 | |
| 40 | if (list_head_empty(h: &c->io_wait_tokens) && act == IO_WAIT_END_YIELD) |
| 41 | scheduler_yield(); |
| 42 | } |
| 43 | |