preemptive_threads/
thread.rs1
2pub type ThreadId = usize;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum ThreadState {
6 Ready,
7 Running,
8 Blocked,
9 Finished,
10}
11
12#[repr(C)]
13pub struct ThreadContext {
14 pub rsp: u64,
15 pub rbp: u64,
16 pub rbx: u64,
17 pub r12: u64,
18 pub r13: u64,
19 pub r14: u64,
20 pub r15: u64,
21 pub rflags: u64,
22 pub rip: u64,
23}
24
25pub struct Thread {
26 pub id: ThreadId,
27 pub state: ThreadState,
28 pub context: ThreadContext,
29 pub stack: &'static mut [u8],
30 pub stack_top: *mut u8,
31 pub stack_bottom: *mut u8,
32 pub entry_point: fn(),
33 pub priority: u8,
34 pub stack_guard: u64,
35 pub join_waiters: [Option<ThreadId>; 4],
36}
37
38impl Thread {
39 pub const STACK_SIZE: usize = 64 * 1024;
40
41 pub fn new(
42 id: ThreadId,
43 stack: &'static mut [u8],
44 entry_point: fn(),
45 priority: u8,
46 ) -> Self {
47 let stack_top = unsafe { stack.as_mut_ptr().add(stack.len()) };
48 let stack_bottom = stack.as_mut_ptr();
49 let stack_guard = 0xDEADBEEFCAFEBABE;
50
51 unsafe {
52 core::ptr::write(stack_bottom as *mut u64, stack_guard);
53 }
54
55 let mut thread = Thread {
56 id,
57 state: ThreadState::Ready,
58 context: ThreadContext {
59 rsp: 0,
60 rbp: 0,
61 rbx: 0,
62 r12: 0,
63 r13: 0,
64 r14: 0,
65 r15: 0,
66 rflags: 0x202,
67 rip: 0,
68 },
69 stack,
70 stack_top,
71 stack_bottom,
72 entry_point,
73 priority,
74 stack_guard,
75 join_waiters: [None; 4],
76 };
77
78 thread.initialize_stack();
79 thread
80 }
81
82 fn initialize_stack(&mut self) {
83 unsafe {
84 let stack_ptr = self.stack_top as *mut u64;
85
86 let stack_ptr = stack_ptr.sub(1);
87 *stack_ptr = thread_wrapper as usize as u64;
88
89 let stack_ptr = stack_ptr.sub(1);
90 *stack_ptr = 0;
91
92 self.context.rsp = stack_ptr as u64;
93 self.context.rip = thread_entry as usize as u64;
94 }
95 }
96
97 pub fn is_runnable(&self) -> bool {
98 self.state == ThreadState::Ready || self.state == ThreadState::Running
99 }
100
101 pub fn check_stack_overflow(&self) -> bool {
102 unsafe {
103 let guard_value = core::ptr::read(self.stack_bottom as *const u64);
104 guard_value != self.stack_guard
105 }
106 }
107}
108
109extern "C" fn thread_entry() {
110 crate::sync::exit_thread();
111}
112
113extern "C" fn thread_wrapper() -> ! {
114 crate::sync::exit_thread();
115}