Skip to content

Commit 4ba624c

Browse files
MRNIUclaude
andcommitted
feat: rewrite TCB ownership prototype to Arc<TCB> model & complete P2 steps
Replace raw-pointer TCB ownership with Arc<TaskControlBlock> pattern (aligned with rCore-Tutorial-v3), eliminating use-after-free risks. Mutable fields protected via interior SpinLock<TcbInner>. All 6 prototype tests pass. Also suppress dead_code warnings for items used in later phases and remove unnecessary unsafe blocks in riscv interrupt ops. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 92c509d commit 4ba624c

10 files changed

Lines changed: 198 additions & 143 deletions

File tree

docs/rust-rewrite/P2-核心基础设施.md

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -112,35 +112,25 @@ end note
112112
| `VFS_MANAGER` | `FileSystemInit()` | DEVICE_MANAGER |
113113

114114
## 实现步骤
115-
- [ ] 步骤 1:实现 `SpinLock`,在加锁/解锁时禁用/启用中断
116-
- [ ] 步骤 2:为 SpinLock 编写单元测试(加锁、解锁、guard 释放)
117-
- [ ] 步骤 3:实现 ELF 解析器(解析符号表、字符串表)
118-
- [ ] 步骤 4:为 ELF 解析器编写单元测试(使用测试二进制数据)
119-
- [ ] 步骤 5:实现带有 DumpStack 支持的 panic 处理程序
120-
- [ ] 步骤 6:**TCB/调度器所有权原型(强制准入门槛)**
121-
122-
在阶段 5 开始之前,验证 TCB 所有权模型。创建一个最小原型:
123-
```rust
124-
// 证明 TaskControlBlock 可以:
125-
// 1. 存储在全局任务表中 (BTreeMap<Pid, Box<TaskControlBlock>>)
126-
// 2. 被调度器运行队列引用 (原始指针或 Pin<&mut TCB>)
127-
// 3. 被 Per-CPU "current_task" 指针引用
128-
// 4. 在 SpinLock 保护下安全访问
129-
//
130-
// 原型必须演示:
131-
// - 将 TCB 入队/出队到模拟调度器
132-
// - 在两个 TCB 之间切换 "current_task" 指针
133-
// - 通过任务表和调度器访问 TCB 字段
134-
//
135-
// 决策:记录是否使用:
136-
// (a) UnsafeCell + 原始指针,配合 SpinLock 保护的访问(可能性大)
137-
// (b) Arc<SpinLock<TCB>> (对调度器热路径来说开销太大)
138-
// (c) 侵入式链表 (最像 C,但最不符合 Rust 习惯)
139-
//
140-
// 该原型必须在阶段 5 推进前通过。
141-
```
142-
143-
- [ ] 步骤 7:提交
115+
- [x] 步骤 1:实现 `SpinLock`,在加锁/解锁时禁用/启用中断
116+
- [x] 步骤 2:为 SpinLock 编写单元测试(加锁、解锁、guard 释放)—— 6 个测试
117+
- [x] 步骤 3:实现 ELF 解析器(解析符号表、字符串表)
118+
- [x] 步骤 4:为 ELF 解析器编写单元测试(使用测试二进制数据)—— 4 个测试
119+
- [x] 步骤 5:实现带有 DumpStack 支持的 panic 处理程序(DWARF 回溯 + 观察者模式)
120+
- [x] 步骤 6:**TCB/调度器所有权原型(强制准入门槛)**
121+
122+
**决策(2026-03-25 生态调研后更新):采用 Arc\<TCB\> 模式(方案 b),与 rCore-Tutorial-v3 一致。**
123+
124+
原型验证了:
125+
1. `Arc<TaskControlBlock>` 存储在 `BTreeMap<Pid, Arc<TCB>>`(任务表)
126+
2. 调度器持有 `Arc` clone(`VecDeque<Arc<TCB>>`
127+
3. Per-CPU `current_task: Option<Arc<TCB>>` 切换
128+
4. 从任务表移除后调度器仍持有有效引用(Arc 引用计数保护,无 use-after-free)
129+
5. 可变字段通过 `SpinLock<TcbInner>` 保护
130+
131+
6 个测试全部通过。
132+
133+
- [x] 步骤 7:提交
144134

145135
## QEMU 预期输出
146136
```

src/arch/aarch64/init.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,6 @@ pub fn arch_init(_argc: i32, argv: *const *const u8) {
8686
logging::flush();
8787
}
8888

89+
/// TODO(P4): 从核架构初始化(当前为空)
90+
#[allow(dead_code)]
8991
pub fn arch_init_smp(_argc: i32, _argv: *const *const u8) {}

src/arch/riscv64/init.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,6 @@ pub fn arch_init(_argc: i32, argv: *const *const u8) {
5656
logging::flush();
5757
}
5858

59+
/// TODO(P4): 从核架构初始化(当前为空)
60+
#[allow(dead_code)]
5961
pub fn arch_init_smp(_argc: i32, _argv: *const *const u8) {}

src/elf.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,14 @@ impl KernelElf {
109109
}
110110

111111
#[must_use]
112+
#[allow(dead_code)] // P3+ panic backtrace 使用
112113
pub fn elf_size(&self) -> usize {
113114
self.data.len()
114115
}
115116

116117
/// 返回 `.symtab` 中符号的数量;若解析失败则返回 0。
117118
#[must_use]
119+
#[allow(dead_code)] // P3+ panic backtrace 使用
118120
pub fn symbol_count(&self) -> usize {
119121
let Ok(elf) = ElfBytes::<AnyEndian>::minimal_parse(self.data) else {
120122
return 0;
@@ -130,6 +132,7 @@ impl KernelElf {
130132
/// 返回最接近且不超过 `addr` 的符号名。
131133
/// 若未找到匹配符号,则返回 `None`。
132134
#[must_use]
135+
#[allow(dead_code)] // P3+ panic backtrace 使用
133136
pub fn lookup_symbol(&self, addr: u64) -> Option<&str> {
134137
let elf = ElfBytes::<AnyEndian>::minimal_parse(self.data).ok()?;
135138
let (symtab, strtab) = elf.symbol_table().ok()??;

src/fdt.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ impl<'a> KernelFdt<'a> {
5353
Ok((region.address, region.len))
5454
}
5555

56+
/// TODO(P4): 定时器初始化时读取此值
57+
#[allow(dead_code)]
5658
pub fn timebase_frequency(&self) -> KResult<u32> {
5759
let fdt = parse_fdt!(self.fdt_addr)?;
5860
let cpus = fdt

src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
#![cfg_attr(not(test), no_main)]
33
#![cfg_attr(not(test), feature(alloc_error_handler))]
44
#![feature(sync_unsafe_cell)]
5+
// 测试模式下部分模块不编译(arch, fdt, lang_items),导致它们的消费者
6+
// 产生 dead_code 警告。这些代码在目标架构上被正常使用。
7+
#![cfg_attr(test, allow(dead_code))]
58

69
#[cfg(not(test))]
710
mod arch;

src/per_cpu.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use crate::config;
22
use core::cell::SyncUnsafeCell;
33
use spin::Once;
44

5+
// P3 将字段类型升级为 PhysAddr,P4+ 读取这些字段
6+
#[allow(dead_code)]
57
pub struct BasicInfo {
68
pub physical_memory_addr: u64,
79
pub physical_memory_size: usize,
@@ -14,6 +16,7 @@ pub struct BasicInfo {
1416

1517
impl BasicInfo {
1618
#[must_use]
19+
#[allow(dead_code)] // P1 init.rs 中通过 BASIC_INFO.call_once() 使用
1720
pub const fn new() -> Self {
1821
Self {
1922
physical_memory_addr: 0,

src/sync/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
mod spinlock;
22

3-
pub use spinlock::{SpinLock, SpinLockGuard};
3+
pub use spinlock::SpinLock;
4+
#[allow(unused_imports)] // P3+ 会使用
5+
pub use spinlock::SpinLockGuard;

src/sync/spinlock.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ mod interrupt_ops {
2626

2727
#[inline(always)]
2828
pub fn disable() {
29-
unsafe { riscv::interrupt::supervisor::disable() };
29+
riscv::interrupt::supervisor::disable();
3030
}
3131

3232
#[inline(always)]
3333
pub fn enable() {
34-
unsafe { riscv::interrupt::supervisor::enable() };
34+
riscv::interrupt::supervisor::enable();
3535
}
3636
}
3737

0 commit comments

Comments
 (0)