1/* @title: APCs */
2#pragma once
3#include <irq/irq.h>
4#include <sch/sched.h>
5#include <smp/core.h>
6#include <stdatomic.h>
7#include <stdbool.h>
8#include <stddef.h>
9#include <stdint.h>
10#include <structures/list.h>
11#include <thread/apc_types.h>
12#include <thread/thread.h>
13#include <types/refcount.h>
14
15enum apc_state : uint8_t {
16 APC_STATE_IDLE = 0,
17 APC_STATE_QUEUED,
18 APC_STATE_EXECUTING,
19};
20
21struct apc;
22typedef void (*apc_destroy_t)(struct apc *apc);
23
24struct apc {
25 apc_func_t func;
26 void *ctx;
27 struct thread *owner;
28 struct apc *next;
29 refcount_t refcount;
30 _Atomic enum apc_state state;
31 apc_destroy_t destroy;
32};
33
34struct event_apc {
35 struct apc apc;
36 struct apc_event_desc *desc;
37 size_t execute_times;
38};
39
40struct apc_event_desc {
41 const char *name; /* TODO: add fields to this structure */
42};
43
44#define APC_EVENT_EXTERN(n) extern struct apc_event_desc __apc_event_##n
45
46#define APC_EVENT_CREATE(n, strname) \
47 struct apc_event_desc __apc_event_##n = {.name = strname}
48#define APC_EVENT(n) &(__apc_event_##n)
49
50struct apc *apc_create(void);
51struct event_apc *apc_event_apc_create(void);
52void apc_init(struct apc *a, apc_func_t fn, void *arg1, apc_destroy_t destroy);
53void apc_event_apc_init(struct event_apc *a, apc_func_t fn, void *arg1,
54 apc_destroy_t destroy);
55bool apc_get(struct apc *a);
56void apc_put(struct apc *a);
57void apc_destroy_free(struct apc *a);
58void apc_event_signal(struct apc_event_desc *desc);
59
60/* The caller must hold a reference to both t and a. */
61bool apc_enqueue(struct thread *t, struct apc *a, enum apc_type type);
62bool apc_enqueue_event_apc(struct event_apc *a, struct apc_event_desc *d);
63/* The caller must hold a reference to both t and a. */
64bool apc_cancel(struct thread *t, struct apc *a);
65
66void apc_check_and_deliver(struct thread *t);
67
68void apc_enable_special();
69void apc_disable_special();
70
71void apc_enable_kernel();
72void apc_disable_kernel();
73
74void apc_rundown_thread(struct thread *t);
75
76static inline const char *apc_event_str(struct apc_event_desc *evt) {
77 return evt->name;
78}
79
80static inline bool apc_enqueue_on_curr(struct apc *a, enum apc_type type) {
81 return apc_enqueue(t: thread_get_current(), a, type);
82}
83
84static inline void apc_queue_init(struct apc_queue *q) {
85 q->head = q->tail = NULL;
86}
87