Files
DragonOS/kernel/src/time/sleep.rs
Jomo 6fc066ac11 实现SystemV共享内存 (#690)
* 实现SystemV共享内存

* 测试shm

* 添加测试程序

* 完善细节

* 修正shm的时间数据错误的问题

* fix: devfs的metadata权限为0x777的错误

---------

Co-authored-by: longjin <longjin@DragonOS.org>
2024-04-07 14:04:19 +08:00

105 lines
3.0 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use core::hint::spin_loop;
use alloc::{boxed::Box, sync::Arc};
use system_error::SystemError;
use crate::{
arch::{CurrentIrqArch, CurrentTimeArch},
exception::InterruptArch,
include::bindings::bindings::useconds_t,
process::ProcessManager,
sched::{schedule, SchedMode},
time::timekeeping::getnstimeofday,
};
use super::{
timer::{next_n_us_timer_jiffies, Timer, WakeUpHelper},
PosixTimeSpec, TimeArch,
};
/// @brief 休眠指定时间(单位:纳秒)
///
/// @param sleep_time 指定休眠的时间
///
/// @return Ok(TimeSpec) 剩余休眠时间
///
/// @return Err(SystemError) 错误码
pub fn nanosleep(sleep_time: PosixTimeSpec) -> Result<PosixTimeSpec, SystemError> {
if sleep_time.tv_nsec < 0 || sleep_time.tv_nsec >= 1000000000 {
return Err(SystemError::EINVAL);
}
// 对于小于500us的时间使用spin/rdtsc来进行定时
if sleep_time.tv_nsec < 500000 && sleep_time.tv_sec == 0 {
let expired_tsc: usize = CurrentTimeArch::cal_expire_cycles(sleep_time.tv_nsec as usize);
while CurrentTimeArch::get_cycles() < expired_tsc {
spin_loop()
}
return Ok(PosixTimeSpec {
tv_sec: 0,
tv_nsec: 0,
});
}
let total_sleep_time_us: u64 =
sleep_time.tv_sec as u64 * 1000000 + sleep_time.tv_nsec as u64 / 1000;
// 创建定时器
let handler: Box<WakeUpHelper> = WakeUpHelper::new(ProcessManager::current_pcb());
let timer: Arc<Timer> = Timer::new(handler, next_n_us_timer_jiffies(total_sleep_time_us));
let irq_guard: crate::exception::IrqFlagsGuard =
unsafe { CurrentIrqArch::save_and_disable_irq() };
ProcessManager::mark_sleep(true).ok();
let start_time = getnstimeofday();
timer.activate();
drop(irq_guard);
schedule(SchedMode::SM_NONE);
let end_time = getnstimeofday();
// 返回正确的剩余时间
let real_sleep_time = end_time - start_time;
let rm_time: PosixTimeSpec = (sleep_time - real_sleep_time.into()).into();
return Ok(rm_time);
}
/// @brief 休眠指定时间(单位:微秒)
///
/// @param usec 微秒
///
/// @return Ok(TimeSpec) 剩余休眠时间
///
/// @return Err(SystemError) 错误码
pub fn usleep(sleep_time: PosixTimeSpec) -> Result<PosixTimeSpec, SystemError> {
match nanosleep(sleep_time) {
Ok(value) => return Ok(value),
Err(err) => return Err(err),
};
}
//===== 以下为提供给C的接口 =====
/// @brief 休眠指定时间单位微秒提供给C的接口
///
/// @param usec 微秒
///
/// @return Ok(i32) 0
///
/// @return Err(SystemError) 错误码
#[no_mangle]
pub extern "C" fn rs_usleep(usec: useconds_t) -> i32 {
let sleep_time = PosixTimeSpec {
tv_sec: (usec / 1000000) as i64,
tv_nsec: ((usec % 1000000) * 1000) as i64,
};
match usleep(sleep_time) {
Ok(_) => {
return 0;
}
Err(err) => {
return err.to_posix_errno();
}
};
}