#[repr(C)]
#[derive(Clone,Copy)]
pub struct ThreadContext {
entry_point: fn()->u8,
}
pub type ThreadId = u8;
pub(crate) mod internal {
use crate::deviceconsts::oxide::MAX_THREADS;
use crate::hal::concurrency::{ThreadContext, interrupt};
pub(super) struct SchedulerState<const MT: usize> {
pub(super) threads: [Option<ThreadContext>; MT],
pub(super) current_thread: Option<u8>,
pub(super) run_q: Option<u8>
}
pub(super) static mut SCHEDULER: Option<SchedulerState<MAX_THREADS>> = None;
pub(crate) fn initialise() {
unsafe {
core::ptr::replace(&mut SCHEDULER,
Some(SchedulerState {
threads: [None; MAX_THREADS],
current_thread: None,
run_q: None
}));
}
}
pub(crate) unsafe fn run_scheduler() -> ! {
loop {
interrupt::disable_interrupts();
if let Some(scheduler) = &mut SCHEDULER {
if let Some(thread_id) = scheduler.run_q {
scheduler.run_q = None;
scheduler.current_thread = Some(thread_id);
if let Some(thread_context) = &mut scheduler.threads[thread_id as usize] {
interrupt::enable_interrupts();
(thread_context.entry_point)();
} else {
panic!();
}
} else {
interrupt::enable_interrupts();
interrupt::wait();
}
} else {
panic!()
}
}
}
}
pub mod thread {
use crate::hal::concurrency::{ThreadContext, interrupt, ThreadId};
use crate::deviceconsts::oxide::MAX_THREADS;
use crate::hal::concurrency::internal::SCHEDULER;
pub struct JoinHandle {
thread: Thread
}
#[repr(C)]
#[derive(Clone,Copy)]
pub struct Thread {
thread_id: u8
}
pub fn spawn(f: fn() -> u8) -> JoinHandle {
interrupt::isolated(||{unsafe{spawn_threadunsafe(f)}})
}
pub(crate) unsafe fn spawn_threadunsafe(f: fn() -> u8) -> JoinHandle
{
if let Some(scheduler) = &mut SCHEDULER {
for i in 0..MAX_THREADS {
match scheduler.threads[i] {
None => {
let thread = ThreadContext {
entry_point: f
};
scheduler.threads[i] = Some(thread);
scheduler.run_q = Some(i as ThreadId);
return JoinHandle {
thread: Thread {
thread_id: i as u8
}
};
},
Some(_) => {}
}
}
panic!()
} else {
panic!()
}
}
impl JoinHandle {
pub fn join(self) -> u8 {
unimplemented!()
}
pub fn thread(&self) -> &Thread {
&self.thread
}
}
impl Thread {
pub fn id(&self) -> ThreadId {
self.thread_id
}
}
}
pub mod interrupt {
use crate::hal::generic::cpu::Cpu;
pub fn isolated<F,R>(f: F) -> R
where
F: FnOnce() -> R
{
unsafe {
#[cfg(target_arch="avr")]
let sreg = crate::cpu!().read_sreg();
disable_interrupts();
let result = f();
#[cfg(target_arch="avr")]
crate::cpu!().write_sreg(sreg);
result
}
}
#[inline(always)]
pub(crate) fn isr<F,R>(f: F) -> R
where
F: FnOnce() -> R
{
crate::hal::atmega4809::debugled::PinE2DebugLed::on();
let result = f();
crate::hal::atmega4809::debugled::PinE2DebugLed::off();
result
}
#[cfg(not(target_arch="avr"))]
pub(crate) unsafe fn enable_interrupts() {
}
#[cfg(not(target_arch="avr"))]
pub(crate) unsafe fn disable_interrupts() {
}
use crate::hal::generic::debugled::DebugLed;
#[cfg(target_arch="avr")]
#[inline(always)]
pub(crate) unsafe fn enable_interrupts(){
#![allow(deprecated)] llvm_asm!("sei" :::: "volatile")
}
#[cfg(target_arch="avr")]
#[inline(always)]
pub(crate) unsafe fn disable_interrupts() {
#![allow(deprecated)] llvm_asm!("cli" :::: "volatile")
}
#[cfg(not(target_arch="avr"))]
pub fn wait() {
std::thread::sleep(std::time::Duration::from_millis(100));
}
#[cfg(target_arch="avr")]
#[inline(always)]
pub fn wait() {
unsafe {
#![allow(deprecated)] llvm_asm!("sleep");
}
}
}