1 // Copyright 2025 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 15 #[cfg(feature = "arch_arm_cortex_m")] 16 mod arm_cortex_m; 17 #[cfg(feature = "arch_arm_cortex_m")] 18 pub use arm_cortex_m::Arch; 19 20 #[cfg(feature = "arch_host")] 21 mod host; 22 #[cfg(feature = "arch_host")] 23 pub use host::Arch; 24 25 use crate::scheduler::{SchedulerState, Stack}; 26 use crate::sync::spinlock::SpinLockGuard; 27 28 pub type ArchThreadState = <Arch as ArchInterface>::ThreadState; 29 30 pub trait ThreadState { 31 #[allow(dead_code)] new() -> Self32 fn new() -> Self; 33 34 // Switch to this thread. 35 // sched_state: a locked spinlockguard for the main SCHEDULER_STATE struct. 36 // Will potentially be dropped and reacquired across this function, and 37 // a copy will be returned (either still held, or newly reacquired). 38 // old_thread_state: thread we're moving from. 39 // new_thread_state: must match current_thread and the container for this ThreadState. context_switch( sched_state: SpinLockGuard<'_, SchedulerState>, old_thread_state: *mut ArchThreadState, new_thread_state: *mut ArchThreadState, ) -> SpinLockGuard<'_, SchedulerState>40 unsafe fn context_switch( 41 sched_state: SpinLockGuard<'_, SchedulerState>, 42 old_thread_state: *mut ArchThreadState, 43 new_thread_state: *mut ArchThreadState, 44 ) -> SpinLockGuard<'_, SchedulerState>; 45 46 // Initialize the default frame of the thread which arranges for it to start at the initial_function 47 // with one argument passed in the first argument slot. 48 #[allow(dead_code)] initialize_frame(&mut self, stack: Stack, initial_function: fn(usize), arg0: usize)49 fn initialize_frame(&mut self, stack: Stack, initial_function: fn(usize), arg0: usize); 50 } 51 52 pub trait BareSpinLock { 53 type Guard<'a> 54 where 55 Self: 'a; 56 57 // Rust does not support const function in traits. However it should be 58 // considered that the BareSpinlockApi includes: 59 // 60 // `const fn new() -> Self` 61 try_lock(&self) -> Option<Self::Guard<'_>>62 fn try_lock(&self) -> Option<Self::Guard<'_>>; 63 64 #[inline(always)] lock(&self) -> Self::Guard<'_>65 fn lock(&self) -> Self::Guard<'_> { 66 loop { 67 if let Some(sentinel) = self.try_lock() { 68 return sentinel; 69 } 70 } 71 } 72 73 // TODO - konkers: Add optimized path for functions that know they are in 74 // atomic context (i.e. interrupt handlers). 75 } 76 77 pub trait ArchInterface { 78 type ThreadState: ThreadState; 79 type BareSpinLock: BareSpinLock; 80 early_init()81 fn early_init() {} init()82 fn init() {} 83 panic() -> !84 fn panic() -> ! { 85 #[allow(clippy::empty_loop)] 86 loop {} 87 } 88 // fill in more arch implementation functions from the kernel here: 89 // arch-specific backtracing 90 #[allow(dead_code)] enable_interrupts()91 fn enable_interrupts(); 92 #[allow(dead_code)] disable_interrupts()93 fn disable_interrupts(); 94 #[allow(dead_code)] interrupts_enabled() -> bool95 fn interrupts_enabled() -> bool; 96 97 #[allow(dead_code)] idle()98 fn idle() {} 99 } 100