Skip to content

Commit 89fd5bb

Browse files
committed
ch5 ok
1 parent fee14e2 commit 89fd5bb

File tree

12 files changed

+430
-32
lines changed

12 files changed

+430
-32
lines changed

.github/workflows/build.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ jobs:
3131
container:
3232
image: duskmoon/dev-env:rcore-ci
3333
steps:
34+
- name: Remove Cargo proxy config
35+
run: |
36+
unset RUSTUP_DIST_SERVER
37+
unset RUSTUP_UPDATE_ROOT
38+
unset CARGO_HTTP_MULTIPLEXING
39+
# 删除或重置全局配置
40+
rm ${CARGO_HOME}/config.toml || true
41+
rm -rf rm ${CARGO_HOME}/registry/* || true
3442
- uses: actions/checkout@v4
3543
- name: Run tests
3644
run: |

os/src/config.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,6 @@ pub const CLOCK_FREQ: usize = 12500000;
2323
pub const MEMORY_END: usize = 0x88000000;
2424
/// The base address of control registers in Virtio_Block device
2525
pub const MMIO: &[(usize, usize)] = &[(0x10001000, 0x1000)];
26+
27+
/// BigStride
28+
pub const BIG_STRIDE: usize = 1000;

os/src/mm/memory_set.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,32 @@ impl MemorySet {
318318
false
319319
}
320320
}
321+
322+
/// find target area by start_va, then insert it to areas
323+
pub fn find_area_insert(&mut self, start_va: VirtAddr, end_va: VirtAddr, permission: MapPermission) -> bool {
324+
if let Some(_area) = self.areas.iter().find(|area| {
325+
area.vpn_range.get_start() < end_va.ceil() && area.vpn_range.get_end() > start_va.floor()
326+
}) {
327+
debug!("!!! find area has been used !!!");
328+
false
329+
} else {
330+
debug!("!!! area not be used, insert it!!!");
331+
self.insert_framed_area(start_va, end_va, permission);
332+
true
333+
}
334+
}
335+
/// find target area by start_va, then remove it from areas
336+
pub fn find_area_remove(&mut self, start_va: VirtAddr, end_va: VirtAddr) -> bool {
337+
if let Some(index) = self.areas.iter().position(|area| {
338+
area.vpn_range.get_start() == start_va.floor() && area.vpn_range.get_end() == end_va.ceil()
339+
}) {
340+
self.areas[index].unmap(&mut self.page_table);
341+
self.areas.remove(index);
342+
true
343+
} else {
344+
false
345+
}
346+
}
321347
}
322348
/// map area structure, controls a contiguous piece of virtual memory
323349
pub struct MapArea {

os/src/mm/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub use memory_set::remap_test;
1919
pub use memory_set::{kernel_token, MapPermission, MemorySet, KERNEL_SPACE};
2020
use page_table::PTEFlags;
2121
pub use page_table::{
22-
translated_byte_buffer, translated_ref, translated_refmut, translated_str, PageTable,
22+
translated_byte_buffer, translated_ref, translated_refmut, translated_physaddr, translated_str, PageTable,
2323
PageTableEntry, UserBuffer, UserBufferIterator,
2424
};
2525

os/src/mm/page_table.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,21 @@ use bitflags::*;
88
bitflags! {
99
/// page table entry flags
1010
pub struct PTEFlags: u8 {
11+
/// Valid
1112
const V = 1 << 0;
13+
/// Readable
1214
const R = 1 << 1;
15+
/// Writable
1316
const W = 1 << 2;
17+
/// eXecutable
1418
const X = 1 << 3;
19+
/// User
1520
const U = 1 << 4;
21+
/// Global
1622
const G = 1 << 5;
23+
/// Accessed
1724
const A = 1 << 6;
25+
/// Dirty
1826
const D = 1 << 7;
1927
}
2028
}
@@ -219,6 +227,19 @@ pub fn translated_refmut<T>(token: usize, ptr: *mut T) -> &'static mut T {
219227
.get_mut()
220228
}
221229

230+
/// translate a ptr and return its mut
231+
pub fn translated_physaddr(token: usize, ptr: *const u8) -> PhysAddr {
232+
let page_table = PageTable::from_token(token);
233+
let va = VirtAddr::from(ptr as usize);
234+
let vpn = va.floor();
235+
let ppn: PhysPageNum = page_table.translate(vpn).unwrap().ppn();
236+
let pa: PhysAddr = ppn.into();
237+
238+
let offset = va.page_offset();
239+
let pa_offset = (pa.0 + offset).into();
240+
return pa_offset;
241+
}
242+
222243
/// An abstraction over a buffer passed from user space to kernel space
223244
pub struct UserBuffer {
224245
/// A list of buffers
@@ -275,4 +296,4 @@ impl Iterator for UserBufferIterator {
275296
Some(r)
276297
}
277298
}
278-
}
299+
}

os/src/syscall/process.rs

Lines changed: 94 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@
33
use alloc::sync::Arc;
44

55
use crate::{
6-
fs::{open_file, OpenFlags},
7-
mm::{translated_refmut, translated_str},
8-
task::{
6+
fs::{open_file, OpenFlags}, mm::{translated_physaddr, translated_refmut, translated_str, MapPermission, VirtAddr}, task::{
97
add_task, current_task, current_user_token, exit_current_and_run_next,
10-
suspend_current_and_run_next,
11-
},
8+
suspend_current_and_run_next, TaskControlBlock
9+
}, timer::get_time_us
1210
};
1311

1412
#[repr(C)]
@@ -78,6 +76,7 @@ pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
7876
.iter()
7977
.any(|p| pid == -1 || pid as usize == p.getpid())
8078
{
79+
debug!("no such pid[{}]", pid);
8180
return -1;
8281
// ---- release current PCB
8382
}
@@ -95,8 +94,10 @@ pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
9594
let exit_code = child.inner_exclusive_access().exit_code;
9695
// ++++ release child PCB
9796
*translated_refmut(inner.memory_set.token(), exit_code_ptr) = exit_code;
97+
debug!("found pid[{}]", found_pid);
9898
found_pid as isize
9999
} else {
100+
// debug!("pid[{}] is running", pid);
100101
-2
101102
}
102103
// ---- release current PCB automatically
@@ -106,29 +107,83 @@ pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
106107
/// HINT: You might reimplement it with virtual memory management.
107108
/// HINT: What if [`TimeVal`] is splitted by two pages ?
108109
pub fn sys_get_time(_ts: *mut TimeVal, _tz: usize) -> isize {
109-
trace!(
110-
"kernel:pid[{}] sys_get_time NOT IMPLEMENTED",
111-
current_task().unwrap().pid.0
112-
);
113-
-1
110+
trace!("kernel: sys_get_time");
111+
let pa = translated_physaddr(current_user_token(), _ts as *const u8);
112+
let phy_ts = pa.0 as *mut TimeVal;
113+
114+
let us = get_time_us();
115+
let time_val = TimeVal {
116+
sec : us / 1_000_000,
117+
usec: us % 1_000_000,
118+
};
119+
120+
unsafe { *phy_ts = time_val };
121+
0
114122
}
115123

116-
/// YOUR JOB: Implement mmap.
124+
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
125+
pub struct Flag(pub usize);
126+
127+
impl Flag {
128+
pub fn is_readable(&self) -> bool {
129+
self.0 & 0x1 == 0x1
130+
}
131+
132+
pub fn is_writeable(&self) -> bool {
133+
self.0 & 0x2 == 0x2
134+
}
135+
136+
pub fn is_execute(&self) -> bool {
137+
self.0 & 0x4 == 0x4
138+
}
139+
}
140+
141+
// YOUR JOB: Implement mmap.
117142
pub fn sys_mmap(_start: usize, _len: usize, _port: usize) -> isize {
118-
trace!(
119-
"kernel:pid[{}] sys_mmap NOT IMPLEMENTED",
120-
current_task().unwrap().pid.0
121-
);
122-
-1
143+
trace!("kernel: sys_mmap ");
144+
145+
debug!("mmap start: {}, len: {}, port: {}", _start, _len, _port);
146+
147+
let start_va = VirtAddr::from(_start);
148+
if !start_va.aligned() {
149+
return -1;
150+
}
151+
let end_va: VirtAddr = (_start + _len).into();
152+
if _port & !0x7 != 0 || _port & 0x7 == 0 {
153+
return -1;
154+
}
155+
156+
let mut map_perm: MapPermission = MapPermission::U;
157+
let pte_flag = Flag(_port);
158+
if pte_flag.is_readable() {
159+
map_perm |= MapPermission::R;
160+
}
161+
if pte_flag.is_writeable() {
162+
map_perm |= MapPermission::W;
163+
}
164+
if pte_flag.is_execute() {
165+
map_perm |= MapPermission::X;
166+
}
167+
168+
if !current_task().unwrap().find_area_insert(start_va, end_va, map_perm) {
169+
return -1;
170+
}
171+
return 0;
123172
}
124173

125174
/// YOUR JOB: Implement munmap.
126175
pub fn sys_munmap(_start: usize, _len: usize) -> isize {
127-
trace!(
128-
"kernel:pid[{}] sys_munmap NOT IMPLEMENTED",
129-
current_task().unwrap().pid.0
130-
);
131-
-1
176+
trace!("kernel: sys_munmap ");
177+
let start_va = VirtAddr::from(_start);
178+
if !start_va.aligned() {
179+
return -1;
180+
}
181+
let end_va: VirtAddr = (_start + _len).into();
182+
183+
if !current_task().unwrap().find_area_remove(start_va, end_va) {
184+
return -1;
185+
}
186+
return 0;
132187
}
133188

134189
/// change data segment size
@@ -148,7 +203,19 @@ pub fn sys_spawn(_path: *const u8) -> isize {
148203
"kernel:pid[{}] sys_spawn NOT IMPLEMENTED",
149204
current_task().unwrap().pid.0
150205
);
151-
-1
206+
let token = current_user_token();
207+
let path = translated_str(token, _path);
208+
if let Some(app_inode) = open_file(path.as_str(), OpenFlags::RDONLY) {
209+
let all_data = app_inode.read_all();
210+
let new_task: Arc<TaskControlBlock> = current_task().unwrap().spawn(&all_data);
211+
let pid = new_task.getpid() as isize;
212+
add_task(new_task);
213+
debug!("add task pid[{}]", pid);
214+
return pid;
215+
} else {
216+
debug!("kernel: sys spawn error...");
217+
return -1;
218+
}
152219
}
153220

154221
// YOUR JOB: Set task priority.
@@ -157,5 +224,9 @@ pub fn sys_set_priority(_prio: isize) -> isize {
157224
"kernel:pid[{}] sys_set_priority NOT IMPLEMENTED",
158225
current_task().unwrap().pid.0
159226
);
160-
-1
227+
if _prio < 2 {
228+
return -1;
229+
}
230+
current_task().unwrap().set_priority(_prio as usize);
231+
return _prio;
161232
}

os/src/task/manager.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,41 @@
11
//!Implementation of [`TaskManager`]
22
use super::TaskControlBlock;
3+
use crate::config::BIG_STRIDE;
34
use crate::sync::UPSafeCell;
4-
use alloc::collections::VecDeque;
55
use alloc::sync::Arc;
6+
use alloc::vec::Vec;
67
use lazy_static::*;
78
///A array of `TaskControlBlock` that is thread-safe
89
pub struct TaskManager {
9-
ready_queue: VecDeque<Arc<TaskControlBlock>>,
10+
ready_queue: Vec<Arc<TaskControlBlock>>,
1011
}
1112

1213
/// A simple FIFO scheduler.
1314
impl TaskManager {
1415
///Creat an empty TaskManager
1516
pub fn new() -> Self {
1617
Self {
17-
ready_queue: VecDeque::new(),
18+
ready_queue: Vec::new(),
1819
}
1920
}
2021
/// Add process back to ready queue
2122
pub fn add(&mut self, task: Arc<TaskControlBlock>) {
22-
self.ready_queue.push_back(task);
23+
self.ready_queue.push(task);
2324
}
2425
/// Take a process out of the ready queue
2526
pub fn fetch(&mut self) -> Option<Arc<TaskControlBlock>> {
26-
self.ready_queue.pop_front()
27+
let mut min_stride_idx = 0;
28+
let mut min_stride = BIG_STRIDE;
29+
for (idx, task) in self.ready_queue.iter().enumerate() {
30+
let stride = task.inner_exclusive_access().stride as usize;
31+
if stride < min_stride {
32+
min_stride_idx = idx;
33+
min_stride = stride;
34+
}
35+
}
36+
let ret = self.ready_queue[min_stride_idx].clone();
37+
self.ready_queue.remove(min_stride_idx);
38+
return Some(ret);
2739
}
2840
}
2941

os/src/task/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ pub fn suspend_current_and_run_next() {
4949
drop(task_inner);
5050
// ---- release current PCB
5151

52+
task.update_stride();
5253
// push back to ready queue.
5354
add_task(task);
5455
// jump to scheduling cycle

0 commit comments

Comments
 (0)