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