os/kernel/task/
ktask.rs

1//! 内核任务相关功能实现
2//!
3//! 包括内核线程创建、等待、执行用户程序等功能
4//! 内核任务不具备用户态任务的内存空间和权限
5//! 仅在内核态运行
6use core::{hint, sync::atomic::Ordering};
7
8use alloc::sync::Arc;
9
10use crate::{
11    arch::{intr::disable_interrupts, trap::restore},
12    kernel::{
13        SCHEDULER, TaskState,
14        cpu::current_cpu,
15        scheduler::Scheduler,
16        task::{TASK_MANAGER, TaskStruct, task_manager::TaskManagerTrait},
17    },
18    mm::{
19        frame_allocator::{alloc_contig_frames, alloc_frame},
20        memory_space::MemorySpace,
21    },
22    sync::SpinLock,
23};
24
25/// 创建一个新的内核线程并返回其 Arc 包装
26///
27/// 该函数负责:
28/// 1. 分配 Task 结构体本身,并用 Arc 包装
29/// 2. 分配内核栈物理页帧 (FrameTracker)
30/// 3. 将内核栈映射到虚拟地址空间 (VMM 逻辑)
31/// 4. 初始化 Task Context,设置栈指针和入口点
32/// 5. 将新的 Task 加入调度器队列
33///
34/// # 参数
35/// * `entry_point`: 线程开始执行的函数地址
36///
37/// # 返回值
38/// Task id
39#[allow(dead_code)]
40pub fn kthread_spawn(entry_point: fn()) -> u32 {
41    let tid = TASK_MANAGER.lock().allocate_tid();
42    let (pid, ppid, signal_handlers, blocked, signal, uts, rlimit, fd_table, fs) = {
43        let cur_cpu = current_cpu().lock();
44        let cur_task = cur_cpu.current_task.as_ref().unwrap();
45        let cur_task = cur_task.lock();
46        (
47            cur_task.pid,
48            cur_task.ppid,
49            cur_task.signal_handlers.clone(),
50            cur_task.blocked,
51            cur_task.shared_pending.clone(),
52            cur_task.uts_namespace.clone(),
53            cur_task.rlimit.clone(),
54            cur_task.fd_table.clone(),
55            cur_task.fs.clone(),
56        )
57    };
58
59    let kstack_tracker = alloc_contig_frames(4).expect("kthread_spawn: failed to alloc kstack");
60    let trap_frame_tracker = alloc_frame().expect("kthread_spawn: failed to alloc trap_frame");
61
62    // 分配 Task 结构体和内核栈
63    let task = TaskStruct::ktask_create(
64        tid,
65        pid,
66        ppid,
67        TaskStruct::empty_children(),
68        kstack_tracker,
69        trap_frame_tracker,
70        signal_handlers,
71        blocked,
72        signal,
73        uts,
74        rlimit,
75        fd_table,
76        fs,
77    );
78
79    let tf = task.trap_frame_ptr.load(Ordering::SeqCst);
80    // SAFETY: 此时 trap_frame_tracker 已经分配完毕且不可变更,所有权在 task 中,指针有效
81    unsafe {
82        (*tf).set_kernel_trap_frame(
83            entry_point as usize,
84            super::terminate_task as usize,
85            task.kstack_base,
86        );
87    }
88    let tid = task.tid;
89    let task = task.into_shared();
90
91    // 将任务加入调度器和任务管理器
92    TASK_MANAGER.lock().add_task(task.clone());
93    SCHEDULER.lock().add_task(task);
94
95    tid
96}
97
98/// 等待指定 tid 的任务结束
99/// 该函数会阻塞调用者直到目标任务状态变为 Stopped
100/// 如果目标任务不存在则立即返回错误码
101/// 任务结束后会将其从任务管理器中移除
102/// 并将其返回值写入调用者提供的指针地址
103/// # 参数
104/// * `tid`: 目标任务的任务 ID
105/// * `return_value_ptr`: 用于存放目标任务返回值的指针
106/// # 返回值
107/// 成功返回 0,失败返回 -1
108/// # 安全性
109/// 调用者必须保证 `return_value_ptr` 指向的内存是合法可写的
110pub unsafe fn kthread_join(tid: u32, return_value_ptr: Option<usize>) -> i32 {
111    loop {
112        let task_opt = TASK_MANAGER.lock().get_task(tid);
113        if let Some(task) = task_opt {
114            let t = task.lock();
115            if t.state == TaskState::Zombie {
116                if let Some(rv) = t.exit_code {
117                    // SAFETY: 调用者保证了 return_value_ptr 指向的内存是合法可写的
118                    unsafe {
119                        if let Some(ptr) = return_value_ptr {
120                            let ptr = ptr as *mut usize;
121                            ptr.write_volatile(rv as usize);
122                        }
123                    }
124                }
125                TASK_MANAGER.lock().release_task(task.clone());
126                return 0; // 成功结束
127            }
128        } else {
129            return -1; // 任务不存在,直接返回
130        }
131        // 暂时的忙等待
132        hint::spin_loop();
133    }
134}
135
136/// 在内核任务中执行 execve,加载并运行指定路径的 ELF 可执行文件
137/// 该函数不会返回,执行成功后会切换到新程序的入口点
138/// # 参数
139/// * `path`: ELF 可执行文件的路径
140/// * `argv`: 传递给新程序的参数列表
141/// * `envp`: 传递给新程序的环境变量列表
142pub fn kernel_execve(path: &str, argv: &[&str], envp: &[&str]) -> ! {
143    // 1. 加载 ELF 文件
144    crate::pr_info!("[kernel_execve] Loading: {}", path);
145    let data = crate::vfs::vfs_load_elf(path).expect("kernel_execve: file not found");
146    crate::pr_info!("[kernel_execve] Loaded {} bytes", data.len());
147
148    // 2. 从 ELF 创建内存空间
149    let (space, entry, sp, phdr_addr, phnum, phent) = MemorySpace::from_elf(&data)
150        .expect("kernel_execve: failed to create memory space from ELF");
151    crate::pr_info!("[kernel_execve] Created memory space, entry=0x{:x}", entry);
152
153    // 3. 包装内存空间
154    let space = Arc::new(SpinLock::new(space));
155    // 换掉当前任务的地址空间,e.g. 切换 satp
156    current_cpu().lock().switch_space(space.clone());
157
158    let task = {
159        let cpu = current_cpu().lock();
160        cpu.current_task.as_ref().unwrap().clone()
161    };
162    // 在restore之前不可发生中断
163    // execve伪造进程上下文用的trapframe和当前进程的是同一个
164    // 这时候发生中断会破坏创建到一半/创建好的的上下文
165    // 不必显式恢复中断,它会在restore中由sret指令自动恢复
166    unsafe { disable_interrupts() };
167    {
168        let mut t = task.lock();
169        t.execve(space, entry, sp, argv, envp, phdr_addr, phnum, phent);
170    }
171    crate::pr_info!("[kernel_execve] Switching to user mode");
172
173    let tfp = task.lock().trap_frame_ptr.load(Ordering::SeqCst);
174    // SAFETY: tfp 指向的内存已经被分配且由当前任务拥有
175    // 直接按 trapframe 状态恢复并 sret 到用户态
176    unsafe {
177        restore(&*tfp);
178    }
179    unreachable!("kernel_execve: should not return");
180}
181
182#[cfg(test)]
183mod tests {
184    // TODO: kthread_spawn 内部依赖全局状态CPU, 现在无法进行测试
185    #![allow(dead_code)]
186    // use alloc::vec::Vec;
187
188    use super::*;
189    use crate::{
190        kassert,
191        kernel::task::{SharedTask, TASK_MANAGER},
192        test_case,
193    };
194    // use core::sync::atomic::Ordering;
195
196    // 创建一个简单的空函数作为 kernel 线程入口
197    fn dummy_thread() {}
198
199    fn mk_task(tid: u32) -> SharedTask {
200        TaskStruct::new_dummy_task(tid).into_shared()
201    }
202
203    // 测试 kthread_spawn:应分配 tid 并放入任务管理器
204    test_case!(test_kthread_spawn_basic, {
205        current_cpu().lock().current_task = Some(mk_task(1));
206        let tid = kthread_spawn(dummy_thread);
207        kassert!(tid != 0);
208        let task_opt = TASK_MANAGER.lock().get_task(tid);
209        kassert!(task_opt.is_some());
210        let t = task_opt.unwrap();
211        let g = t.lock();
212        kassert!(g.tid == tid);
213        kassert!(g.is_kernel_thread());
214    });
215
216    // 测试 kthread_join 成功路径:预置一个 Stopped 状态的任务与返回值
217    // test_case!(test_kthread_join_success, {
218    //     // 预创建任务
219    //     let tid = TASK_MANAGER.lock().allocate_tid();
220    //     let kstack_tracker =
221    //         crate::mm::frame_allocator::physical_page_alloc_contiguous(1).expect("alloc kstack");
222    //     let trap_frame_tracker =
223    //         crate::mm::frame_allocator::physical_page_alloc().expect("alloc trap_frame");
224    //     let task = TaskStruct::ktask_create(
225    //         tid,
226    //         tid,
227    //         0,
228    //         kstack_tracker,
229    //         trap_frame_tracker,
230    //         dummy_thread as usize,
231    //     );
232    //     let shared = into_shared(task);
233    //     {
234    //         let mut g = shared.lock();
235    //         g.state = TaskState::Stopped;
236    //         g.return_value = Some(0xDEAD_BEEF);
237    //     }
238    //     TASK_MANAGER.lock().add_task(shared.clone());
239    //     SCHEDULER.lock().add_task(shared);
240
241    //     // 为返回值提供缓冲区
242    //     let mut rv_slot: usize = 0;
243    //     let rc = kthread_join(tid, Some(&mut rv_slot as *mut usize as usize));
244    //     kassert!(rc == 0);
245    //     kassert!(rv_slot == 0xDEAD_BEEF);
246    //     // 任务应已从管理器移除
247    //     kassert!(TASK_MANAGER.lock().get_task(tid).is_none());
248    // });
249
250    // 测试 kthread_join 失败路径:不存在的 tid
251    test_case!(test_kthread_join_not_found, {
252        // 选择一个极小概率已存在的高 tid(或先确保不存在)
253        let missing_tid = 0xFFFF_FFFFu32;
254        kassert!(TASK_MANAGER.lock().get_task(missing_tid).is_none());
255        let rc = unsafe { kthread_join(missing_tid, None) };
256        kassert!(rc == -1);
257    });
258}