• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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