preemptive_threads/
thread.rs

1
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}