preemptive_threads/arch/
mod.rs

1//! Architecture abstraction layer for context switching and interrupt handling.
2//!
3//! This module provides a unified interface for architecture-specific operations
4//! that need to be implemented for each supported CPU architecture.
5
6// PhantomData import not needed yet
7// use core::marker::PhantomData;
8
9/// Architecture abstraction trait.
10///
11/// This trait must be implemented for each supported CPU architecture to provide
12/// context switching, interrupt handling, and FPU management capabilities.
13///
14/// # Safety
15///
16/// Implementations of this trait involve direct hardware manipulation and
17/// inline assembly. All methods marked as unsafe have specific preconditions
18/// that must be upheld by the caller.
19pub trait Arch {
20    /// Architecture-specific saved context type.
21    ///
22    /// This type must contain all CPU registers and state needed to fully
23    /// restore a thread's execution context.
24    type SavedContext: Send + Sync;
25
26    /// Switch from one thread context to another.
27    ///
28    /// # Safety
29    ///
30    /// - `prev` must point to a valid, properly aligned SavedContext
31    /// - `next` must point to a valid, properly aligned SavedContext  
32    /// - The caller must ensure the memory pointed to by both pointers remains
33    ///   valid for the duration of this call
34    /// - Must be called with interrupts disabled
35    /// - The `next` context must represent a valid execution state
36    unsafe fn context_switch(prev: *mut Self::SavedContext, next: *const Self::SavedContext);
37
38    /// Save floating point unit state to the given context.
39    ///
40    /// # Safety
41    ///
42    /// - `ctx` must point to a valid, properly aligned SavedContext
43    /// - Must be called when the current thread owns the FPU
44    /// - The context must have sufficient space for FPU state
45    #[cfg(feature = "full-fpu")]
46    unsafe fn save_fpu(ctx: &mut Self::SavedContext);
47
48    /// Restore floating point unit state from the given context.
49    ///
50    /// # Safety
51    ///
52    /// - `ctx` must contain valid FPU state
53    /// - Must be called before the thread uses FPU instructions
54    /// - The current thread must be the owner of the FPU
55    #[cfg(feature = "full-fpu")]
56    unsafe fn restore_fpu(ctx: &Self::SavedContext);
57
58    /// Enable interrupts on the current CPU.
59    ///
60    /// This function re-enables interrupt delivery, allowing preemption
61    /// and timer interrupts to occur.
62    fn enable_interrupts();
63
64    /// Disable interrupts on the current CPU.
65    ///
66    /// This function prevents interrupt delivery, creating a critical section
67    /// where the current thread cannot be preempted.
68    fn disable_interrupts();
69
70    /// Check if interrupts are currently enabled.
71    ///
72    /// Returns `true` if interrupts are enabled, `false` otherwise.
73    fn interrupts_enabled() -> bool;
74}
75
76/// A no-op architecture implementation for testing and fallback purposes.
77///
78/// This implementation provides stub functionality and should not be used
79/// in production code where real context switching is required.
80pub struct NoOpArch;
81
82impl Arch for NoOpArch {
83    type SavedContext = ();
84
85    unsafe fn context_switch(_prev: *mut Self::SavedContext, _next: *const Self::SavedContext) {
86        // No-op for testing
87    }
88
89    #[cfg(feature = "full-fpu")]
90    unsafe fn save_fpu(_ctx: &mut Self::SavedContext) {
91        // No-op for testing  
92    }
93
94    #[cfg(feature = "full-fpu")]
95    unsafe fn restore_fpu(_ctx: &Self::SavedContext) {
96        // No-op for testing
97    }
98
99    fn enable_interrupts() {
100        // No-op for testing
101    }
102
103    fn disable_interrupts() {
104        // No-op for testing
105    }
106
107    fn interrupts_enabled() -> bool {
108        true
109    }
110}
111
112// Include architecture-specific implementations
113#[cfg(feature = "x86_64")]
114pub mod x86_64;
115
116#[cfg(feature = "arm64")]
117pub mod aarch64;
118
119#[cfg(feature = "riscv64")]
120pub mod riscv;
121
122pub mod barriers;
123pub mod detection;
124
125// Re-export the default architecture for the current target
126#[cfg(all(target_arch = "x86_64", feature = "x86_64"))]
127pub use x86_64::X86_64Arch as DefaultArch;
128
129#[cfg(all(target_arch = "aarch64", feature = "arm64"))]
130pub use aarch64::Aarch64Arch as DefaultArch;
131
132#[cfg(all(any(target_arch = "riscv64"), feature = "riscv64"))]
133pub use riscv::RiscvArch as DefaultArch;
134
135#[cfg(all(feature = "std-shim", not(any(feature = "x86_64", feature = "arm64", feature = "riscv64"))))]
136pub use NoOpArch as DefaultArch;
137
138// Fallback for when no specific architecture is enabled
139#[cfg(not(any(
140    all(target_arch = "x86_64", feature = "x86_64"),
141    all(target_arch = "aarch64", feature = "arm64"), 
142    all(any(target_arch = "riscv64"), feature = "riscv64"),
143    all(feature = "std-shim", not(any(feature = "x86_64", feature = "arm64", feature = "riscv64")))
144)))]
145pub use NoOpArch as DefaultArch;