os/kernel/
timer.rs

1//! 定时器队列模块
2//!
3//! 该模块实现了一个简单的定时器队列,用于管理和调度定时任务。
4
5use core::ptr;
6
7use alloc::{collections::btree_map::BTreeMap, sync::Arc};
8
9use crate::{kernel::SharedTask, sync::SpinLock, vfs::TimeSpec};
10
11lazy_static::lazy_static! {
12    /// 全局等待队列实例
13    /// 使用硬件时钟周期数作为时间单位
14    /// 在定时器触发时唤醒任务
15    pub static ref TIMER_QUEUE: SpinLock<TimerQueue> = SpinLock::new(TimerQueue::new());
16    /// 定时器队列
17    /// 使用硬件时钟周期数作为时间单位
18    /// 在定时器触发时向任务发送对应信号
19    pub static ref TIMER: SpinLock<TimerEntries> = SpinLock::new(TimerEntries::new());
20}
21
22/// 定时器队列,用于管理定时任务
23pub struct TimerQueue {
24    /// 以触发时间为键,任务为值的有序映射
25    queue: BTreeMap<usize, SharedTask>,
26}
27
28impl TimerQueue {
29    /// 创建一个新的定时器队列
30    pub fn new() -> Self {
31        Self {
32            queue: BTreeMap::new(),
33        }
34    }
35
36    /// 向队列中添加一个定时任务
37    /// # 参数:
38    /// - `trigger_time`: 任务触发的时间点
39    /// - `task`: 需要执行的任务
40    pub fn push(&mut self, mut trigger_time: usize, task: SharedTask) {
41        while self.queue.contains_key(&trigger_time) {
42            trigger_time += 1;
43        }
44        self.queue.insert(trigger_time, task);
45    }
46
47    /// 弹出已到期的任务
48    /// # 参数:
49    /// - `current_time`: 当前时间点
50    /// # 返回值:
51    /// - 已到期的任务(如果有)
52    pub fn pop_due_task(&mut self, current_time: usize) -> Option<SharedTask> {
53        if let Some((&trigger_time, _)) = self.queue.iter().next() {
54            if trigger_time <= current_time {
55                return self.queue.remove(&trigger_time);
56            }
57        }
58        None
59    }
60
61    /// 移除指定任务
62    /// # 参数:
63    /// - `task`: 需要移除的任务
64    /// # 返回值:
65    /// - 被移除的任务(如果存在)
66    pub fn remove_task(&mut self, task: &SharedTask) -> Option<SharedTask> {
67        let key = self.queue.iter().find_map(|(time, t)| {
68            if Arc::ptr_eq(task, t) {
69                Some(*time)
70            } else {
71                None
72            }
73        })?;
74        self.queue.remove(&key)
75    }
76}
77
78/// 定时器条目
79pub struct TimerEntry {
80    /// 信号编号
81    pub sig: usize,
82    /// 关联的任务
83    pub task: SharedTask,
84    /// 定时器周期
85    pub it_interval: TimeSpec,
86}
87
88impl TimerEntry {
89    /// 创建一个新的定时器条目
90    pub fn new(sig: usize, task: SharedTask, it_interval: TimeSpec) -> Self {
91        Self {
92            sig,
93            task,
94            it_interval,
95        }
96    }
97}
98
99/// 定时器条目集合
100pub struct TimerEntries {
101    pub entries: BTreeMap<usize, TimerEntry>,
102}
103
104impl TimerEntries {
105    /// 创建一个新的定时器条目集合
106    pub fn new() -> Self {
107        Self {
108            entries: BTreeMap::new(),
109        }
110    }
111
112    /// 向集合中添加一个定时器条目
113    /// # 参数:
114    /// - `trigger_time`: 触发时间点
115    /// - `entry`: 定时器条目
116    pub fn push(&mut self, trigger_time: usize, entry: TimerEntry) {
117        self.entries.insert(trigger_time, entry);
118    }
119
120    /// 弹出已到期的定时器条目
121    /// # 参数:
122    /// - `current_time`: 当前时间点
123    /// # 返回值:
124    /// - 已到期的定时器条目(如果有)
125    pub fn pop_due_entry(&mut self, current_time: usize) -> Option<TimerEntry> {
126        if let Some((&trigger_time, _)) = self.entries.iter().next() {
127            if trigger_time <= current_time {
128                return self.entries.remove(&trigger_time);
129            }
130        }
131        None
132    }
133
134    /// 查找与指定任务关联的定时器条目
135    /// # 参数:
136    /// - `task`: 目标任务
137    /// # 返回值:
138    /// - 关联的定时器条目(如果存在)
139    pub fn find_entry(&self, task: &SharedTask, sig: usize) -> Option<(&usize, &TimerEntry)> {
140        for (time, entry) in self.entries.iter() {
141            if ptr::eq(task, &entry.task) && entry.sig == sig {
142                return Some((time, entry));
143            }
144        }
145        None
146    }
147
148    /// 移除与指定任务关联的定时器条目
149    /// # 参数:
150    /// - `task`: 目标任务
151    /// # 返回值:
152    /// - 被移除的定时器条目(如果存在)
153    pub fn remove_entry(&mut self, task: &SharedTask, sig: usize) -> Option<TimerEntry> {
154        let key = self.find_entry(task, sig).map(|(time, _)| *time)?;
155        self.entries.remove(&key)
156    }
157}