good_os_framework/task/
thread.rs

1use alloc::sync::Arc;
2use alloc::sync::Weak;
3use core::fmt::Debug;
4use core::sync::atomic::{AtomicU64, Ordering};
5use spin::RwLock;
6
7use super::context::Context;
8use super::process::WeakSharedProcess;
9use super::process::KERNEL_PROCESS;
10use super::scheduler::SCHEDULER;
11use super::stack::{KernelStack, UserStack};
12use crate::arch::gdt::Selectors;
13use crate::drivers::fpu::FpState;
14use crate::memory::KERNEL_PAGE_TABLE;
15
16pub(super) type SharedThread = Arc<RwLock<Thread>>;
17pub(super) type WeakSharedThread = Weak<RwLock<Thread>>;
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
20pub struct ThreadId(pub u64);
21
22impl ThreadId {
23    fn new() -> Self {
24        static NEXT_ID: AtomicU64 = AtomicU64::new(0);
25        ThreadId(NEXT_ID.fetch_add(1, Ordering::Relaxed))
26    }
27}
28
29#[derive(Debug, Copy, Clone, PartialEq, Eq)]
30pub enum ThreadState {
31    Running,
32    Ready,
33    Blocked,
34    Waiting,
35    Terminated,
36}
37
38impl ThreadState {
39    pub fn is_active(&self) -> bool {
40        match self {
41            ThreadState::Running | ThreadState::Ready => true,
42            _ => false,
43        }
44    }
45}
46
47#[allow(dead_code)]
48pub struct Thread {
49    pub id: ThreadId,
50    pub state: ThreadState,
51    pub kernel_stack: KernelStack,
52    pub context: Context,
53    pub process: WeakSharedProcess,
54    pub fpu_context: FpState,
55}
56
57impl Thread {
58    /// Creates a new thread.
59    /// Don't call this function directly, use `Thread::new_init_thread`,`Thread::new_user_thread` or `Thread::new_kernel_thread` instead.
60    pub fn new(process: WeakSharedProcess) -> Self {
61        let thread = Thread {
62            id: ThreadId::new(),
63            state: ThreadState::Ready,
64            context: Context::default(),
65            kernel_stack: KernelStack::new(),
66            process,
67            fpu_context: FpState::default(),
68        };
69
70        thread
71    }
72
73    /// Creates a new initial thread.
74    pub fn get_init_thread() -> WeakSharedThread {
75        let thread = Self::new(Arc::downgrade(&KERNEL_PROCESS));
76        let thread = Arc::new(RwLock::new(thread));
77        KERNEL_PROCESS.write().threads.push_back(thread.clone());
78        //SCHEDULER.lock().add(Arc::downgrade(&thread));
79        Arc::downgrade(&thread)
80    }
81
82
83    /// Creates a new kernel thread.
84    pub fn new_kernel_thread(function: fn()) {
85        let mut thread = Self::new(Arc::downgrade(&KERNEL_PROCESS));
86
87        thread.context.init(
88            function as usize,
89            thread.kernel_stack.end_address(),
90            KERNEL_PAGE_TABLE.lock().physical_address,
91            Selectors::get_kernel_segments(),
92        );
93
94        
95
96        let thread = Arc::new(RwLock::new(thread));
97        
98        
99        SCHEDULER.lock().add(Arc::downgrade(&thread));
100        KERNEL_PROCESS.write().threads.push_back(thread);
101        
102    }
103
104    /// Creates a new user thread.
105    pub fn new_user_thread(process: WeakSharedProcess, entry_point: usize) {
106        let mut thread = Self::new(process.clone());
107        //log::info!("New : {}", thread.id.0);
108        let process = process.upgrade().unwrap();
109        let mut process = process.write();
110        let user_stack = UserStack::new(&mut process.page_table);
111
112        thread.context.init(
113            entry_point,
114            user_stack.end_address,
115            process.page_table.physical_address,
116            Selectors::get_user_segments(),
117        );
118
119        let thread = Arc::new(RwLock::new(thread));
120        SCHEDULER.lock().add(Arc::downgrade(&thread));
121        process.threads.push_back(thread.clone());
122    }
123}
124
125