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