1#include <sch/sched.h>
2#include <thread/io_wait.h>
3#include <thread/thread.h>
4
5void 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
19void 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
25void io_wait_signal(struct thread_wait_header *request) {
26 thread_wait_header_satisfy(hdr: request, reason: THREAD_WAKE_REASON_BLOCKING_IO, NULL);
27}
28
29void 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