1#include <sch/sched.h>
2#include <thread/io_wait.h>
3#include <thread/thread.h>
4
5static atomic_size_t io_wait_magic = ATOMIC_VAR_INIT(0);
6
7void io_wait_begin(struct io_wait_token *out, void *io_object) {
8 struct thread *t = thread_get_current();
9
10 *out = (struct io_wait_token){.wait_object = io_object,
11 .active = true,
12 .magic = atomic_fetch_add(&io_wait_magic, 1),
13 .owner = t};
14 list_add_tail(new: &out->list, head: &t->io_wait_tokens);
15
16 thread_prepare_to_block(t, r: THREAD_BLOCK_REASON_IO,
17 wait_type: THREAD_WAIT_UNINTERRUPTIBLE, expect_wake_src: io_object);
18}
19
20void io_wait_end(struct io_wait_token *t, enum io_wait_end_action act) {
21 struct thread *c = thread_get_current();
22 bool found = false;
23
24 /* double check */
25 struct io_wait_token *iter;
26 list_for_each_entry(iter, &c->io_wait_tokens, list) {
27 kassert(iter->active);
28 kassert(iter->owner == c);
29 if (iter == t) {
30 found = true;
31 break;
32 }
33 }
34
35 kassert(found);
36
37 list_del(entry: &t->list);
38
39 if (list_empty(head: &c->io_wait_tokens)) {
40 thread_unboost_self();
41
42 if (act == IO_WAIT_END_YIELD)
43 scheduler_yield();
44 }
45
46 t->active = false;
47}
48