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}