136fd0130Shoumkh use core::{ 236fd0130Shoumkh fmt::Debug, 336fd0130Shoumkh intrinsics::unlikely, 436fd0130Shoumkh sync::atomic::{compiler_fence, AtomicBool, AtomicU64, Ordering}, 536fd0130Shoumkh }; 6bacd691cSlogin 7bacd691cSlogin use alloc::{ 8bacd691cSlogin boxed::Box, 9bacd691cSlogin collections::LinkedList, 10bacd691cSlogin sync::{Arc, Weak}, 11bacd691cSlogin }; 12*91e9d4abSLoGin use system_error::SystemError; 13bacd691cSlogin 14bacd691cSlogin use crate::{ 151496ba7bSLoGin arch::{sched::sched, CurrentIrqArch}, 1636fd0130Shoumkh exception::{ 1736fd0130Shoumkh softirq::{softirq_vectors, SoftirqNumber, SoftirqVec}, 1836fd0130Shoumkh InterruptArch, 19bacd691cSlogin }, 20be8cdf4bSLoGin kerror, kinfo, 21bacd691cSlogin libs::spinlock::SpinLock, 221496ba7bSLoGin process::{ProcessControlBlock, ProcessManager}, 23bacd691cSlogin }; 24bacd691cSlogin 2536fd0130Shoumkh use super::timekeeping::update_wall_time; 2636fd0130Shoumkh 27bacd691cSlogin const MAX_TIMEOUT: i64 = i64::MAX; 28bacd691cSlogin const TIMER_RUN_CYCLE_THRESHOLD: usize = 20; 2936fd0130Shoumkh static TIMER_JIFFIES: AtomicU64 = AtomicU64::new(0); 30bacd691cSlogin 31bacd691cSlogin lazy_static! { 32bacd691cSlogin pub static ref TIMER_LIST: SpinLock<LinkedList<Arc<Timer>>> = SpinLock::new(LinkedList::new()); 33bacd691cSlogin } 34bacd691cSlogin 35bacd691cSlogin /// 定时器要执行的函数的特征 3636fd0130Shoumkh pub trait TimerFunction: Send + Sync + Debug { 3736fd0130Shoumkh fn run(&mut self) -> Result<(), SystemError>; 38bacd691cSlogin } 39bacd691cSlogin 4036fd0130Shoumkh #[derive(Debug)] 41bacd691cSlogin /// WakeUpHelper函数对应的结构体 42bacd691cSlogin pub struct WakeUpHelper { 431496ba7bSLoGin pcb: Arc<ProcessControlBlock>, 44bacd691cSlogin } 45bacd691cSlogin 46bacd691cSlogin impl WakeUpHelper { 471496ba7bSLoGin pub fn new(pcb: Arc<ProcessControlBlock>) -> Box<WakeUpHelper> { 48bacd691cSlogin return Box::new(WakeUpHelper { pcb }); 49bacd691cSlogin } 50bacd691cSlogin } 51bacd691cSlogin 52bacd691cSlogin impl TimerFunction for WakeUpHelper { 5336fd0130Shoumkh fn run(&mut self) -> Result<(), SystemError> { 541496ba7bSLoGin ProcessManager::wakeup(&self.pcb).ok(); 5536fd0130Shoumkh return Ok(()); 56bacd691cSlogin } 57bacd691cSlogin } 58bacd691cSlogin 5936fd0130Shoumkh #[derive(Debug)] 60bacd691cSlogin pub struct Timer(SpinLock<InnerTimer>); 61bacd691cSlogin 62bacd691cSlogin impl Timer { 63bacd691cSlogin /// @brief 创建一个定时器(单位:ms) 64bacd691cSlogin /// 65bacd691cSlogin /// @param timer_func 定时器需要执行的函数对应的结构体 66bacd691cSlogin /// 67bacd691cSlogin /// @param expire_jiffies 定时器结束时刻 68bacd691cSlogin /// 69bacd691cSlogin /// @return 定时器结构体 70bacd691cSlogin pub fn new(timer_func: Box<dyn TimerFunction>, expire_jiffies: u64) -> Arc<Self> { 71bacd691cSlogin let result: Arc<Timer> = Arc::new(Timer(SpinLock::new(InnerTimer { 72bacd691cSlogin expire_jiffies, 73bacd691cSlogin timer_func, 74bacd691cSlogin self_ref: Weak::default(), 75971462beSGnoCiYeH triggered: false, 76bacd691cSlogin }))); 77bacd691cSlogin 78bacd691cSlogin result.0.lock().self_ref = Arc::downgrade(&result); 79bacd691cSlogin 80bacd691cSlogin return result; 81bacd691cSlogin } 82bacd691cSlogin 83bacd691cSlogin /// @brief 将定时器插入到定时器链表中 84bacd691cSlogin pub fn activate(&self) { 85bacd691cSlogin let inner_guard = self.0.lock(); 861a72a751SLoGin let mut timer_list = TIMER_LIST.lock(); 87cde5492fSlogin 88bacd691cSlogin // 链表为空,则直接插入 89bacd691cSlogin if timer_list.is_empty() { 90bacd691cSlogin // FIXME push_timer 91cde5492fSlogin 92bacd691cSlogin timer_list.push_back(inner_guard.self_ref.upgrade().unwrap()); 93cde5492fSlogin 94cde5492fSlogin drop(inner_guard); 95cde5492fSlogin drop(timer_list); 96cde5492fSlogin compiler_fence(Ordering::SeqCst); 97cde5492fSlogin 98bacd691cSlogin return; 99bacd691cSlogin } 100bacd691cSlogin let mut split_pos: usize = 0; 101bacd691cSlogin for (pos, elt) in timer_list.iter().enumerate() { 102bacd691cSlogin if elt.0.lock().expire_jiffies > inner_guard.expire_jiffies { 103bacd691cSlogin split_pos = pos; 104bacd691cSlogin break; 105bacd691cSlogin } 106bacd691cSlogin } 107bacd691cSlogin let mut temp_list: LinkedList<Arc<Timer>> = timer_list.split_off(split_pos); 108bacd691cSlogin timer_list.push_back(inner_guard.self_ref.upgrade().unwrap()); 109bacd691cSlogin timer_list.append(&mut temp_list); 110cde5492fSlogin drop(inner_guard); 111cde5492fSlogin drop(timer_list); 112bacd691cSlogin } 113bacd691cSlogin 114bacd691cSlogin #[inline] 115bacd691cSlogin fn run(&self) { 116971462beSGnoCiYeH let mut timer = self.0.lock(); 117971462beSGnoCiYeH timer.triggered = true; 118971462beSGnoCiYeH let r = timer.timer_func.run(); 11936fd0130Shoumkh if unlikely(r.is_err()) { 12036fd0130Shoumkh kerror!( 12136fd0130Shoumkh "Failed to run timer function: {self:?} {:?}", 12236fd0130Shoumkh r.err().unwrap() 12336fd0130Shoumkh ); 12436fd0130Shoumkh } 125bacd691cSlogin } 126971462beSGnoCiYeH 127971462beSGnoCiYeH /// ## 判断定时器是否已经触发 128971462beSGnoCiYeH pub fn timeout(&self) -> bool { 129971462beSGnoCiYeH self.0.lock().triggered 130971462beSGnoCiYeH } 131971462beSGnoCiYeH 132971462beSGnoCiYeH /// ## 取消定时器任务 133971462beSGnoCiYeH pub fn cancel(&self) -> bool { 134971462beSGnoCiYeH TIMER_LIST 135971462beSGnoCiYeH .lock() 1361a72a751SLoGin .extract_if(|x| Arc::<Timer>::as_ptr(&x) == self as *const Timer) 1371a72a751SLoGin .for_each(|p| drop(p)); 138971462beSGnoCiYeH true 139971462beSGnoCiYeH } 140bacd691cSlogin } 141bacd691cSlogin 142bacd691cSlogin /// 定时器类型 14336fd0130Shoumkh #[derive(Debug)] 144bacd691cSlogin pub struct InnerTimer { 145bacd691cSlogin /// 定时器结束时刻 146bacd691cSlogin pub expire_jiffies: u64, 147bacd691cSlogin /// 定时器需要执行的函数结构体 148bacd691cSlogin pub timer_func: Box<dyn TimerFunction>, 149bacd691cSlogin /// self_ref 150bacd691cSlogin self_ref: Weak<Timer>, 151971462beSGnoCiYeH /// 判断该计时器是否触发 152971462beSGnoCiYeH triggered: bool, 153bacd691cSlogin } 154bacd691cSlogin 155bacd691cSlogin #[derive(Debug)] 156bacd691cSlogin pub struct DoTimerSoftirq { 157bacd691cSlogin running: AtomicBool, 158bacd691cSlogin } 159bacd691cSlogin 160bacd691cSlogin impl DoTimerSoftirq { 161bacd691cSlogin pub fn new() -> Self { 162bacd691cSlogin return DoTimerSoftirq { 163bacd691cSlogin running: AtomicBool::new(false), 164bacd691cSlogin }; 165bacd691cSlogin } 166bacd691cSlogin 167bacd691cSlogin fn set_run(&self) -> bool { 168bacd691cSlogin let x = self 169bacd691cSlogin .running 170bacd691cSlogin .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed); 171bacd691cSlogin if x.is_ok() { 172bacd691cSlogin return true; 173bacd691cSlogin } else { 174bacd691cSlogin return false; 175bacd691cSlogin } 176bacd691cSlogin } 177bacd691cSlogin 178bacd691cSlogin fn clear_run(&self) { 179bacd691cSlogin self.running.store(false, Ordering::Release); 180bacd691cSlogin } 181bacd691cSlogin } 182bacd691cSlogin impl SoftirqVec for DoTimerSoftirq { 183bacd691cSlogin fn run(&self) { 184bacd691cSlogin if self.set_run() == false { 185bacd691cSlogin return; 186bacd691cSlogin } 187bacd691cSlogin // 最多只处理TIMER_RUN_CYCLE_THRESHOLD个计时器 188bacd691cSlogin for _ in 0..TIMER_RUN_CYCLE_THRESHOLD { 189bacd691cSlogin // kdebug!("DoTimerSoftirq run"); 190cde5492fSlogin let timer_list = TIMER_LIST.try_lock(); 191cde5492fSlogin if timer_list.is_err() { 192cde5492fSlogin continue; 193cde5492fSlogin } 194cde5492fSlogin let mut timer_list = timer_list.unwrap(); 195bacd691cSlogin 196bacd691cSlogin if timer_list.is_empty() { 197bacd691cSlogin break; 198bacd691cSlogin } 199bacd691cSlogin 200cde5492fSlogin let timer_list_front = timer_list.pop_front().unwrap(); 201cde5492fSlogin // kdebug!("to lock timer_list_front"); 202cde5492fSlogin let mut timer_list_front_guard = None; 203cde5492fSlogin for _ in 0..10 { 204cde5492fSlogin let x = timer_list_front.0.try_lock(); 205cde5492fSlogin if x.is_err() { 206cde5492fSlogin continue; 207bacd691cSlogin } 208cde5492fSlogin timer_list_front_guard = Some(x.unwrap()); 209cde5492fSlogin } 210cde5492fSlogin if timer_list_front_guard.is_none() { 211cde5492fSlogin continue; 212cde5492fSlogin } 213cde5492fSlogin let timer_list_front_guard = timer_list_front_guard.unwrap(); 21436fd0130Shoumkh if timer_list_front_guard.expire_jiffies > TIMER_JIFFIES.load(Ordering::SeqCst) { 215cde5492fSlogin drop(timer_list_front_guard); 216cde5492fSlogin timer_list.push_front(timer_list_front); 217cde5492fSlogin break; 218cde5492fSlogin } 219cde5492fSlogin drop(timer_list_front_guard); 220cde5492fSlogin drop(timer_list); 221cde5492fSlogin timer_list_front.run(); 222bacd691cSlogin } 223bacd691cSlogin 224bacd691cSlogin self.clear_run(); 225bacd691cSlogin } 226bacd691cSlogin } 227bacd691cSlogin 228bacd691cSlogin /// @brief 初始化timer模块 229bacd691cSlogin pub fn timer_init() { 230bacd691cSlogin // FIXME 调用register_trap 231bacd691cSlogin let do_timer_softirq = Arc::new(DoTimerSoftirq::new()); 232bacd691cSlogin softirq_vectors() 233bacd691cSlogin .register_softirq(SoftirqNumber::TIMER, do_timer_softirq) 234bacd691cSlogin .expect("Failed to register timer softirq"); 23540fe15e0SLoGin kinfo!("timer initialized successfully"); 236bacd691cSlogin } 237bacd691cSlogin 238bacd691cSlogin /// 计算接下来n毫秒对应的定时器时间片 239bacd691cSlogin pub fn next_n_ms_timer_jiffies(expire_ms: u64) -> u64 { 24036fd0130Shoumkh return TIMER_JIFFIES.load(Ordering::SeqCst) + 1000 * (expire_ms); 241bacd691cSlogin } 242bacd691cSlogin /// 计算接下来n微秒对应的定时器时间片 243bacd691cSlogin pub fn next_n_us_timer_jiffies(expire_us: u64) -> u64 { 24436fd0130Shoumkh return TIMER_JIFFIES.load(Ordering::SeqCst) + (expire_us); 245bacd691cSlogin } 246bacd691cSlogin 247bacd691cSlogin /// @brief 让pcb休眠timeout个jiffies 248bacd691cSlogin /// 249bacd691cSlogin /// @param timeout 需要休眠的时间(单位:jiffies) 250bacd691cSlogin /// 251bacd691cSlogin /// @return Ok(i64) 剩余需要休眠的时间(单位:jiffies) 252bacd691cSlogin /// 253bacd691cSlogin /// @return Err(SystemError) 错误码 254bacd691cSlogin pub fn schedule_timeout(mut timeout: i64) -> Result<i64, SystemError> { 255bacd691cSlogin // kdebug!("schedule_timeout"); 256bacd691cSlogin if timeout == MAX_TIMEOUT { 257be8cdf4bSLoGin ProcessManager::mark_sleep(true).ok(); 258bacd691cSlogin sched(); 259bacd691cSlogin return Ok(MAX_TIMEOUT); 260bacd691cSlogin } else if timeout < 0 { 261bacd691cSlogin kerror!("timeout can't less than 0"); 262bacd691cSlogin return Err(SystemError::EINVAL); 263bacd691cSlogin } else { 264bacd691cSlogin // 禁用中断,防止在这段期间发生调度,造成死锁 26536fd0130Shoumkh let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 26636fd0130Shoumkh 26736fd0130Shoumkh timeout += TIMER_JIFFIES.load(Ordering::SeqCst) as i64; 2681496ba7bSLoGin let timer = Timer::new( 2691496ba7bSLoGin WakeUpHelper::new(ProcessManager::current_pcb()), 2701496ba7bSLoGin timeout as u64, 2711496ba7bSLoGin ); 2721496ba7bSLoGin ProcessManager::mark_sleep(true).ok(); 273bacd691cSlogin timer.activate(); 27436fd0130Shoumkh 27536fd0130Shoumkh drop(irq_guard); 276bacd691cSlogin 277bacd691cSlogin sched(); 27836fd0130Shoumkh let time_remaining: i64 = timeout - TIMER_JIFFIES.load(Ordering::SeqCst) as i64; 279bacd691cSlogin if time_remaining >= 0 { 280bacd691cSlogin // 被提前唤醒,返回剩余时间 281bacd691cSlogin return Ok(time_remaining); 282bacd691cSlogin } else { 283bacd691cSlogin return Ok(0); 284bacd691cSlogin } 285bacd691cSlogin } 286bacd691cSlogin } 287bacd691cSlogin 288bacd691cSlogin pub fn timer_get_first_expire() -> Result<u64, SystemError> { 289bacd691cSlogin // FIXME 290bacd691cSlogin // kdebug!("rs_timer_get_first_expire,timer_jif = {:?}", TIMER_JIFFIES); 291bacd691cSlogin for _ in 0..10 { 292be8cdf4bSLoGin match TIMER_LIST.try_lock_irqsave() { 293bacd691cSlogin Ok(timer_list) => { 294bacd691cSlogin // kdebug!("rs_timer_get_first_expire TIMER_LIST lock successfully"); 295bacd691cSlogin if timer_list.is_empty() { 296bacd691cSlogin // kdebug!("timer_list is empty"); 297bacd691cSlogin return Ok(0); 298bacd691cSlogin } else { 299bacd691cSlogin // kdebug!("timer_list not empty"); 300bacd691cSlogin return Ok(timer_list.front().unwrap().0.lock().expire_jiffies); 301bacd691cSlogin } 302bacd691cSlogin } 303bacd691cSlogin // 加锁失败返回啥?? 304bacd691cSlogin Err(_) => continue, 305bacd691cSlogin } 306bacd691cSlogin } 30779a452ceShoumkh return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 308bacd691cSlogin } 309bacd691cSlogin 310be8cdf4bSLoGin /// 更新系统时间片 311be8cdf4bSLoGin /// 312be8cdf4bSLoGin /// todo: 这里的实现有问题,貌似把HPET的500us当成了500个jiffies,然后update_wall_time()里面也硬编码了这个500us 313bacd691cSlogin pub fn update_timer_jiffies(add_jiffies: u64) -> u64 { 31436fd0130Shoumkh let prev = TIMER_JIFFIES.fetch_add(add_jiffies, Ordering::SeqCst); 31536fd0130Shoumkh compiler_fence(Ordering::SeqCst); 31636fd0130Shoumkh update_wall_time(); 31736fd0130Shoumkh 31836fd0130Shoumkh compiler_fence(Ordering::SeqCst); 31936fd0130Shoumkh return prev + add_jiffies; 320bacd691cSlogin } 32136fd0130Shoumkh 322bacd691cSlogin pub fn clock() -> u64 { 32336fd0130Shoumkh return TIMER_JIFFIES.load(Ordering::SeqCst); 324bacd691cSlogin } 325bacd691cSlogin 326bacd691cSlogin // ====== 以下为给C提供的接口 ====== 327bacd691cSlogin 328bacd691cSlogin #[no_mangle] 329bacd691cSlogin pub extern "C" fn rs_timer_init() { 330bacd691cSlogin timer_init(); 331bacd691cSlogin } 332