Skip to content

Commit 33c28aa

Browse files
committed
ch4 lab; fix switch time; rm task_info
1 parent 2942a96 commit 33c28aa

File tree

21 files changed

+337
-207
lines changed

21 files changed

+337
-207
lines changed

os/src/mm/memory_set.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,10 @@ impl MemorySet {
374374
pub fn token(&self) -> usize {
375375
self.page_table.token()
376376
}
377+
378+
pub fn page_table_mut(&mut self) -> &mut PageTable {
379+
&mut self.page_table
380+
}
377381
}
378382

379383
#[allow(unused)]

os/src/mm/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ mod heap_allocator;
44
mod memory_set;
55
mod page_table;
66

7-
pub use address::{PhysPageNum, VirtAddr};
7+
pub use address::*;
88
pub use memory_set::{remap_test, MapPermission, MemorySet, KERNEL_SPACE};
9-
pub use page_table::translated_byte_buffer;
9+
pub use page_table::*;
1010

1111
pub fn init() {
1212
heap_allocator::init_heap();

os/src/mm/page_table.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ impl PageTable {
182182
}
183183
}
184184

185-
pub fn translated_byte_buffer(token: usize, ptr: *const u8, len: usize) -> Vec<&'static [u8]> {
185+
pub fn translated_byte_buffer(token: usize, ptr: *const u8, len: usize) -> Vec<&'static mut [u8]> {
186186
let page_table = PageTable::from_token(token);
187187
let mut start = ptr as usize;
188188
let end = start + len;
@@ -201,9 +201,9 @@ pub fn translated_byte_buffer(token: usize, ptr: *const u8, len: usize) -> Vec<&
201201
let end_va = VirtAddr::from(vpn).min(VirtAddr::from(end));
202202
// 5. 非end时, 当前page的[start_va.offset..]都是需要的空间; end时, 则到end_va.offset为止
203203
if end_va.page_offset() == 0 {
204-
v.push(&ppn.get_bytes_array()[start_va.page_offset()..]);
204+
v.push(&mut ppn.get_bytes_array()[start_va.page_offset()..]);
205205
} else {
206-
v.push(&ppn.get_bytes_array()[start_va.page_offset()..end_va.page_offset()]);
206+
v.push(&mut ppn.get_bytes_array()[start_va.page_offset()..end_va.page_offset()]);
207207
}
208208
start = end_va.into();
209209
}

os/src/syscall/mem.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use crate::{
2+
mm::{MapPermission, VirtAddr},
3+
task,
4+
};
5+
6+
const VA_MAX: usize = usize::MAX;
7+
8+
/// `start` must be 4k aligned, `prot` arrange as (hi->lo) xwr
9+
pub fn sys_mmap(start: usize, len: usize, prot: usize) -> isize {
10+
// 4k align
11+
if start & 0xfff != 0 ||
12+
// only last 3 bits allowed
13+
prot & !0x7 != 0 ||
14+
// no perm specified, meaningless
15+
prot & 0x7 == 0 ||
16+
// theoretically no space (avoid overflow)
17+
VA_MAX - len <= start
18+
{
19+
return -1;
20+
}
21+
22+
let start_vpn = VirtAddr::from(start).floor();
23+
let end_vpn = VirtAddr::from(start + len).ceil();
24+
let map_perm = MapPermission::from_bits_truncate((prot << 1) as u8) | MapPermission::U;
25+
task::current_task_map_new_area(start_vpn, end_vpn, map_perm)
26+
}
27+
28+
pub fn sys_munmap(start: usize, len: usize) -> isize {
29+
// 4k align
30+
if start & 0xfff != 0 ||
31+
// theoretically no space
32+
VA_MAX - len <= start
33+
{
34+
return -1;
35+
}
36+
37+
let start_vpn = VirtAddr::from(start).floor();
38+
let end_vpn = VirtAddr::from(start + len).ceil();
39+
task::current_task_unmap_area(start_vpn, end_vpn)
40+
}

os/src/syscall/mod.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
11
mod fs;
2+
mod mem;
23
mod process;
34

45
use fs::*;
6+
use mem::*;
57
use process::*;
68

7-
// use crate::task::TaskInfo;
8-
99
const SYSCALL_WRITE: usize = 64;
1010
const SYSCALL_EXIT: usize = 93;
1111
const SYSCALL_YIELD: usize = 124;
1212
const SYSCALL_GET_TIME: usize = 169;
13-
// const SYSCALL_TASK_INFO: usize = 410;
13+
const SYSCALL_MUNMAP: usize = 215;
14+
const SYSCALL_MMAP: usize = 222;
1415

1516
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
1617
match syscall_id {
1718
SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]),
1819
SYSCALL_EXIT => sys_exit(args[0] as i32),
1920
SYSCALL_YIELD => sys_yield(),
20-
SYSCALL_GET_TIME => sys_get_time(),
21-
// SYSCALL_TASK_INFO => sys_task_info(args[0] as *mut TaskInfo),
21+
SYSCALL_GET_TIME => sys_get_time(args[0] as *mut TimeVal),
22+
SYSCALL_MUNMAP => sys_munmap(args[0], args[1]),
23+
SYSCALL_MMAP => sys_mmap(args[0], args[1], args[2]),
2224
_ => panic!("Unsupported syscall_id: {}", syscall_id),
2325
}
2426
}

os/src/syscall/process.rs

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{task::*, timer::get_time_ms};
1+
use crate::{mm, task::*, timer};
22

33
/// task exits and submit an exit code
44
pub fn sys_exit(exit_code: i32) -> ! {
@@ -13,19 +13,32 @@ pub fn sys_yield() -> isize {
1313
0
1414
}
1515

16-
/// get time in ms
17-
pub fn sys_get_time() -> isize {
18-
get_time_ms() as isize
16+
#[repr(C)]
17+
#[derive(Debug)]
18+
pub struct TimeVal {
19+
pub sec: usize,
20+
pub usec: usize,
1921
}
2022

21-
// /// get info of current task
22-
// pub fn sys_task_info(ti: *mut TaskInfo) -> isize {
23-
// unsafe {
24-
// *ti = TaskInfo {
25-
// status: get_current_task_status(),
26-
// call: get_current_task_syscall_times(),
27-
// time: get_current_task_run_time(),
28-
// }
29-
// }
30-
// 0
31-
// }
23+
/// get time
24+
pub fn sys_get_time(ts: *mut TimeVal) -> isize {
25+
let us = timer::get_time_us();
26+
let dst_vs = mm::translated_byte_buffer(
27+
current_user_token(),
28+
ts as *const u8,
29+
core::mem::size_of::<TimeVal>(),
30+
);
31+
let ts = TimeVal {
32+
sec: us / 1_000_000,
33+
usec: us % 1_000_000,
34+
};
35+
let ts_ptr = (&ts as *const TimeVal) as *const u8;
36+
for (i, dst) in dst_vs.into_iter().enumerate() {
37+
let len = dst.len();
38+
unsafe {
39+
let src = core::slice::from_raw_parts(ts_ptr.wrapping_add(i * len), len);
40+
dst.copy_from_slice(src);
41+
}
42+
}
43+
0
44+
}

os/src/task/context.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use crate::trap::trap_return;
2-
31
/// Task Context
42
#[repr(C)]
53
pub struct TaskContext {
@@ -20,9 +18,10 @@ impl TaskContext {
2018
}
2119
}
2220

21+
// 想办法第一次调用switch_cost, 然后正常走trap_return
2322
pub fn goto_trap_return(kstack_ptr: usize) -> Self {
2423
Self {
25-
ra: trap_return as usize,
24+
ra: crate::trap::pre_trap_return as usize,
2625
sp: kstack_ptr,
2726
s: [0; 12],
2827
}

os/src/task/mod.rs

Lines changed: 41 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,23 @@ use context::TaskContext;
33
use lazy_static::lazy_static;
44
use task::{TaskControlBlock, TaskStatus};
55

6-
use crate::{loader, sbi::shutdown, sync::UPSafeCell, timer::get_time_us, trap::TrapContext};
6+
use crate::{
7+
loader,
8+
mm::{MapPermission, VPNRange, VirtPageNum},
9+
sbi::shutdown,
10+
sync::UPSafeCell,
11+
timer::get_time_us,
12+
trap::TrapContext,
13+
};
714

815
mod context;
916
mod switch;
1017
mod task;
1118

1219
lazy_static! {
1320
pub static ref TASK_MANAGER: TaskManager = {
14-
log::info!("init TASK_MANAGER");
1521
let num_app = loader::get_num_app();
16-
log::info!("num_app = {}", num_app);
22+
log::info!("init TASK_MANAGER: num_app = {}", num_app);
1723
let mut tasks = Vec::new();
1824

1925
for i in 0..num_app {
@@ -159,34 +165,6 @@ impl TaskManager {
159165
inner.tasks[curr].user_time += inner.refresh_stop_watch();
160166
}
161167

162-
// fn current_task(&self) -> usize {
163-
// let inner = self.inner.exclusive_access();
164-
// inner.curr_task
165-
// }
166-
167-
// fn current_task_status(&self) -> TaskStatus {
168-
// let inner = self.inner.exclusive_access();
169-
// inner.tasks[inner.curr_task].task_status
170-
// }
171-
172-
// fn current_task_run_time(&self) -> usize {
173-
// let inner = self.inner.exclusive_access();
174-
// let curr = &inner.tasks[inner.curr_task];
175-
// curr.kernel_time + curr.user_time
176-
// }
177-
178-
// fn record_syscall(&self, id: usize) {
179-
// let mut inner = self.inner.exclusive_access();
180-
// let curr = inner.curr_task;
181-
// inner.tasks[curr].syscall_times[id] += 1;
182-
// }
183-
184-
// // todo: opt copy?
185-
// fn current_task_syscall_times(&self) -> [usize; MAX_SYSCALL_NUM] {
186-
// let inner = self.inner.exclusive_access();
187-
// inner.tasks[inner.curr_task].syscall_times.clone()
188-
// }
189-
190168
fn get_current_token(&self) -> usize {
191169
let inner = self.inner.exclusive_access();
192170
let current = inner.curr_task;
@@ -247,38 +225,42 @@ pub fn user_time_end() {
247225
TASK_MANAGER.user_time_end()
248226
}
249227

250-
// #[repr(C)]
251-
// pub struct TaskInfo {
252-
// pub status: TaskStatus,
253-
// pub call: [usize; MAX_SYSCALL_NUM],
254-
// pub time: usize,
255-
// }
256-
257-
// pub fn get_current_task_id() -> usize {
258-
// TASK_MANAGER.current_task()
259-
// }
260-
261-
// pub fn get_current_task_status() -> TaskStatus {
262-
// TASK_MANAGER.current_task_status()
263-
// }
264-
265-
// pub fn get_current_task_run_time() -> usize {
266-
// TASK_MANAGER.current_task_run_time()
267-
// }
268-
269-
// pub fn current_task_record_syscall(id: usize) {
270-
// TASK_MANAGER.record_syscall(id);
271-
// }
272-
273-
// pub fn get_current_task_syscall_times() -> [usize; MAX_SYSCALL_NUM] {
274-
// let si = TASK_MANAGER.current_task_syscall_times();
275-
// si
276-
// }
277-
278228
pub fn current_user_token() -> usize {
279229
TASK_MANAGER.get_current_token()
280230
}
281231

282232
pub fn current_trap_cx() -> &'static mut TrapContext {
283233
TASK_MANAGER.get_current_trap_cx()
284234
}
235+
236+
pub fn current_task_map_new_area(
237+
start_vpn: VirtPageNum,
238+
end_vpn: VirtPageNum,
239+
map_perm: MapPermission,
240+
) -> isize {
241+
let mut inner = TASK_MANAGER.inner.exclusive_access();
242+
let current = inner.curr_task;
243+
let curr_mem_set = &mut inner.tasks[current].memory_set;
244+
for vpn in VPNRange::new(start_vpn, end_vpn) {
245+
match curr_mem_set.translate(vpn) {
246+
Some(pte) if pte.is_valid() => return -1, // mapped already
247+
_ => {}
248+
}
249+
}
250+
curr_mem_set.insert_framed_area(start_vpn.into(), end_vpn.into(), map_perm);
251+
0
252+
}
253+
254+
pub fn current_task_unmap_area(start_vpn: VirtPageNum, end_vpn: VirtPageNum) -> isize {
255+
let mut inner = TASK_MANAGER.inner.exclusive_access();
256+
let current = inner.curr_task;
257+
let curr_mem_set = &mut inner.tasks[current].memory_set;
258+
for vpn in VPNRange::new(start_vpn, end_vpn) {
259+
match curr_mem_set.translate(vpn) {
260+
Some(pte) if !pte.is_valid() => return -1, // not valid
261+
Some(_) => curr_mem_set.page_table_mut().unmap(vpn),
262+
_ => return -1, // no entry
263+
}
264+
}
265+
0
266+
}

os/src/task/task.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ pub struct TaskControlBlock {
2626

2727
pub user_time: usize,
2828
pub kernel_time: usize,
29-
// pub syscall_times: [usize; MAX_SYSCALL_NUM],
3029
}
3130

3231
impl TaskControlBlock {

os/src/trap/mod.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use riscv::register::{
99
use crate::{
1010
config::{TRAMPOLINE, TRAP_CONTEXT},
1111
syscall::syscall,
12-
task::{current_trap_cx, current_user_token},
1312
};
1413

1514
mod context;
@@ -45,15 +44,14 @@ pub fn trap_handler() -> ! {
4544
crate::task::user_time_end();
4645
// 应用的 Trap 上下文不在内核地址空间,因此我们调用 current_trap_cx 来获取当前应用的 Trap 上下文的可变引用
4746
// 而不是像之前那样作为参数传入 trap_handler
48-
let cx = current_trap_cx();
47+
let cx = crate::task::current_trap_cx();
4948
let scause = scause::read();
5049
let stval = stval::read();
5150

5251
match scause.cause() {
5352
scause::Trap::Exception(Exception::UserEnvCall) => {
5453
cx.sepc += 4;
5554
let syscall_id = cx.x[17];
56-
// task::current_task_record_syscall(syscall_id);
5755
cx.x[10] = syscall(syscall_id, [cx.x[10], cx.x[11], cx.x[12]]) as usize;
5856
}
5957
scause::Trap::Exception(Exception::StorePageFault)
@@ -89,7 +87,7 @@ pub fn trap_return() -> ! {
8987
// __restore的参数a0, Trap 上下文在应用地址空间中的虚拟地址
9088
let trap_cx_ptr = TRAP_CONTEXT;
9189
// __restore的参数a1, 应用地址空间的 token
92-
let user_satp = current_user_token();
90+
let user_satp = crate::task::current_user_token();
9391

9492
extern "C" {
9593
fn __alltraps();
@@ -114,11 +112,11 @@ pub fn trap_return() -> ! {
114112
}
115113
}
116114

117-
// #[no_mangle]
118-
// pub unsafe fn switch_cost(cx: &mut TrapContext) -> &mut TrapContext {
119-
// task::SWITCH_TIME_COUNT += timer::get_time_us() - task::SWITCH_TIME_START;
120-
// cx
121-
// }
115+
#[no_mangle]
116+
pub unsafe fn pre_trap_return() -> ! {
117+
crate::task::SWITCH_TIME_COUNT += crate::timer::get_time_us() - crate::task::SWITCH_TIME_START;
118+
trap_return()
119+
}
122120

123121
#[no_mangle]
124122
pub fn trap_from_kernel() -> ! {

0 commit comments

Comments
 (0)