feat: alarm系统调用实现 (#710)

* alarm系统调用实现
This commit is contained in:
SMALLC
2024-04-16 21:34:36 +08:00
committed by GitHub
parent d623e90231
commit fbd63a301c
14 changed files with 398 additions and 2 deletions

View File

@ -333,6 +333,7 @@ impl SigInfo {
#[derive(Copy, Clone, Debug)]
pub enum SigType {
Kill(Pid),
Alarm(Pid),
// 后续完善下列中的具体字段
// Timer,
// Rt,

View File

@ -60,6 +60,7 @@ use crate::{
},
syscall::{user_access::clear_user, Syscall},
};
use timer::AlarmTimer;
use self::kthread::WorkerPrivate;
@ -74,6 +75,7 @@ pub mod pid;
pub mod resource;
pub mod stdio;
pub mod syscall;
pub mod timer;
pub mod utils;
/// 系统中所有进程的pcb
@ -639,6 +641,9 @@ pub struct ProcessControlBlock {
/// 线程信息
thread: RwLock<ThreadInfo>,
///闹钟定时器
alarm_timer: SpinLock<Option<AlarmTimer>>,
/// 进程的robust lock列表
robust_list: RwLock<Option<RobustListHead>>,
}
@ -706,6 +711,7 @@ impl ProcessControlBlock {
children: RwLock::new(Vec::new()),
wait_queue: WaitQueue::default(),
thread: RwLock::new(ThreadInfo::new()),
alarm_timer: SpinLock::new(None),
robust_list: RwLock::new(None),
};
@ -967,6 +973,10 @@ impl ProcessControlBlock {
pub fn set_robust_list(&self, new_robust_list: Option<RobustListHead>) {
*self.robust_list.write_irqsave() = new_robust_list;
}
pub fn alarm_timer_irqsave(&self) -> SpinLockGuard<Option<AlarmTimer>> {
return self.alarm_timer.lock_irqsave();
}
}
impl Drop for ProcessControlBlock {

144
kernel/src/process/timer.rs Normal file
View File

@ -0,0 +1,144 @@
use crate::arch::ipc::signal::{SigCode, Signal};
use crate::exception::InterruptArch;
use crate::ipc::signal_types::SigType;
use crate::process::CurrentIrqArch;
use crate::process::Pid;
use crate::process::SigInfo;
use crate::time::timer::{clock, Jiffies, Timer, TimerFunction};
use alloc::{boxed::Box, sync::Arc};
use core::sync::atomic::compiler_fence;
use core::time::Duration;
use system_error::SystemError;
/// 闹钟结构体
#[derive(Debug)]
pub struct AlarmTimer {
/// 闹钟内置定时器
pub timer: Arc<Timer>,
/// 闹钟触发时间
expired_second: u64,
}
impl AlarmTimer {
/// # 创建闹钟结构体
///
/// 自定义定时器触发函数和截止时间来创建闹钟结构体
///
/// ## 函数参数
///
/// timer_func定时器触发函数
///
/// second设置alarm触发的秒数
///
/// ### 函数返回值
///
/// Self
pub fn new(timer_func: Box<dyn TimerFunction>, second: u64) -> Self {
let expired_jiffies =
<Jiffies as From<Duration>>::from(Duration::from_secs(second)).timer_jiffies();
let result = AlarmTimer {
timer: Timer::new(timer_func, expired_jiffies),
expired_second: second,
};
result
}
/// # 启动闹钟
pub fn activate(&self) {
let timer = self.timer.clone();
timer.activate();
}
/// # 初始化目标进程的alarm定时器
///
/// 创建一个闹钟结构体并启动闹钟
///
/// ## 函数参数
///
/// pid发送消息的目标进程的pid
///
/// second设置alarm触发的秒数
///
/// ### 函数返回值
///
/// AlarmTimer结构体
pub fn alarm_timer_init(pid: Pid, second: u64) -> AlarmTimer {
//初始化Timerfunc
let timerfunc = AlarmTimerFunc::new(pid);
let alarmtimer = AlarmTimer::new(timerfunc, second);
alarmtimer.activate();
alarmtimer
}
/// # 查看闹钟是否触发
pub fn timeout(&self) -> bool {
self.timer.timeout()
}
/// # 返回闹钟定时器剩余时间
pub fn remain(&self) -> Duration {
if self.timer.timeout() {
Duration::ZERO
} else {
let now_jiffies = clock();
let end_jiffies =
<Jiffies as From<Duration>>::from(Duration::from_secs(self.expired_second))
.timer_jiffies();
let remain_second = Duration::from(Jiffies::new(end_jiffies - now_jiffies));
// kdebug!(
// "end: {} - now: {} = remain: {}",
// end_jiffies,
// now_jiffies,
// end_jiffies - now_jiffies
// );
remain_second
}
}
/// # 取消闹钟
pub fn cancel(&self) {
self.timer.cancel();
}
}
/// # 闹钟TimerFuntion结构体
///
/// ## 结构成员
///
/// pid发送消息的目标进程的pid
#[derive(Debug)]
pub struct AlarmTimerFunc {
pid: Pid,
}
impl AlarmTimerFunc {
pub fn new(pid: Pid) -> Box<AlarmTimerFunc> {
return Box::new(AlarmTimerFunc { pid });
}
}
impl TimerFunction for AlarmTimerFunc {
/// # 闹钟触发函数
///
/// 闹钟触发时向目标进程发送一个SIGALRM信号
///
/// ## 函数参数
///
/// expired_second设置alarm触发的秒数
///
/// ### 函数返回值
///
/// Ok(()): 发送成功
fn run(&mut self) -> Result<(), SystemError> {
let sig = Signal::SIGALRM;
// 初始化signal info
let mut info = SigInfo::new(sig, 0, SigCode::Timer, SigType::Alarm(self.pid));
compiler_fence(core::sync::atomic::Ordering::SeqCst);
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
let _retval = sig
.send_signal_info(Some(&mut info), self.pid)
.map(|x| x as usize)?;
compiler_fence(core::sync::atomic::Ordering::SeqCst);
drop(irq_guard);
Ok(())
}
}

View File

@ -1055,6 +1055,11 @@ impl Syscall {
Err(SystemError::EINVAL)
}
SYS_ALARM => {
let second = args[0] as u32;
Self::alarm(second)
}
SYS_SHMGET => {
let key = ShmKey::new(args[0]);
let size = args[1];

View File

@ -28,7 +28,7 @@
#define SYS_DUP2 33
#define SYS_NANOSLEEP 35
#define SYS_ALARM 37
#define SYS_GETPID 39
#define SYS_SOCKET 41

View File

@ -1,9 +1,13 @@
use core::ffi::{c_int, c_longlong};
use core::{
ffi::{c_int, c_longlong},
time::Duration,
};
use num_traits::FromPrimitive;
use system_error::SystemError;
use crate::{
process::{timer::AlarmTimer, ProcessManager},
syscall::{user_access::UserBufferWriter, Syscall},
time::{sleep::nanosleep, PosixTimeSpec},
};
@ -151,4 +155,45 @@ impl Syscall {
return Ok(0);
}
/// # alarm函数功能
///
/// 设置alarm单位
///
/// ## 函数参数
///
/// expired_second设置alarm触发的秒数
///
/// ### 函数返回值
///
/// Ok(usize): 上一个alarm的剩余秒数
pub fn alarm(expired_second: u32) -> Result<usize, SystemError> {
//初始化second
let second = Duration::from_secs(expired_second as u64);
let pcb = ProcessManager::current_pcb();
let mut pcb_alarm = pcb.alarm_timer_irqsave();
let alarm = pcb_alarm.as_ref();
//alarm第一次调用
if alarm.is_none() {
//注册alarm定时器
let pid = ProcessManager::current_pid();
let new_alarm = Some(AlarmTimer::alarm_timer_init(pid, 0));
*pcb_alarm = new_alarm;
drop(pcb_alarm);
return Ok(0);
}
//查询上一个alarm的剩余时间和重新注册alarm
let alarmtimer = alarm.unwrap();
let remain = alarmtimer.remain();
if second.is_zero() {
alarmtimer.cancel();
}
if !alarmtimer.timeout() {
alarmtimer.cancel();
}
let pid = ProcessManager::current_pid();
let new_alarm = Some(AlarmTimer::alarm_timer_init(pid, second.as_secs()));
*pcb_alarm = new_alarm;
drop(pcb_alarm);
return Ok(remain.as_secs() as usize);
}
}

View File

@ -2,6 +2,7 @@ use core::{
fmt::Debug,
intrinsics::unlikely,
sync::atomic::{compiler_fence, AtomicBool, AtomicU64, Ordering},
time::Duration,
};
use alloc::{
@ -37,6 +38,51 @@ lazy_static! {
pub trait TimerFunction: Send + Sync + Debug {
fn run(&mut self) -> Result<(), SystemError>;
}
// # Jiffies结构体注意这是一段时间的jiffies数而不是某一时刻的定时器时间片
int_like!(Jiffies, u64);
impl Jiffies {
/// ## 返回接下来的n_jiffies对应的定时器时间片
pub fn timer_jiffies(&self) -> u64 {
let result = TIMER_JIFFIES.load(Ordering::SeqCst) + self.data();
result
}
}
impl From<Jiffies> for Duration {
/// # Jiffies转Duration
///
/// ## 参数
///
/// jiffies 一段时间的jiffies数
///
/// ### 返回值
///
/// Duration 这段时间的Duration形式
fn from(jiffies: Jiffies) -> Self {
let ms = jiffies.data() / 1_000_000 * NSEC_PER_JIFFY as u64;
let result = Duration::from_millis(ms);
result
}
}
impl From<Duration> for Jiffies {
/// # Duration 转 Jiffies
///
/// ## 参数
///
/// ms 表示一段时间的Duration类型
///
/// ### 返回值
///
/// Jiffies结构体 这段时间的Jiffies数
fn from(ms: Duration) -> Self {
let jiffies = ms.as_millis() as u64 * 1_000_000 / NSEC_PER_JIFFY as u64;
let result = Jiffies::new(jiffies);
result
}
}
#[derive(Debug)]
/// WakeUpHelper函数对应的结构体