1bacd691cSlogin use core::sync::atomic::{AtomicBool, Ordering}; 2bacd691cSlogin 3bacd691cSlogin use alloc::{ 4bacd691cSlogin boxed::Box, 5bacd691cSlogin collections::LinkedList, 6bacd691cSlogin sync::{Arc, Weak}, 7bacd691cSlogin }; 8bacd691cSlogin 9bacd691cSlogin use crate::{ 10bacd691cSlogin arch::{ 11bacd691cSlogin asm::current::current_pcb, 12bacd691cSlogin interrupt::{cli, sti}, 13bacd691cSlogin sched::sched, 14bacd691cSlogin }, 15bacd691cSlogin exception::softirq::{softirq_vectors, SoftirqNumber, SoftirqVec}, 16bacd691cSlogin include::bindings::bindings::{process_control_block, process_wakeup, pt_regs, PROC_RUNNING}, 17bacd691cSlogin kdebug, kerror, 18bacd691cSlogin libs::spinlock::SpinLock, 19bacd691cSlogin syscall::SystemError, 20bacd691cSlogin }; 21bacd691cSlogin 22bacd691cSlogin const MAX_TIMEOUT: i64 = i64::MAX; 23bacd691cSlogin const TIMER_RUN_CYCLE_THRESHOLD: usize = 20; 24bacd691cSlogin static mut TIMER_JIFFIES: u64 = 0; 25bacd691cSlogin 26bacd691cSlogin lazy_static! { 27bacd691cSlogin pub static ref TIMER_LIST: SpinLock<LinkedList<Arc<Timer>>> = SpinLock::new(LinkedList::new()); 28bacd691cSlogin } 29bacd691cSlogin 30bacd691cSlogin /// 定时器要执行的函数的特征 31bacd691cSlogin pub trait TimerFunction: Send + Sync { 32bacd691cSlogin fn run(&mut self); 33bacd691cSlogin } 34bacd691cSlogin 35bacd691cSlogin /// WakeUpHelper函数对应的结构体 36bacd691cSlogin pub struct WakeUpHelper { 37bacd691cSlogin pcb: &'static mut process_control_block, 38bacd691cSlogin } 39bacd691cSlogin 40bacd691cSlogin impl WakeUpHelper { 41bacd691cSlogin pub fn new(pcb: &'static mut process_control_block) -> Box<WakeUpHelper> { 42bacd691cSlogin return Box::new(WakeUpHelper { pcb }); 43bacd691cSlogin } 44bacd691cSlogin } 45bacd691cSlogin 46bacd691cSlogin impl TimerFunction for WakeUpHelper { 47bacd691cSlogin fn run(&mut self) { 48bacd691cSlogin unsafe { 49bacd691cSlogin process_wakeup(self.pcb); 50bacd691cSlogin } 51bacd691cSlogin } 52bacd691cSlogin } 53bacd691cSlogin 54bacd691cSlogin pub struct Timer(SpinLock<InnerTimer>); 55bacd691cSlogin 56bacd691cSlogin impl Timer { 57bacd691cSlogin /// @brief 创建一个定时器(单位:ms) 58bacd691cSlogin /// 59bacd691cSlogin /// @param timer_func 定时器需要执行的函数对应的结构体 60bacd691cSlogin /// 61bacd691cSlogin /// @param expire_jiffies 定时器结束时刻 62bacd691cSlogin /// 63bacd691cSlogin /// @return 定时器结构体 64bacd691cSlogin pub fn new(timer_func: Box<dyn TimerFunction>, expire_jiffies: u64) -> Arc<Self> { 65bacd691cSlogin let result: Arc<Timer> = Arc::new(Timer(SpinLock::new(InnerTimer { 66bacd691cSlogin expire_jiffies, 67bacd691cSlogin timer_func, 68bacd691cSlogin self_ref: Weak::default(), 69bacd691cSlogin }))); 70bacd691cSlogin 71bacd691cSlogin result.0.lock().self_ref = Arc::downgrade(&result); 72bacd691cSlogin 73bacd691cSlogin return result; 74bacd691cSlogin } 75bacd691cSlogin 76bacd691cSlogin /// @brief 将定时器插入到定时器链表中 77bacd691cSlogin pub fn activate(&self) { 78bacd691cSlogin let timer_list = &mut TIMER_LIST.lock(); 79bacd691cSlogin let inner_guard = self.0.lock(); 80bacd691cSlogin // 链表为空,则直接插入 81bacd691cSlogin if timer_list.is_empty() { 82bacd691cSlogin // FIXME push_timer 83bacd691cSlogin timer_list.push_back(inner_guard.self_ref.upgrade().unwrap()); 84bacd691cSlogin return; 85bacd691cSlogin } 86bacd691cSlogin 87bacd691cSlogin let mut split_pos: usize = 0; 88bacd691cSlogin for (pos, elt) in timer_list.iter().enumerate() { 89bacd691cSlogin if elt.0.lock().expire_jiffies > inner_guard.expire_jiffies { 90bacd691cSlogin split_pos = pos; 91bacd691cSlogin break; 92bacd691cSlogin } 93bacd691cSlogin } 94bacd691cSlogin let mut temp_list: LinkedList<Arc<Timer>> = timer_list.split_off(split_pos); 95bacd691cSlogin timer_list.push_back(inner_guard.self_ref.upgrade().unwrap()); 96bacd691cSlogin timer_list.append(&mut temp_list); 97bacd691cSlogin } 98bacd691cSlogin 99bacd691cSlogin #[inline] 100bacd691cSlogin fn run(&self) { 101bacd691cSlogin self.0.lock().timer_func.run(); 102bacd691cSlogin } 103bacd691cSlogin } 104bacd691cSlogin 105bacd691cSlogin /// 定时器类型 106bacd691cSlogin pub struct InnerTimer { 107bacd691cSlogin /// 定时器结束时刻 108bacd691cSlogin pub expire_jiffies: u64, 109bacd691cSlogin /// 定时器需要执行的函数结构体 110bacd691cSlogin pub timer_func: Box<dyn TimerFunction>, 111bacd691cSlogin /// self_ref 112bacd691cSlogin self_ref: Weak<Timer>, 113bacd691cSlogin } 114bacd691cSlogin 115bacd691cSlogin #[derive(Debug)] 116bacd691cSlogin pub struct DoTimerSoftirq { 117bacd691cSlogin running: AtomicBool, 118bacd691cSlogin } 119bacd691cSlogin 120bacd691cSlogin impl DoTimerSoftirq { 121bacd691cSlogin pub fn new() -> Self { 122bacd691cSlogin return DoTimerSoftirq { 123bacd691cSlogin running: AtomicBool::new(false), 124bacd691cSlogin }; 125bacd691cSlogin } 126bacd691cSlogin 127bacd691cSlogin fn set_run(&self) -> bool { 128bacd691cSlogin let x = self 129bacd691cSlogin .running 130bacd691cSlogin .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed); 131bacd691cSlogin if x.is_ok() { 132bacd691cSlogin return true; 133bacd691cSlogin } else { 134bacd691cSlogin return false; 135bacd691cSlogin } 136bacd691cSlogin } 137bacd691cSlogin 138bacd691cSlogin fn clear_run(&self) { 139bacd691cSlogin self.running.store(false, Ordering::Release); 140bacd691cSlogin } 141bacd691cSlogin } 142bacd691cSlogin impl SoftirqVec for DoTimerSoftirq { 143bacd691cSlogin fn run(&self) { 144bacd691cSlogin if self.set_run() == false { 145bacd691cSlogin return; 146bacd691cSlogin } 147bacd691cSlogin // 最多只处理TIMER_RUN_CYCLE_THRESHOLD个计时器 148bacd691cSlogin for _ in 0..TIMER_RUN_CYCLE_THRESHOLD { 149bacd691cSlogin // kdebug!("DoTimerSoftirq run"); 150bacd691cSlogin 151bacd691cSlogin let timer_list = &mut TIMER_LIST.lock(); 152bacd691cSlogin 153bacd691cSlogin if timer_list.is_empty() { 154bacd691cSlogin break; 155bacd691cSlogin } 156bacd691cSlogin 157bacd691cSlogin if timer_list.front().unwrap().0.lock().expire_jiffies 158bacd691cSlogin <= unsafe { TIMER_JIFFIES as u64 } 159bacd691cSlogin { 160bacd691cSlogin let timer = timer_list.pop_front().unwrap(); 161bacd691cSlogin drop(timer_list); 162bacd691cSlogin timer.run(); 163bacd691cSlogin } 164bacd691cSlogin } 165bacd691cSlogin 166bacd691cSlogin self.clear_run(); 167bacd691cSlogin } 168bacd691cSlogin } 169bacd691cSlogin 170bacd691cSlogin /// @brief 初始化timer模块 171bacd691cSlogin pub fn timer_init() { 172bacd691cSlogin // FIXME 调用register_trap 173bacd691cSlogin let do_timer_softirq = Arc::new(DoTimerSoftirq::new()); 174bacd691cSlogin softirq_vectors() 175bacd691cSlogin .register_softirq(SoftirqNumber::TIMER, do_timer_softirq) 176bacd691cSlogin .expect("Failed to register timer softirq"); 177bacd691cSlogin kdebug!("timer initiated successfully"); 178bacd691cSlogin } 179bacd691cSlogin 180bacd691cSlogin /// 计算接下来n毫秒对应的定时器时间片 181bacd691cSlogin pub fn next_n_ms_timer_jiffies(expire_ms: u64) -> u64 { 182bacd691cSlogin return unsafe { TIMER_JIFFIES as u64 } + 1000 * (expire_ms); 183bacd691cSlogin } 184bacd691cSlogin /// 计算接下来n微秒对应的定时器时间片 185bacd691cSlogin pub fn next_n_us_timer_jiffies(expire_us: u64) -> u64 { 186bacd691cSlogin return unsafe { TIMER_JIFFIES as u64 } + (expire_us); 187bacd691cSlogin } 188bacd691cSlogin 189bacd691cSlogin /// @brief 让pcb休眠timeout个jiffies 190bacd691cSlogin /// 191bacd691cSlogin /// @param timeout 需要休眠的时间(单位:jiffies) 192bacd691cSlogin /// 193bacd691cSlogin /// @return Ok(i64) 剩余需要休眠的时间(单位:jiffies) 194bacd691cSlogin /// 195bacd691cSlogin /// @return Err(SystemError) 错误码 196bacd691cSlogin pub fn schedule_timeout(mut timeout: i64) -> Result<i64, SystemError> { 197bacd691cSlogin // kdebug!("schedule_timeout"); 198bacd691cSlogin if timeout == MAX_TIMEOUT { 199bacd691cSlogin sched(); 200bacd691cSlogin return Ok(MAX_TIMEOUT); 201bacd691cSlogin } else if timeout < 0 { 202bacd691cSlogin kerror!("timeout can't less than 0"); 203bacd691cSlogin return Err(SystemError::EINVAL); 204bacd691cSlogin } else { 205bacd691cSlogin // 禁用中断,防止在这段期间发生调度,造成死锁 206bacd691cSlogin cli(); 207bacd691cSlogin timeout += unsafe { TIMER_JIFFIES } as i64; 208bacd691cSlogin let timer = Timer::new(WakeUpHelper::new(current_pcb()), timeout as u64); 209bacd691cSlogin timer.activate(); 210bacd691cSlogin current_pcb().state &= (!PROC_RUNNING) as u64; 211bacd691cSlogin sti(); 212bacd691cSlogin 213bacd691cSlogin sched(); 214bacd691cSlogin let time_remaining: i64 = timeout - unsafe { TIMER_JIFFIES } as i64; 215bacd691cSlogin if time_remaining >= 0 { 216bacd691cSlogin // 被提前唤醒,返回剩余时间 217bacd691cSlogin return Ok(time_remaining); 218bacd691cSlogin } else { 219bacd691cSlogin return Ok(0); 220bacd691cSlogin } 221bacd691cSlogin } 222bacd691cSlogin } 223bacd691cSlogin 224bacd691cSlogin pub fn timer_get_first_expire() -> Result<u64, SystemError> { 225bacd691cSlogin // FIXME 226bacd691cSlogin // kdebug!("rs_timer_get_first_expire,timer_jif = {:?}", TIMER_JIFFIES); 227bacd691cSlogin for _ in 0..10 { 228bacd691cSlogin match TIMER_LIST.try_lock() { 229bacd691cSlogin Ok(timer_list) => { 230bacd691cSlogin // kdebug!("rs_timer_get_first_expire TIMER_LIST lock successfully"); 231bacd691cSlogin if timer_list.is_empty() { 232bacd691cSlogin // kdebug!("timer_list is empty"); 233bacd691cSlogin return Ok(0); 234bacd691cSlogin } else { 235bacd691cSlogin // kdebug!("timer_list not empty"); 236bacd691cSlogin return Ok(timer_list.front().unwrap().0.lock().expire_jiffies); 237bacd691cSlogin } 238bacd691cSlogin } 239bacd691cSlogin // 加锁失败返回啥?? 240bacd691cSlogin Err(_) => continue, 241bacd691cSlogin } 242bacd691cSlogin } 243*79a452ceShoumkh return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 244bacd691cSlogin } 245bacd691cSlogin 246bacd691cSlogin pub fn update_timer_jiffies(add_jiffies: u64) -> u64 { 247bacd691cSlogin unsafe { TIMER_JIFFIES += add_jiffies }; 248bacd691cSlogin return unsafe { TIMER_JIFFIES }; 249bacd691cSlogin } 250bacd691cSlogin pub fn clock() -> u64 { 251bacd691cSlogin return unsafe { TIMER_JIFFIES }; 252bacd691cSlogin } 253bacd691cSlogin // ====== 重构完成后请删掉extern C ====== 254bacd691cSlogin #[no_mangle] 255bacd691cSlogin pub extern "C" fn rs_clock() -> u64 { 256bacd691cSlogin clock() 257bacd691cSlogin } 258bacd691cSlogin #[no_mangle] 259bacd691cSlogin pub extern "C" fn sys_clock(_regs: *const pt_regs) -> u64 { 260bacd691cSlogin clock() 261bacd691cSlogin } 262bacd691cSlogin 263bacd691cSlogin // ====== 以下为给C提供的接口 ====== 264bacd691cSlogin #[no_mangle] 265bacd691cSlogin pub extern "C" fn rs_schedule_timeout(timeout: i64) -> i64 { 266bacd691cSlogin match schedule_timeout(timeout) { 267bacd691cSlogin Ok(v) => { 268bacd691cSlogin return v; 269bacd691cSlogin } 270bacd691cSlogin Err(e) => { 271bacd691cSlogin kdebug!("rs_schedule_timeout run failed"); 272bacd691cSlogin return e.to_posix_errno() as i64; 273bacd691cSlogin } 274bacd691cSlogin } 275bacd691cSlogin } 276bacd691cSlogin 277bacd691cSlogin #[no_mangle] 278bacd691cSlogin pub extern "C" fn rs_timer_init() { 279bacd691cSlogin timer_init(); 280bacd691cSlogin } 281bacd691cSlogin 282bacd691cSlogin #[no_mangle] 283bacd691cSlogin pub extern "C" fn rs_timer_next_n_ms_jiffies(expire_ms: u64) -> u64 { 284bacd691cSlogin return next_n_ms_timer_jiffies(expire_ms); 285bacd691cSlogin } 286bacd691cSlogin 287bacd691cSlogin #[no_mangle] 288bacd691cSlogin pub extern "C" fn rs_timer_next_n_us_jiffies(expire_us: u64) -> u64 { 289bacd691cSlogin return next_n_us_timer_jiffies(expire_us); 290bacd691cSlogin } 291bacd691cSlogin 292bacd691cSlogin #[no_mangle] 293bacd691cSlogin pub extern "C" fn rs_timer_get_first_expire() -> i64 { 294bacd691cSlogin match timer_get_first_expire() { 295bacd691cSlogin Ok(v) => return v as i64, 296bacd691cSlogin Err(e) => return e.to_posix_errno() as i64, 297bacd691cSlogin } 298bacd691cSlogin } 299bacd691cSlogin 300bacd691cSlogin #[no_mangle] 301bacd691cSlogin pub extern "C" fn rs_update_timer_jiffies(add_jiffies: u64) -> u64 { 302bacd691cSlogin return update_timer_jiffies(add_jiffies); 303bacd691cSlogin } 304