Skip to content

Commit 766fc62

Browse files
committed
ch5 ok
1 parent f97386c commit 766fc62

File tree

13 files changed

+430
-33
lines changed

13 files changed

+430
-33
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
@@ -21,3 +21,6 @@ pub const TRAP_CONTEXT_BASE: usize = TRAMPOLINE - PAGE_SIZE;
2121
pub const CLOCK_FREQ: usize = 12500000;
2222
/// the physical memory end
2323
pub const MEMORY_END: usize = 0x88000000;
24+
25+
/// BigStride
26+
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
@@ -300,6 +300,32 @@ impl MemorySet {
300300
false
301301
}
302302
}
303+
304+
/// find target area by start_va, then insert it to areas
305+
pub fn find_area_insert(&mut self, start_va: VirtAddr, end_va: VirtAddr, permission: MapPermission) -> bool {
306+
if let Some(_area) = self.areas.iter().find(|area| {
307+
area.vpn_range.get_start() < end_va.ceil() && area.vpn_range.get_end() > start_va.floor()
308+
}) {
309+
debug!("!!! find area has been used !!!");
310+
false
311+
} else {
312+
debug!("!!! area not be used, insert it!!!");
313+
self.insert_framed_area(start_va, end_va, permission);
314+
true
315+
}
316+
}
317+
/// find target area by start_va, then remove it from areas
318+
pub fn find_area_remove(&mut self, start_va: VirtAddr, end_va: VirtAddr) -> bool {
319+
if let Some(index) = self.areas.iter().position(|area| {
320+
area.vpn_range.get_start() == start_va.floor() && area.vpn_range.get_end() == end_va.ceil()
321+
}) {
322+
self.areas[index].unmap(&mut self.page_table);
323+
self.areas.remove(index);
324+
true
325+
} else {
326+
false
327+
}
328+
}
303329
}
304330
/// map area structure, controls a contiguous piece of virtual memory
305331
pub struct MapArea {

os/src/mm/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ use address::{StepByOne, VPNRange};
1616
pub use frame_allocator::{frame_alloc, FrameTracker};
1717
pub use memory_set::remap_test;
1818
pub use memory_set::{MapPermission, MemorySet, KERNEL_SPACE};
19-
pub use page_table::{translated_byte_buffer, translated_refmut, translated_str, PageTableEntry};
20-
use page_table::{PTEFlags, PageTable};
19+
pub use page_table::{translated_byte_buffer, translated_refmut, translated_physaddr, translated_str, PageTableEntry};
20+
pub use page_table::{PTEFlags, PageTable};
21+
2122
/// initiate heap allocator, frame allocator and kernel space
2223
pub fn init() {
2324
heap_allocator::init_heap();

os/src/mm/page_table.rs

Lines changed: 22 additions & 0 deletions
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
}
@@ -202,6 +210,7 @@ pub fn translated_str(token: usize, ptr: *const u8) -> String {
202210
}
203211
string
204212
}
213+
205214
/// Translate a ptr[u8] array through page table and return a mutable reference of T
206215
pub fn translated_refmut<T>(token: usize, ptr: *mut T) -> &'static mut T {
207216
//trace!("into translated_refmut!");
@@ -213,3 +222,16 @@ pub fn translated_refmut<T>(token: usize, ptr: *mut T) -> &'static mut T {
213222
.unwrap()
214223
.get_mut()
215224
}
225+
226+
/// translate a ptr and return its mut
227+
pub fn translated_physaddr(token: usize, ptr: *const u8) -> PhysAddr {
228+
let page_table = PageTable::from_token(token);
229+
let va = VirtAddr::from(ptr as usize);
230+
let vpn = va.floor();
231+
let ppn: PhysPageNum = page_table.translate(vpn).unwrap().ppn();
232+
let pa: PhysAddr = ppn.into();
233+
234+
let offset = va.page_offset();
235+
let pa_offset = (pa.0 + offset).into();
236+
return pa_offset;
237+
}

os/src/syscall/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ mod process;
4343

4444
use fs::*;
4545
use process::*;
46+
4647
/// handle syscall exception with `syscall_id` and other arguments
4748
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
4849
match syscall_id {

os/src/syscall/process.rs

Lines changed: 91 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@
22
use alloc::sync::Arc;
33

44
use crate::{
5-
loader::get_app_data_by_name,
6-
mm::{translated_refmut, translated_str},
7-
task::{
8-
add_task, current_task, current_user_token, exit_current_and_run_next,
9-
suspend_current_and_run_next,
10-
},
5+
loader::get_app_data_by_name, mm::{translated_physaddr, translated_refmut, translated_str, MapPermission, VirtAddr}, task::{add_task, current_task, current_user_token, exit_current_and_run_next, suspend_current_and_run_next, TaskControlBlock}, timer::get_time_us
116
};
127

138
#[repr(C)]
@@ -78,6 +73,7 @@ pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
7873
.iter()
7974
.any(|p| pid == -1 || pid as usize == p.getpid())
8075
{
76+
debug!("no such pid[{}]", pid);
8177
return -1;
8278
// ---- release current PCB
8379
}
@@ -95,8 +91,10 @@ pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
9591
let exit_code = child.inner_exclusive_access().exit_code;
9692
// ++++ release child PCB
9793
*translated_refmut(inner.memory_set.token(), exit_code_ptr) = exit_code;
94+
debug!("found pid[{}]", found_pid);
9895
found_pid as isize
9996
} else {
97+
// debug!("pid[{}] is running", pid);
10098
-2
10199
}
102100
// ---- release current PCB automatically
@@ -106,29 +104,83 @@ pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
106104
/// HINT: You might reimplement it with virtual memory management.
107105
/// HINT: What if [`TimeVal`] is splitted by two pages ?
108106
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
107+
trace!("kernel: sys_get_time");
108+
let pa = translated_physaddr(current_user_token(), _ts as *const u8);
109+
let phy_ts = pa.0 as *mut TimeVal;
110+
111+
let us = get_time_us();
112+
let time_val = TimeVal {
113+
sec : us / 1_000_000,
114+
usec: us % 1_000_000,
115+
};
116+
117+
unsafe { *phy_ts = time_val };
118+
0
119+
}
120+
121+
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
122+
pub struct Flag(pub usize);
123+
124+
impl Flag {
125+
pub fn is_readable(&self) -> bool {
126+
self.0 & 0x1 == 0x1
127+
}
128+
129+
pub fn is_writeable(&self) -> bool {
130+
self.0 & 0x2 == 0x2
131+
}
132+
133+
pub fn is_execute(&self) -> bool {
134+
self.0 & 0x4 == 0x4
135+
}
114136
}
115137

116-
/// YOUR JOB: Implement mmap.
138+
// YOUR JOB: Implement mmap.
117139
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
140+
trace!("kernel: sys_mmap ");
141+
142+
debug!("mmap start: {}, len: {}, port: {}", _start, _len, _port);
143+
144+
let start_va = VirtAddr::from(_start);
145+
if !start_va.aligned() {
146+
return -1;
147+
}
148+
let end_va: VirtAddr = (_start + _len).into();
149+
if _port & !0x7 != 0 || _port & 0x7 == 0 {
150+
return -1;
151+
}
152+
153+
let mut map_perm: MapPermission = MapPermission::U;
154+
let pte_flag = Flag(_port);
155+
if pte_flag.is_readable() {
156+
map_perm |= MapPermission::R;
157+
}
158+
if pte_flag.is_writeable() {
159+
map_perm |= MapPermission::W;
160+
}
161+
if pte_flag.is_execute() {
162+
map_perm |= MapPermission::X;
163+
}
164+
165+
if !current_task().unwrap().find_area_insert(start_va, end_va, map_perm) {
166+
return -1;
167+
}
168+
return 0;
123169
}
124170

125171
/// YOUR JOB: Implement munmap.
126172
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
173+
trace!("kernel: sys_munmap ");
174+
let start_va = VirtAddr::from(_start);
175+
if !start_va.aligned() {
176+
return -1;
177+
}
178+
let end_va: VirtAddr = (_start + _len).into();
179+
180+
if !current_task().unwrap().find_area_remove(start_va, end_va) {
181+
return -1;
182+
}
183+
return 0;
132184
}
133185

134186
/// change data segment size
@@ -148,7 +200,18 @@ pub fn sys_spawn(_path: *const u8) -> isize {
148200
"kernel:pid[{}] sys_spawn NOT IMPLEMENTED",
149201
current_task().unwrap().pid.0
150202
);
151-
-1
203+
let token = current_user_token();
204+
let path = translated_str(token, _path);
205+
if let Some(data) = get_app_data_by_name(&path) {
206+
let new_task: Arc<TaskControlBlock> = current_task().unwrap().spawn(data);
207+
let pid = new_task.getpid() as isize;
208+
add_task(new_task);
209+
debug!("add task pid[{}]", pid);
210+
return pid;
211+
} else {
212+
debug!("kernel: sys spawn error...");
213+
return -1;
214+
}
152215
}
153216

154217
// YOUR JOB: Set task priority.
@@ -157,5 +220,9 @@ pub fn sys_set_priority(_prio: isize) -> isize {
157220
"kernel:pid[{}] sys_set_priority NOT IMPLEMENTED",
158221
current_task().unwrap().pid.0
159222
);
160-
-1
223+
if _prio < 2 {
224+
return -1;
225+
}
226+
current_task().unwrap().set_priority(_prio as usize);
227+
return _prio;
161228
}

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
@@ -48,6 +48,7 @@ pub fn suspend_current_and_run_next() {
4848
drop(task_inner);
4949
// ---- release current PCB
5050

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

0 commit comments

Comments
 (0)