preemptive_threads/time/timer.rs
1//! Timer configuration and interrupt management.
2
3use super::Duration;
4use crate::arch::Arch;
5
6/// Timer configuration for preemptive scheduling.
7#[derive(Debug, Clone)]
8pub struct TimerConfig {
9 /// Timer frequency in Hz (interrupts per second)
10 pub frequency: u32,
11 /// Timer interrupt vector number
12 pub vector: u8,
13 /// Whether high-precision timing is enabled
14 pub high_precision: bool,
15}
16
17impl Default for TimerConfig {
18 fn default() -> Self {
19 Self {
20 frequency: super::TIMER_FREQUENCY_HZ,
21 vector: 0xEF, // Default timer vector
22 high_precision: true,
23 }
24 }
25}
26
27/// Timer abstraction for different hardware timers.
28pub trait Timer {
29 /// Initialize the timer with the given configuration.
30 ///
31 /// # Safety
32 ///
33 /// This function configures hardware timers and interrupt vectors.
34 /// It must only be called once during system initialization with
35 /// interrupts disabled.
36 unsafe fn init(&mut self, config: &TimerConfig) -> Result<(), TimerError>;
37
38 /// Start the timer.
39 ///
40 /// The timer will begin generating interrupts at the configured frequency.
41 fn start(&mut self) -> Result<(), TimerError>;
42
43 /// Stop the timer.
44 ///
45 /// This stops interrupt generation but preserves timer configuration.
46 fn stop(&mut self) -> Result<(), TimerError>;
47
48 /// Get the current timer count.
49 ///
50 /// This provides access to the hardware timer's current count value
51 /// for high-precision timing measurements.
52 fn current_count(&self) -> u64;
53
54 /// Convert timer counts to nanoseconds.
55 fn counts_to_nanos(&self, counts: u64) -> u64;
56
57 /// Convert nanoseconds to timer counts.
58 fn nanos_to_counts(&self, nanos: u64) -> u64;
59
60 /// Set up a one-shot timer for the given duration.
61 ///
62 /// This is used for implementing sleep and timeout functionality.
63 fn set_oneshot(&mut self, duration: Duration) -> Result<(), TimerError>;
64}
65
66/// Errors that can occur during timer operations.
67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub enum TimerError {
69 /// Timer is not initialized
70 NotInitialized,
71 /// Invalid configuration parameters
72 InvalidConfig,
73 /// Hardware timer is not available
74 NotAvailable,
75 /// Timer is already running
76 AlreadyRunning,
77 /// Timer is not running
78 NotRunning,
79 /// Frequency is out of supported range
80 UnsupportedFrequency,
81}
82
83/// Preemption guard for disabling preemption without disabling interrupts.
84///
85/// This allows critical sections that need to prevent preemption but still
86/// allow interrupt handling (e.g., for device drivers).
87pub struct PreemptGuard {
88 /// Previous preemption state
89 was_enabled: bool,
90}
91
92impl PreemptGuard {
93 /// Enter a preemption-disabled critical section.
94 ///
95 /// # Returns
96 ///
97 /// A guard that will re-enable preemption when dropped.
98 pub fn enter() -> Self {
99 let was_enabled = disable_preemption();
100 Self { was_enabled }
101 }
102
103 /// Check if preemption is currently disabled.
104 pub fn is_disabled() -> bool {
105 !is_preemption_enabled()
106 }
107}
108
109impl Drop for PreemptGuard {
110 fn drop(&mut self) {
111 if self.was_enabled {
112 enable_preemption();
113 }
114 }
115}
116
117/// Interrupt guard for disabling all interrupts.
118///
119/// This provides a critical section where no interrupts can occur,
120/// used for the most critical kernel operations.
121pub struct IrqGuard {
122 /// Previous interrupt state
123 was_enabled: bool,
124}
125
126impl IrqGuard {
127 /// Enter an interrupt-disabled critical section.
128 ///
129 /// # Returns
130 ///
131 /// A guard that will restore interrupt state when dropped.
132 pub fn enter() -> Self {
133 let was_enabled = crate::arch::DefaultArch::interrupts_enabled();
134 crate::arch::DefaultArch::disable_interrupts();
135 Self { was_enabled }
136 }
137}
138
139impl Drop for IrqGuard {
140 fn drop(&mut self) {
141 if self.was_enabled {
142 crate::arch::DefaultArch::enable_interrupts();
143 }
144 }
145}
146
147/// Per-CPU preemption state.
148///
149/// This tracks whether preemption is enabled for the current CPU.
150/// We use thread-local storage or per-CPU data structures for this.
151static mut PREEMPTION_ENABLED: bool = true;
152
153/// Disable preemption on the current CPU.
154///
155/// # Returns
156///
157/// Previous preemption state.
158fn disable_preemption() -> bool {
159 // TODO: This should be per-CPU and atomic
160 // For now, use a simple global flag
161 unsafe {
162 let was_enabled = PREEMPTION_ENABLED;
163 PREEMPTION_ENABLED = false;
164 was_enabled
165 }
166}
167
168/// Enable preemption on the current CPU.
169fn enable_preemption() {
170 unsafe {
171 PREEMPTION_ENABLED = true;
172 }
173}
174
175/// Check if preemption is enabled on the current CPU.
176fn is_preemption_enabled() -> bool {
177 unsafe { PREEMPTION_ENABLED }
178}
179
180/// Handle a timer interrupt for preemptive scheduling.
181///
182/// This function should be called from the architecture-specific
183/// timer interrupt handler. It updates tick counters and triggers
184/// scheduling decisions.
185///
186/// # Safety
187///
188/// Must be called from an interrupt context with a valid interrupt frame.
189/// The caller must ensure that the interrupt frame is properly saved
190/// and that this function doesn't corrupt the interrupted context.
191pub unsafe fn handle_timer_interrupt() {
192 // Increment global tick counter
193 super::tick::GLOBAL_TICK_COUNTER.increment();
194
195 // Only preempt if preemption is enabled
196 if !is_preemption_enabled() {
197 return;
198 }
199
200 // TODO: Get current kernel handle and trigger scheduling
201 // This would call kernel.handle_timer_interrupt()
202
203 // For now, just a placeholder
204 schedule_if_needed();
205}
206
207/// Check if scheduling is needed and trigger it.
208///
209/// This examines the current thread's time slice and the ready queue
210/// to determine if a context switch should occur.
211fn schedule_if_needed() {
212 // TODO: Implement scheduling logic
213 // 1. Get current thread
214 // 2. Update its time slice
215 // 3. Check if quantum expired or higher priority thread available
216 // 4. Trigger context switch if needed
217}
218
219#[cfg(test)]
220mod tests {
221 use super::*;
222
223 #[test]
224 fn test_timer_config() {
225 let config = TimerConfig::default();
226 assert_eq!(config.frequency, super::super::TIMER_FREQUENCY_HZ);
227 assert_eq!(config.vector, 0xEF);
228 assert!(config.high_precision);
229 }
230
231 #[test]
232 fn test_preempt_guard() {
233 // Initially preemption should be enabled
234 assert!(!PreemptGuard::is_disabled());
235
236 {
237 let _guard = PreemptGuard::enter();
238 assert!(PreemptGuard::is_disabled());
239 } // Guard dropped here
240
241 // Should be re-enabled after guard drop
242 assert!(!PreemptGuard::is_disabled());
243 }
244
245 #[test]
246 fn test_timer_error_types() {
247 let error = TimerError::NotInitialized;
248 assert_eq!(error, TimerError::NotInitialized);
249
250 let error2 = TimerError::InvalidConfig;
251 assert_ne!(error, error2);
252 }
253}