rt/rust/src/task.rs

122 lines
3.5 KiB
Rust

use core::{
cell::UnsafeCell,
ffi::{c_void, CStr},
marker::PhantomPinned,
mem::{size_of, transmute},
panic::{RefUnwindSafe, UnwindSafe},
ptr::null_mut,
str,
};
use crate::{
bindings::{
rt_context_init, rt_syscall, rt_syscall_args, rt_syscall_pend, rt_syscall_push,
rt_syscall_record, rt_task, rt_task_drop_privilege, rt_task_enable_fp, rt_task_exit,
rt_task_name, rt_task_sleep, rt_task_sleep_periodic, rt_task_state, rt_task_yield,
RT_STACK_MIN,
},
list::list_init,
tick::Utick,
};
pub const STACK_MIN: usize = RT_STACK_MIN as usize;
pub struct Task {
t: UnsafeCell<rt_task>,
_pin_marker: PhantomPinned,
}
unsafe impl Send for Task {}
unsafe impl Sync for Task {}
impl UnwindSafe for Task {}
impl RefUnwindSafe for Task {}
pub fn yield_() {
unsafe { rt_task_yield() }
}
pub fn sleep(ticks: Utick) {
unsafe { rt_task_sleep(ticks) }
}
pub fn sleep_periodic(last_wake_tick: &mut Utick, period: Utick) {
unsafe { rt_task_sleep_periodic(last_wake_tick, period) }
}
pub fn exit() -> ! {
unsafe { rt_task_exit() }
}
pub fn name() -> &'static str {
unsafe { str::from_utf8_unchecked(CStr::from_ptr(rt_task_name()).to_bytes()) }
}
pub fn enable_fp() {
unsafe { rt_task_enable_fp() }
}
pub fn drop_privilege() {
unsafe { rt_task_drop_privilege() }
}
impl Task {
pub const fn init(task: &'static Task, name: &'static CStr, priority: u32) -> Task {
let t = unsafe { &*(task.t.get() as *const rt_task) };
Task {
t: UnsafeCell::new(rt_task {
list: list_init(&t.list),
sleep_list: list_init(&t.sleep_list),
ctx: null_mut(),
list_head: null_mut(),
record: rt_syscall_record {
next: null_mut(),
args: unsafe { transmute([0u8; size_of::<rt_syscall_args>()]) },
syscall: rt_syscall::RT_SYSCALL_TASK_READY,
},
priority,
base_priority: priority,
state: rt_task_state::RT_TASK_STATE_EXITED,
wake_tick: 0,
mutex_list: list_init(&t.mutex_list),
name: name.as_ptr(),
}),
_pin_marker: PhantomPinned,
}
}
pub fn start(&mut self, f: extern "C" fn(), stack: &mut [u8]) {
let t = self.t.get_mut();
unsafe {
t.ctx = rt_context_init(Some(f), stack.as_mut_ptr() as *mut c_void, stack.len());
rt_syscall_push(&mut t.record);
rt_syscall_pend();
}
}
}
#[macro_export]
macro_rules! task {
($fn: ident $params: tt, $stack_size: expr, $priority: expr) => {
$crate::paste::paste! {
{
static mut [< $fn:upper _TASK >]: rt::task::Task = rt::task::Task::init(
unsafe { &[< $fn:upper _TASK >] },
unsafe { core::ffi::CStr::from_bytes_with_nul_unchecked(core::concat!(core::stringify!($fn), "\0").as_bytes()) },
$priority,
);
static mut [< $fn:upper _TASK_STACK >]: [u8; $stack_size] = [0u8; $stack_size];
extern "C" fn [< $fn _c >]() {
$fn $params
}
unsafe {
[< $fn:upper _TASK >].start([< $fn _c >], [< $fn:upper _TASK_STACK >].as_mut_slice());
}
}
}
};
($fn: ident, $stack_size: expr, $priority: expr) => {
rt::task!($fn(), $stack_size, $priority);
};
}