1/* @title: Thread Enumerations and Types */
2#pragma once
3#include <mem/page.h>
4#include <stdarg.h>
5#include <stdint.h>
6
7struct thread;
8struct thread_create_params;
9struct cpu_context;
10
11typedef void (*thread_entry_fn_t)(void *arg);
12typedef uint8_t thread_act_reason_t; /* Polymorphic type:
13 * all the THREAD_*_REASONs
14 * are uint8_t, and often, we
15 * may need just a generic reason.
16 *
17 * This is that. */
18
19/* Both ASAN and the lock validator are very eager to consume
20 * stack memory, so we'll give threads 16 times as many pages
21 * if either of those happen to be on, and this should
22 * give enough headroom for when both are on too */
23#if defined(DEBUG_ASAN) || defined(DEBUG_LOCK_CHK)
24#define THREAD_STACK_SIZE (PAGE_SIZE * 16)
25#else
26#define THREAD_STACK_SIZE (PAGE_SIZE * 4)
27#endif
28
29#define THREAD_STACKS_HEAP_START 0xFFFFF10000000000ULL
30#define THREAD_STACKS_HEAP_END 0xFFFFF20000000000ULL
31
32enum thread_state : uint8_t {
33 THREAD_STATE_IDLE_THREAD, /* Specifically the idle thread */
34 THREAD_STATE_READY, /* Thread is ready to run but not currently running */
35 THREAD_STATE_RUNNING, /* Thread is currently executing */
36 THREAD_STATE_BLOCKED, /* Waiting on I/O, lock, or condition */
37 THREAD_STATE_SLEEPING, /* Temporarily not runnable */
38 THREAD_STATE_ZOMBIE, /* Finished executing but hasn't been reaped it yet */
39 THREAD_STATE_TERMINATED, /* Fully done, can be cleaned up */
40 THREAD_STATE_HALTED, /* Thread manually suspended */
41};
42
43enum thread_wait_type : uint8_t {
44 THREAD_WAIT_NONE,
45 THREAD_WAIT_UNINTERRUPTIBLE, /* Only object matching/satisfaction ends it */
46 THREAD_WAIT_INTERRUPTIBLE, /* APCs OK, alerts end the wait */
47};
48
49enum thread_wait_status : uint8_t {
50 THREAD_WAIT_SATISFIED,
51 THREAD_WAIT_ALERTED,
52 THREAD_WAIT_TIMED_OUT,
53};
54
55/* thread_flags: 32 bit bitflags:
56 *
57 * ┌───────────────────────────────────────────────────────────┐
58 * Bits │ 31..28 27..24 23..20 19..16 15..12 11..8 7..4 3..0 │
59 * Use │ AAAA **** **** **** **** *adJ jRWY DEF* │
60 * └───────────────────────────────────────────────────────────┘
61 * F - Flexible RT - realtime scheduler related stuff
62 * E - Executing APC
63 * D - Dying
64 * Y - Yielded after a wait (block, sleep)
65 * W - Available
66 * r - Realtime fault tolerance
67 * j - Joinable - someone holds a join reference on this thread
68 * J - Joined - a join is in progress or consumed the join reference
69 * d - Diagnostic - Diagnostics enabled for this thread in debug
70 * a - Delivering APCs - In the APC delivery code
71 *
72 * A - Unused (Available)
73 * * - Unused (Unavailable)
74 *
75 */
76enum thread_flags : uint32_t {
77 THREAD_FLAG_RESV0 = 1,
78 THREAD_FLAG_FLEXIBLE_RT = 1 << 1,
79 THREAD_FLAG_EXECUTING_APC = 1 << 2,
80 THREAD_FLAG_DYING = 1 << 3,
81 THREAD_FLAG_YIELDED = 1 << 4,
82 THREAD_FLAG_RT_FAULT_TOLERANCE = 1 << 6,
83 THREAD_FLAG_JOINABLE = 1 << 7,
84 THREAD_FLAG_JOINED = 1 << 8,
85
86 THREAD_FLAG_DIAG = 1 << 9,
87
88 /* This is for when inside the APC subsystem, whereas
89 * THREAD_FLAG_EXECUTING_APC is for an actual APC callback */
90 THREAD_FLAG_DELIVERING_APCS = 1 << 10,
91
92};
93
94enum thread_prio_class : uint8_t {
95 THREAD_PRIO_CLASS_BACKGROUND = 0, /* Background thread */
96 THREAD_PRIO_CLASS_TIMESHARE = 1, /* Timesharing thread */
97 THREAD_PRIO_CLASS_REALTIME = 2, /* Realtime thread */
98 THREAD_PRIO_CLASS_URGENT = 3, /* Urgent thread - ran before RT */
99};
100#define THREAD_PRIO_CLASS_COUNT (4)
101#define THREAD_PRIO_CLASS_BIT_COUNT 2
102#define THREAD_PRIO_CLASS_MASK 0x3
103
104/* Different enums are used for the little
105 * bit of type safety since different ringbuffers
106 * are used to keep track of different reasons */
107enum thread_resume_reason : uint8_t {
108 THREAD_WAKE_REASON_BLOCKING_IO = 1,
109 THREAD_WAKE_REASON_BLOCKING_MANUAL = 2,
110 THREAD_WAKE_REASON_SLEEP_TIMEOUT = 3,
111 THREAD_WAKE_REASON_SLEEP_MANUAL = 4,
112};
113
114enum thread_block_reason : uint8_t {
115 THREAD_BLOCK_REASON_IO = 5,
116 THREAD_BLOCK_REASON_MANUAL = 6,
117};
118
119enum thread_sleep_reason : uint8_t {
120 THREAD_SLEEP_REASON_MANUAL = 7,
121};
122
123/* Used in condvars, totally separate from thread_resume_reason */
124enum wake_reason {
125 WAKE_REASON_NONE = 0, /* No reason specified */
126 WAKE_REASON_SIGNAL = 1, /* Signal from something */
127 WAKE_REASON_TIMEOUT = 2, /* Timeout */
128};
129
130struct thread_class_donation {
131 struct thread *target;
132 enum thread_prio_class class : 2;
133 bool active;
134};
135
136#define THREAD_CLASS_DONATION_EMPTY \
137 ((struct thread_class_donation) {.target = NULL, \
138 .class = THREAD_PRIO_CLASS_BACKGROUND, \
139 .active = false})
140
141struct thread *thread_create_full(char *cc_nonnull_ptr name,
142 thread_entry_fn_t entry,
143 struct thread_create_params *params,
144 va_list args) cc_printf_like(1, 0);
145