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;