PatchworkOS  da8a090
A non-POSIX operating system.
Loading...
Searching...
No Matches
thread.h
Go to the documentation of this file.
1#pragma once
2
3#include <kernel/cpu/gdt.h>
5#include <kernel/cpu/simd.h>
8#include <kernel/ipc/note.h>
10#include <kernel/sched/sched.h>
11#include <kernel/sched/wait.h>
12#include <kernel/utils/ref.h>
13
14#include <sys/list.h>
15#include <sys/proc.h>
16
17/**
18 * @brief Thread of execution.
19 * @ingroup kernel_sched
20 * @defgroup kernel_sched_thread Threads
21 * @{
22 */
23
24/**
25 * @brief Thread state enum.
26 * @enum thread_state_t
27 *
28 */
29typedef enum
30{
31 THREAD_PARKED = 0, ///< Is doing nothing, not in a queue, not blocking, think of it as "other".
32 THREAD_ACTIVE, ///< Is either running or ready to run.
33 THREAD_PRE_BLOCK, ///< Has started the process of blocking but has not yet been given to a owner cpu.
34 THREAD_BLOCKED, ///< Is blocking and waiting in one or multiple wait queues.
35 THREAD_UNBLOCKING, ///< Has started unblocking, used to prevent the same thread being unblocked multiple times.
36 /**
37 * The thread is currently dying, it will be freed by the scheduler once its invoked.
38 *
39 * @warning This state is more fragile than the others. Since a thread could technically be killed at any time and
40 * we have several systems relying on the thread state as a form of synchronization, this state should only be set
41 * when the thread is running in an interrupt context.
42 */
45
46/**
47 * @brief Thread of execution structure.
48 * @struct thread_t
49 *
50 * A `thread_t` represents an independent thread of execution within a `process_t`.
51 *
52 * ## Thread Stacks
53 * The position of a thread user stack is decided based on its thread id. The user stack of the thread with id 0 is
54 * located at the top of the lower half of the address space, the user stack is `CONFIG_MAX_USER_STACK_PAGES` pages
55 * long, and below it is the guard page. Below that is the user stack of the thread with id 1, below that is its guard
56 * page, it then continues like that for however many threads there are.
57 *
58 * The kernel stack works the same way, but instead starts just under the kernel code and data section, at the top of
59 * the kernel stacks region and each stack is `CONFIG_MAX_KERNEL_STACK_PAGES` pages long.
60 *
61 */
62typedef struct thread
63{
64 process_t* process; ///< The parent process that the thread executes within.
65 list_entry_t processEntry; ///< The entry for the parent process.
66 tid_t id; ///< The thread id, unique within a `process_t`.
67 /**
68 * The current state of the thread, used to prevent race conditions and make debugging easier.
69 */
71 /**
72 * The last error that occurred while the thread was running, specified using errno codes.
73 */
75 stack_pointer_t kernelStack; ///< The kernel stack of the thread.
76 stack_pointer_t userStack; ///< The user stack of the thread.
83 /**
84 * The threads interrupt frame is used to save the values in the CPU registers such that the scheduler can continue
85 * executing the thread later on.
86 */
88} thread_t;
89
90/**
91 * @brief Creates a new thread structure.
92 *
93 * Does not push the created thread to the scheduler or similar, merely handling allocation and initialization.
94 *
95 * @param process The parent process that the thread will execute within.
96 * @return On success, returns the newly created thread. On failure, returns `NULL` and `errno` is set.
97 */
99
100/**
101 * @brief Kernel thread entry point function type.
102 */
103typedef void (*thread_kernel_entry_t)(void* arg);
104
105/**
106 * @brief Creates a new thread that runs in kernel mode and submits it to the scheduler.
107 *
108 * @param entry The entry point function for the thread.
109 * @param arg An argument to pass to the entry point function.
110 * @return On success, returns the newly created thread ID. On failure, returns `ERR` and `errno` is set.
111 */
113
114/**
115 * @brief Frees a thread structure.
116 *
117 * @param thread The thread to be freed.
118 */
119void thread_free(thread_t* thread);
120
121/**
122 * @brief Save state to a thread.
123 *
124 * @param thread The destination thread where the state will be saved.
125 * @param frame The source frame..
126 */
127void thread_save(thread_t* thread, const interrupt_frame_t* frame);
128
129/**
130 * @brief Load state from a thread.
131 *
132 * Will retrieve the interrupt frame and setup the CPU with the threads contexts/data.
133 *
134 * @param thread The source thread to load state from.
135 * @param frame The destination interrupt frame.
136 */
137void thread_load(thread_t* thread, interrupt_frame_t* frame);
138
139/**
140 * @brief Check if a thread has a note pending.
141 *
142 * @param thread The thread to query.
143 * @return True if there is a note pending, false otherwise.
144 */
145bool thread_is_note_pending(thread_t* thread);
146
147/**
148 * @brief Send a note to a thread.
149 *
150 * This function should always be used over the `note_queue_push()` function, as it performs additional checks, like unblocking the thread to notify it of the received note.
151 *
152 * @param thread The destination thread.
153 * @param buffer The buffer to write.
154 * @param count The number of bytes to write.
155 * @return On success, `0`. On failure, `ERR` and `errno` is set.
156 */
158
159/**
160 * @brief Safely copy data from user space.
161 *
162 * Will pin the user pages in memory while performing the copy and expand the user stack if necessary.
163 *
164 * @param thread The thread performing the operation.
165 * @param dest The destination buffer in kernel space.
166 * @param userSrc The source buffer in user space.
167 * @param length The number of bytes to copy.
168 * @return On success, `0`. On failure, `ERR` and `errno` is set.
169 */
170uint64_t thread_copy_from_user(thread_t* thread, void* dest, const void* userSrc, uint64_t length);
171
172/**
173 * @brief Safely copy data to user space.
174 *
175 * Will pin the user pages in memory while performing the copy and expand the user stack if necessary.
176 *
177 * @param thread The thread performing the operation.
178 * @param dest The destination buffer in user space.
179 * @param userSrc The source buffer in kernel space.
180 * @param length The number of bytes to copy.
181 * @return On success, `0`. On failure, `ERR` and `errno` is set.
182 */
183uint64_t thread_copy_to_user(thread_t* thread, void* dest, const void* userSrc, uint64_t length);
184
185/**
186 * @brief Safely copy a null-terminated array of objects from user space.
187 *
188 * @param thread The thread performing the operation.
189 * @param userArray The source array in user space.
190 * @param terminator A pointer to the terminator object.
191 * @param objectSize The size of each object in the array.
192 * @param maxCount The maximum number of objects to copy.
193 * @param outArray Output pointer to store the allocated array in kernel space, must be freed by the caller.
194 * @param outCount Output pointer to store the number of objects copied, can be `NULL`.
195 * @return On success, `0`. On failure, `ERR` and `errno` is set.
196 */
197uint64_t thread_copy_from_user_terminated(thread_t* thread, const void* userArray, const void* terminator,
198 uint8_t objectSize, uint64_t maxCount, void** outArray, uint64_t* outCount);
199
200/**
201 * @brief Safely copy a string from user space and use it to initialize a pathname.
202 *
203 * @param thread The thread performing the operation.
204 * @param pathname A pointer to the pathname to initialize.
205 * @param userPath The string in user space.
206 * @return On success, `0`. On failure, `ERR` and `errno` is set.
207 */
208uint64_t thread_copy_from_user_pathname(thread_t* thread, pathname_t* pathname, const char* userPath);
209
210/**
211 * @brief Safely copy a null-terminated array of strings and their contents from user space into a string vector.
212 *
213 * @param thread The thread performing the operation.
214 * @param user The source array of strings in user space.
215 * @param out Output pointer to store the allocated array of strings in kernel space, must be freed by the caller.
216 * @param outAmount Output pointer to store the number of strings copied, can be `NULL`.
217 * @return On success, `0`. On failure, `ERR` and `errno` is set.
218 */
219uint64_t thread_copy_from_user_string_array(thread_t* thread, const char** user, char*** out, uint64_t* outAmount);
220
221/**
222 * @brief Atomically load a 64-bit value from a user-space atomic variable.
223 *
224 * Will pin the user pages in memory while performing the load and expand the user stack if necessary.
225 *
226 * @param thread The thread performing the operation.
227 * @param userObj The user-space atomic variable to load from.
228 * @param outValue Output pointer to store the loaded value.
229 * @return On success, `0`. On failure, `ERR` and `errno` is set.
230 */
231uint64_t thread_load_atomic_from_user(thread_t* thread, atomic_uint64_t* userObj, uint64_t* outValue);
232
233/**
234 * @brief Jump to a thread by calling `thread_load()` and then loading its interrupt frame.
235 *
236 * Must be done in assembly as it requires directly modifying registers.
237 *
238 * Will never return instead it ends up at `thread->frame.rip`.
239 *
240 * @param thread The thread to jump to.
241 */
242_NORETURN extern void thread_jump(thread_t* thread);
243
244/** @} */
int errno_t
Definition errno_t.h:4
uint64_t thread_copy_from_user_string_array(thread_t *thread, const char **user, char ***out, uint64_t *outAmount)
Safely copy a null-terminated array of strings and their contents from user space into a string vecto...
Definition thread.c:294
bool thread_is_note_pending(thread_t *thread)
Check if a thread has a note pending.
Definition thread.c:156
void thread_free(thread_t *thread)
Frees a thread structure.
Definition thread.c:124
uint64_t thread_send_note(thread_t *thread, const void *buffer, uint64_t count)
Send a note to a thread.
Definition thread.c:161
uint64_t thread_copy_from_user(thread_t *thread, void *dest, const void *userSrc, uint64_t length)
Safely copy data from user space.
Definition thread.c:188
void thread_load(thread_t *thread, interrupt_frame_t *frame)
Load state from a thread.
Definition thread.c:147
uint64_t thread_copy_to_user(thread_t *thread, void *dest, const void *userSrc, uint64_t length)
Safely copy data to user space.
Definition thread.c:206
_NORETURN void thread_jump(thread_t *thread)
Jump to a thread by calling thread_load() and then loading its interrupt frame.
uint64_t thread_load_atomic_from_user(thread_t *thread, atomic_uint64_t *userObj, uint64_t *outValue)
Atomically load a 64-bit value from a user-space atomic variable.
Definition thread.c:333
uint64_t thread_copy_from_user_terminated(thread_t *thread, const void *userArray, const void *terminator, uint8_t objectSize, uint64_t maxCount, void **outArray, uint64_t *outCount)
Safely copy a null-terminated array of objects from user space.
Definition thread.c:224
uint64_t thread_copy_from_user_pathname(thread_t *thread, pathname_t *pathname, const char *userPath)
Safely copy a string from user space and use it to initialize a pathname.
Definition thread.c:265
thread_t * thread_new(process_t *process)
Creates a new thread structure.
Definition thread.c:70
void thread_save(thread_t *thread, const interrupt_frame_t *frame)
Save state to a thread.
Definition thread.c:140
thread_state_t
Thread state enum.
Definition thread.h:30
void(* thread_kernel_entry_t)(void *arg)
Kernel thread entry point function type.
Definition thread.h:103
tid_t thread_kernel_create(thread_kernel_entry_t entry, void *arg)
Creates a new thread that runs in kernel mode and submits it to the scheduler.
Definition thread.c:97
@ THREAD_UNBLOCKING
Has started unblocking, used to prevent the same thread being unblocked multiple times.
Definition thread.h:35
@ THREAD_PRE_BLOCK
Has started the process of blocking but has not yet been given to a owner cpu.
Definition thread.h:33
@ THREAD_BLOCKED
Is blocking and waiting in one or multiple wait queues.
Definition thread.h:34
@ THREAD_PARKED
Is doing nothing, not in a queue, not blocking, think of it as "other".
Definition thread.h:31
@ THREAD_DYING
Definition thread.h:43
@ THREAD_ACTIVE
Is either running or ready to run.
Definition thread.h:32
__UINT64_TYPE__ tid_t
Thread Identifier.
Definition tid_t.h:12
#define _NORETURN
Definition config.h:28
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
static atomic_long count
Definition main.c:10
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
Trap Frame Structure.
Definition interrupt.h:143
A entry in a doubly linked list.
Definition list.h:36
Per-thread note queue.
Definition note.h:79
Pathname structure.
Definition path.h:137
Per-Thread performance context.
Definition perf.h:78
Process structure.
Definition process.h:158
Per-thread scheduler context.
Definition sched.h:370
Structure to define a stack in memory.
Per thread syscall context.
Definition syscall.h:107
Thread of execution structure.
Definition thread.h:63
perf_thread_ctx_t perf
Definition thread.h:82
list_entry_t processEntry
The entry for the parent process.
Definition thread.h:65
process_t * process
The parent process that the thread executes within.
Definition thread.h:64
_Atomic(thread_state_t) state
interrupt_frame_t frame
Definition thread.h:87
stack_pointer_t kernelStack
The kernel stack of the thread.
Definition thread.h:75
errno_t error
Definition thread.h:74
note_queue_t notes
Definition thread.h:80
syscall_ctx_t syscall
Definition thread.h:81
stack_pointer_t userStack
The user stack of the thread.
Definition thread.h:76
wait_client_t wait
Definition thread.h:78
tid_t id
The thread id, unique within a process_t.
Definition thread.h:66
sched_client_t sched
Definition thread.h:77
simd_ctx_t simd
Definition thread.h:79
Represents a thread in the waiting subsystem.
Definition wait.h:195