Skip to content

Commit 7fdcdbb

Browse files
committed
feat(kernel): migrate to HashMap
1 parent 060c473 commit 7fdcdbb

10 files changed

Lines changed: 50 additions & 31 deletions

File tree

docs/labs/0x03/tasks.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,16 +189,22 @@ impl Processor {
189189

190190
```rust
191191
pub struct ProcessManager {
192-
processes: RwLock<BTreeMap<ProcessId, Arc<Process>>>,
192+
processes: RwLock<HashMap<ProcessId, Arc<Process>, ahash::RandomState>>,
193193
ready_queue: Mutex<VecDeque<ProcessId>>,
194194
}
195195
```
196196

197197
其中 `processes` 字段用于存储所有的进程,`ready_queue` 字段则用于存储就绪的进程队列。`ProcessManager` 结构体被设计为“不可变”的,也就是说,它由 `RwLock``Mutex` 来提供内部可变性。
198198

199+
??? hint "`HashMap``ahash`"
200+
201+
在内核 `no_std` 环境下,可以使用 `hashbrown` 库提供的 `HashMap` 能力,它也是 Rust 标准库所使用的 HashMap 实现。
202+
203+
`ahash` 是一个专为 `HashMap` 设计的高性能哈希算法。在 `ProcessManager` 中,我们显式指定了 `ahash::RandomState` 作为哈希状态,以确保进程查找的高效性。
204+
199205
就绪队列的操作(`push``pop`)是需要对 `VecDeque` 进行修改,所以是在 `Mutex` 的保护下进行的,并没有读写操作的区别。
200206

201-
而进程列表只有 `insert` 操作需要对 `BTreeMap` 的可变引用,因此 `RwLock` 的保护下更加合适。
207+
而进程列表只有 `insert` 操作需要对 `HashMap` 的可变引用,因此 `RwLock` 的保护下更加合适。
202208

203209
`ProcessManager` 的不可变约束下,就可以通过 `spin::Once` 来定义一个全局的 `ProcessManager`,并在 `init()` 函数中初始化它:
204210

@@ -227,7 +233,7 @@ pub fn get_process_manager() -> &'static ProcessManager {
227233

228234
```rust
229235
pub fn new(init: Arc<Process>) -> Self {
230-
let mut processes = BTreeMap::new();
236+
let mut processes = HashMap::default();
231237
let ready_queue = VecDeque::new();
232238
let pid = init.pid();
233239

docs/labs/0x05/tasks.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -363,11 +363,11 @@ entry!(main);
363363
```rust
364364
pub struct ProcessManager {
365365
// ...
366-
wait_queue: Mutex<BTreeMap<ProcessId, BTreeSet<ProcessId>>>,
366+
wait_queue: Mutex<HashMap<ProcessId, BTreeSet<ProcessId>, ahash::RandomState>>,
367367
}
368368
```
369369

370-
其中,`BTreeMap` 的键值对应于被等待的进程 ID,`BTreeSet` 用于存储等待的进程 ID 的集合。
370+
其中,`HashMap` 的键值对应于被等待的进程 ID,`BTreeSet` 用于存储等待的进程 ID 的集合。
371371

372372
### 阻塞进程
373373

@@ -422,12 +422,12 @@ pub fn wait_pid(&self, pid: ProcessId) {
422422
}
423423
```
424424

425-
!!! tip "使用 `BTreeMap``entry` 方法"
425+
!!! tip "使用 `HashMap``entry` 方法"
426426

427-
`BTreeMap` 的 `entry` 方法可以用于获取一个键对应的值的可变引用,并可以通过 `or_default` 或者 `or_insert` 来插入一个默认值。
427+
`HashMap` 的 `entry` 方法可以用于获取一个键对应的值的可变引用,并可以通过 `or_default` 或者 `or_insert` 来插入一个默认值。
428428

429429
```rust
430-
let mut map: BTreeMap<u32, BTreeSet<u32>> = BTreeMap::new();
430+
let mut map: HashMap<u32, BTreeSet<u32>, ahash::RandomState> = HashMap::default();
431431
let entry = map.entry(42).or_default();
432432
entry.insert(2333);
433433
```
@@ -697,7 +697,7 @@ pub enum SemaphoreResult {
697697

698698
```rust
699699
pub struct SemaphoreSet {
700-
sems: BTreeMap<SemaphoreId, Mutex<Semaphore>>,
700+
sems: HashMap<SemaphoreId, Mutex<Semaphore>, ahash::RandomState>
701701
}
702702
```
703703

src/0x02/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ debug = false
1818
arrayvec = { version = "0.7", default-features = false }
1919
bit_field = "0.10"
2020
bitflags = "2.10"
21+
hashbrown = "0.16"
2122
lazy_static = { version = "1.4", features = ["spin_no_std"] }
2223
libm = "0.2"
2324
linked_list_allocator = "0.10"

src/0x03/crates/kernel/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ version.workspace = true
55
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
66

77
[dependencies]
8+
ahash = { workspace = true }
89
bit_field = { workspace = true }
910
bitflags = { workspace = true }
1011
boot = { workspace = true }
1112
crossbeam-queue = { workspace = true }
13+
hashbrown = { workspace = true }
1214
lazy_static = { workspace = true }
1315
libm = { workspace = true }
1416
linked_list_allocator = { workspace = true }

src/0x03/crates/kernel/src/proc/data.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,26 @@
1-
use alloc::{collections::BTreeMap, sync::Arc};
1+
use hashbrown::HashMap;
22
use spin::RwLock;
3-
use x86_64::structures::paging::{
4-
page::{PageRange, PageRangeInclusive},
5-
Page,
6-
};
73

84
use super::*;
5+
use crate::resource::ResourceSet;
96

107
#[derive(Debug, Clone)]
118
pub struct ProcessData {
129
// shared data
13-
pub(super) env: Arc<RwLock<BTreeMap<String, String>>>,
10+
pub(super) env: Arc<RwLock<HashMap<String, String, ahash::RandomState>>>,
1411
}
1512

1613
impl Default for ProcessData {
1714
fn default() -> Self {
18-
Self {
19-
env: Arc::new(RwLock::new(BTreeMap::new())),
20-
}
15+
Self::new()
2116
}
2217
}
2318

2419
impl ProcessData {
2520
pub fn new() -> Self {
26-
Self::default()
21+
Self {
22+
env: Arc::new(RwLock::new(HashMap::default())),
23+
}
2724
}
2825

2926
pub fn env(&self, key: &str) -> Option<String> {

src/0x03/crates/kernel/src/proc/manager.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::memory::{
44
allocator::{ALLOCATOR, HEAP_SIZE},
55
get_frame_alloc_for_sure, PAGE_SIZE,
66
};
7+
use hashbrown::HashMap;
78
use alloc::{collections::*, format};
89
use spin::{Mutex, RwLock};
910

@@ -25,13 +26,13 @@ pub fn get_process_manager() -> &'static ProcessManager {
2526
}
2627

2728
pub struct ProcessManager {
28-
processes: RwLock<BTreeMap<ProcessId, Arc<Process>>>,
29+
processes: RwLock<HashMap<ProcessId, Arc<Process>, ahash::RandomState>>,
2930
ready_queue: Mutex<VecDeque<ProcessId>>,
3031
}
3132

3233
impl ProcessManager {
3334
pub fn new(init: Arc<Process>) -> Self {
34-
let mut processes = BTreeMap::new();
35+
let mut processes = HashMap::default();
3536
let ready_queue = VecDeque::new();
3637
let pid = init.pid();
3738

src/0x03/crates/kernel/src/proc/pid.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use core::sync::atomic::{AtomicU16, Ordering};
22

3-
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
3+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
44
pub struct ProcessId(pub u16);
55

66
impl ProcessId {

src/0x03/crates/kernel/src/proc/process.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use x86_64::structures::paging::*;
1010
#[derive(Clone)]
1111
pub struct Process {
1212
pid: ProcessId,
13-
inner: Arc<RwLock<ProcessInner>>,
13+
inner: RwLock<ProcessInner>,
1414
}
1515

1616
pub struct ProcessInner {
@@ -70,7 +70,7 @@ impl Process {
7070
// create process struct
7171
Arc::new(Self {
7272
pid,
73-
inner: Arc::new(RwLock::new(inner)),
73+
inner: RwLock::new(inner),
7474
})
7575
}
7676

@@ -165,7 +165,7 @@ impl ProcessInner {
165165
}
166166

167167
impl core::ops::Deref for Process {
168-
type Target = Arc<RwLock<ProcessInner>>;
168+
type Target = RwLock<ProcessInner>;
169169

170170
fn deref(&self) -> &Self::Target {
171171
&self.inner

src/0x04/crates/kernel/src/utils/resource.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use alloc::string::String;
2+
use hashbrown::HashMap;
23

34
#[derive(Debug, Clone)]
45
pub enum StdIO {
@@ -9,13 +10,13 @@ pub enum StdIO {
910

1011
#[derive(Debug)]
1112
pub struct ResourceSet {
12-
pub handles: BTreeMap<u8, Mutex<Resource>>,
13+
pub(crate) handles: HashMap<u8, Mutex<Resource>, ahash::RandomState>,
1314
}
1415

1516
impl Default for ResourceSet {
1617
fn default() -> Self {
1718
let mut res = Self {
18-
handles: BTreeMap::new(),
19+
handles: HashMap::default(),
1920
};
2021

2122
res.open(Resource::Console(StdIO::Stdin));

src/0x05/crates/kernel/src/proc/sync.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
use super::ProcessId;
21
use alloc::collections::*;
2+
3+
use hashbrown::HashMap;
34
use spin::Mutex;
45

5-
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
6+
use super::ProcessId;
7+
8+
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
69
pub struct SemaphoreId(u32);
710

811
impl SemaphoreId {
@@ -58,9 +61,17 @@ impl Semaphore {
5861
}
5962
}
6063

61-
#[derive(Debug, Default)]
64+
#[derive(Debug)]
6265
pub struct SemaphoreSet {
63-
sems: BTreeMap<SemaphoreId, Mutex<Semaphore>>,
66+
sems: HashMap<SemaphoreId, Mutex<Semaphore>, ahash::RandomState>,
67+
}
68+
69+
impl Default for SemaphoreSet {
70+
fn default() -> Self {
71+
Self {
72+
sems: HashMap::with_hasher(ahash::RandomState::new()),
73+
}
74+
}
6475
}
6576

6677
impl SemaphoreSet {

0 commit comments

Comments
 (0)