Warning: That file was not part of the compilation database. It may have many parsing errors.

1/* @title: Asynchronous completion objects */
2#pragma once
3#include <stdint.h>
4#include <thread/apc.h>
5
6enum async_completion_type {
7 ASYNC_COMPLETION_APC = 0,
8 ASYNC_COMPLETION_WORKER = 1,
9};
10
11/* TODO: I wrote this all out and never used it. this is a nice
12 * wrapper around using APCs vs callbacks via worker for async
13 * callbacks, and it would be great if I could start using the pattern */
14struct async_completion {
15 union {
16 struct apc apc;
17
18 /* We use this structure to store data BEFORE the
19 * APC is enqueued. This is so that we can save
20 * space in this very frequently instantiated structure,
21 * and reuse space instead of using more */
22 struct {
23 apc_func_t apc_func_internal;
24 void *ctx;
25
26 /* NOTE: must match the position of *owner in struct apc.
27 *
28 * This is used here so that we don't use extra space *
29 * In prepare():
30 *
31 * apc_init(&ac->apc);
32 *
33 * Later on...
34 * ac->type = type; // APC is '0', so it's fine to overwrite
35 * // *owner
36 *
37 * In complete():
38 * enum async_completion_type type = ac->type;
39 *
40 * check `type` and act on it */
41 enum async_completion_type type;
42
43 struct thread *thread;
44 };
45 };
46
47 void (*callback)(struct async_completion *);
48};
49
50static_assert(offsetof(struct apc, owner) ==
51 offsetof(struct async_completion, type));
52
53static inline void async_complete(struct async_completion *ac, void *ctx) {
54 if (ac->type == ASYNC_COMPLETION_APC) {
55 struct thread *t = ac->thread;
56 ac->thread = NULL;
57 apc_enqueue(t, a: &ac->apc, type: APC_TYPE_KERNEL);
58 apc_putref(a: &ac->apc);
59 thread_putref(t);
60 } else {
61 ac->ctx = ctx;
62 ac->callback(ac);
63 }
64}
65
66static inline void async_apc_callback_internal(struct apc_context *apc_ctx,
67 void *arg) {
68 cc_ignore(apc_ctx);
69 struct async_completion *ac = arg;
70 ac->callback(ac);
71}
72
73static inline void async_prepare(
74 struct async_completion *ac,
75 void (*cb)(
76 struct async_completion *), /* If type == ASYNC_COMPLETION_APC, this is
77 * the APC callback. Otherwise, this is the
78 * callback to wake up a worker */
79 enum async_completion_type type) {
80 if (type == ASYNC_COMPLETION_APC) {
81 apc_init(a: &ac->apc, fn: async_apc_callback_internal, arg1: ac, NULL);
82 ac->thread = thread_get_current();
83 enforce(thread_getref(ac->thread), STALE_REFERENCE);
84 }
85
86 ac->callback = cb;
87 ac->type = type;
88}
89
90#define ASYNC_CTX_NONE NULL
91

Warning: That file was not part of the compilation database. It may have many parsing errors.