starnix_core/task/
timers.rs1use crate::signals::{SignalEvent, SignalEventNotify, SignalEventValue};
6use crate::task::interval_timer::{IntervalTimer, IntervalTimerHandle};
7use crate::task::{CurrentTask, Timeline, TimerWakeup};
8use starnix_sync::Mutex;
9use starnix_uapi::errors::Errno;
10use starnix_uapi::signals::SIGALRM;
11use starnix_uapi::{TIMER_ABSTIME, error, itimerspec, uapi};
12use std::collections::HashMap;
13
14static_assertions::const_assert!(
15 std::mem::size_of::<uapi::__kernel_timer_t>()
16 == std::mem::size_of::<uapi::arch32::__kernel_timer_t>()
17);
18pub type TimerId = uapi::__kernel_timer_t;
19
20static_assertions::const_assert!(
21 std::mem::size_of::<uapi::__kernel_clockid_t>()
22 == std::mem::size_of::<uapi::arch32::__kernel_clockid_t>()
23);
24pub type ClockId = uapi::__kernel_clockid_t;
25
26#[derive(Debug, Default)]
29pub struct TimerTable {
30 state: Mutex<TimerTableMutableState>,
31}
32
33#[derive(Debug)]
34struct TimerTableMutableState {
35 next_timer_id: TimerId,
37 timers: HashMap<TimerId, IntervalTimerHandle>,
38 itimer_real: IntervalTimerHandle,
39}
40
41impl Default for TimerTableMutableState {
42 fn default() -> Self {
43 let signal_event =
44 SignalEvent::new(SignalEventValue(0), SIGALRM, SignalEventNotify::Signal);
45 let itimer_real =
46 IntervalTimer::new(0, Timeline::RealTime, TimerWakeup::Regular, signal_event)
47 .expect("Failed to create itimer_real");
48 TimerTableMutableState {
49 itimer_real,
50 timers: Default::default(),
51 next_timer_id: Default::default(),
52 }
53 }
54}
55
56impl TimerTable {
57 pub fn create(
61 &self,
62 timeline: Timeline,
63 wakeup_type: TimerWakeup,
64 signal_event: Option<SignalEvent>,
65 ) -> Result<TimerId, Errno> {
66 let mut state = self.state.lock();
67
68 let end = state.next_timer_id;
70 let timer_id = loop {
71 let timer_id = state.next_timer_id;
72 state.next_timer_id += 1;
73
74 if state.next_timer_id == TimerId::MAX {
75 state.next_timer_id = 0;
76 } else if state.next_timer_id == end {
77 return error!(EAGAIN);
80 }
81
82 if !state.timers.contains_key(&timer_id) {
83 break timer_id;
84 }
85 };
86
87 state.timers.insert(
88 timer_id,
89 IntervalTimer::new(
90 timer_id,
91 timeline,
92 wakeup_type,
93 signal_event.unwrap_or_else(|| {
94 SignalEvent::new(
95 SignalEventValue(timer_id as u64),
96 SIGALRM,
97 SignalEventNotify::Signal,
98 )
99 }),
100 )?,
101 );
102
103 Ok(timer_id)
104 }
105
106 pub fn itimer_real(&self) -> IntervalTimerHandle {
107 self.state.lock().itimer_real.clone()
108 }
109
110 pub fn delete(&self, current_task: &CurrentTask, id: TimerId) -> Result<(), Errno> {
112 let mut state = self.state.lock();
113 match state.timers.remove_entry(&id) {
114 Some(entry) => entry.1.disarm(current_task),
115 None => error!(EINVAL),
116 }
117 }
118
119 pub fn get_time(&self, id: TimerId) -> Result<itimerspec, Errno> {
122 Ok(self.get_timer(id)?.time_remaining().into())
123 }
124
125 pub fn get_overrun(&self, id: TimerId) -> Result<i32, Errno> {
127 Ok(self.get_timer(id)?.overrun_last())
128 }
129
130 pub fn set_time(
134 &self,
135 current_task: &CurrentTask,
136 id: TimerId,
137 flags: i32,
138 new_value: itimerspec,
139 ) -> Result<itimerspec, Errno> {
140 let itimer = self.get_timer(id)?;
141 let old_value: itimerspec = itimer.time_remaining().into();
142 if new_value.it_value.tv_sec != 0 || new_value.it_value.tv_nsec != 0 {
143 let is_absolute = flags == TIMER_ABSTIME as i32;
144 itimer.arm(current_task, new_value, is_absolute)?;
145 } else {
146 itimer.disarm(current_task)?;
147 }
148
149 Ok(old_value)
150 }
151
152 pub fn get_timer(&self, id: TimerId) -> Result<IntervalTimerHandle, Errno> {
153 match self.state.lock().timers.get(&id) {
154 Some(itimer) => Ok(itimer.clone()),
155 None => error!(EINVAL),
156 }
157 }
158}