diff --git a/os/src/syscall/mod.rs b/os/src/syscall/mod.rs index f0159c2..d29ad2c 100644 --- a/os/src/syscall/mod.rs +++ b/os/src/syscall/mod.rs @@ -30,7 +30,7 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]), SYSCALL_EXIT => sys_exit(args[0] as i32), SYSCALL_YIELD => sys_yield(), - SYSCALL_GET_TIME => sys_get_time(), + SYSCALL_GET_TIME => sys_get_time(args[0] as *mut TimeVal, args[1]), SYSCALL_SBRK => sys_sbrk(args[0] as i32), SYSCALL_MMAP => sys_mmap(args[0], args[1], args[2]), SYSCALL_MUNMAP => sys_munmap(args[0], args[1]), diff --git a/os/src/syscall/process.rs b/os/src/syscall/process.rs index dd873bf..a0ca421 100644 --- a/os/src/syscall/process.rs +++ b/os/src/syscall/process.rs @@ -3,7 +3,7 @@ use crate::config::PAGE_SIZE; use crate::mm::{MapPermission, VPNRange, VirtAddr}; use crate::task::{change_program_brk, create_new_map_area, exit_current_and_run_next, get_current_task_page_table_entry, suspend_current_and_run_next, unmap_virtual_page}; -use crate::timer::get_time_ms; +use crate::timer::get_time_us; /// task exits and submit an exit code pub fn sys_exit(exit_code: i32) -> ! { @@ -18,9 +18,24 @@ pub fn sys_yield() -> isize { 0 } +#[repr(C)] +#[derive(Debug)] +pub struct TimeVal { + pub sec: usize, + pub usec: usize, +} + /// get current time -pub fn sys_get_time() -> isize { - get_time_ms() as isize +pub fn sys_get_time(ts: *mut TimeVal, _tz: usize) -> isize { + let us = get_time_us(); + unsafe { + *ts = TimeVal { + sec: us / 1_000_000, + usec: us % 1_000_000, + }; + } + 0 + -1 } /// change data segment size diff --git a/os/src/timer.rs b/os/src/timer.rs index 1948c6a..8ddca7c 100644 --- a/os/src/timer.rs +++ b/os/src/timer.rs @@ -6,16 +6,23 @@ use riscv::register::time; const TICKS_PER_SEC: usize = 100; const MSEC_PER_SEC: usize = 1000; +const MICRO_PER_SEC: usize = 1_000_000; pub fn get_time() -> usize { time::read() } /// get current time in microseconds +#[allow(unused)] pub fn get_time_ms() -> usize { time::read() / (CLOCK_FREQ / MSEC_PER_SEC) } +/// get current time in us +pub fn get_time_us() -> usize { + time::read() / (CLOCK_FREQ / MICRO_PER_SEC) +} + /// set the next timer interrupt pub fn set_next_trigger() { set_timer(get_time() + CLOCK_FREQ / TICKS_PER_SEC); diff --git a/user/src/bin/03sleep.rs b/user/src/bin/03sleep.rs index 7e43d9c..d98c660 100644 --- a/user/src/bin/03sleep.rs +++ b/user/src/bin/03sleep.rs @@ -6,13 +6,19 @@ extern crate user_lib; use user_lib::{get_time, yield_}; +/// 正确输出:(无报错信息) +/// get_time OK! {...} +/// Test sleep OK! + #[no_mangle] fn main() -> i32 { - let current_timer = get_time(); - let wait_for = current_timer + 3000; + let current_time = get_time(); + assert!(current_time > 0); + println!("get_time OK! {}", current_time); + let wait_for = current_time + 3000; while get_time() < wait_for { yield_(); } println!("Test sleep OK!"); 0 -} +} \ No newline at end of file diff --git a/user/src/bin/03sleep1.rs b/user/src/bin/03sleep1.rs new file mode 100644 index 0000000..23b8060 --- /dev/null +++ b/user/src/bin/03sleep1.rs @@ -0,0 +1,22 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +use user_lib::{get_time, sleep}; + +#[no_mangle] +pub fn main() -> i32 { + let start = get_time(); + println!("current time_msec = {}", start); + sleep(100); + let end = get_time(); + println!( + "time_msec = {} after sleeping 100 ticks, delta = {}ms!", + end, + end - start + ); + println!("Test sleep1 passed!"); + 0 +} \ No newline at end of file diff --git a/user/src/lib.rs b/user/src/lib.rs index 6351f57..9d39c52 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -20,6 +20,19 @@ fn main() -> i32 { panic!("Cannot find main!"); } +#[repr(C)] +#[derive(Debug, Default)] +pub struct TimeVal { + pub sec: usize, + pub usec: usize, +} + +impl TimeVal { + pub fn new() -> Self { + Self::default() + } +} + use syscall::*; pub fn write(fd: usize, buf: &[u8]) -> isize { @@ -32,7 +45,11 @@ pub fn yield_() -> isize { sys_yield() } pub fn get_time() -> isize { - sys_get_time() + let time = TimeVal::new(); + match sys_get_time(&time, 0) { + 0 => ((time.sec & 0xffff) * 1000 + time.usec / 1000) as isize, + _ => -1, + } } pub fn sbrk(size: i32) -> isize { @@ -46,3 +63,10 @@ pub fn munmap(start: usize, len: usize) -> isize { pub fn mmap(start: usize, len: usize, prot: usize) -> isize { sys_mmap(start, len, prot) } + +pub fn sleep(period_ms: usize) { + let start = get_time(); + while get_time() < start + period_ms as isize { + sys_yield(); + } +} \ No newline at end of file diff --git a/user/src/syscall.rs b/user/src/syscall.rs index 12a1662..474684c 100644 --- a/user/src/syscall.rs +++ b/user/src/syscall.rs @@ -1,12 +1,15 @@ use core::arch::asm; +use crate::TimeVal; + const SYSCALL_WRITE: usize = 64; const SYSCALL_EXIT: usize = 93; const SYSCALL_YIELD: usize = 124; const SYSCALL_GET_TIME: usize = 169; +const SYSCALL_GETTIMEOFDAY: usize = 169; const SYSCALL_SBRK: usize = 214; -pub const SYSCALL_MMAP: usize = 222; -pub const SYSCALL_MUNMAP: usize = 215; +const SYSCALL_MMAP: usize = 222; +const SYSCALL_MUNMAP: usize = 215; fn syscall(id: usize, args: [usize; 3]) -> isize { let mut ret: isize; @@ -34,8 +37,8 @@ pub fn sys_yield() -> isize { syscall(SYSCALL_YIELD, [0, 0, 0]) } -pub fn sys_get_time() -> isize { - syscall(SYSCALL_GET_TIME, [0, 0, 0]) +pub fn sys_get_time(time: &TimeVal, tz: usize) -> isize { + syscall(SYSCALL_GETTIMEOFDAY, [time as *const _ as usize, tz, 0]) } pub fn sys_sbrk(size: i32) -> isize {