mikros: Implement synchronization primitives

This commit is contained in:
pjht 2024-11-28 13:41:12 -06:00
parent 9a9205b8c1
commit 68a58e1dae
Signed by: pjht
GPG Key ID: CA239FC6934E6F3A
7 changed files with 125 additions and 0 deletions

View File

@ -222,3 +222,23 @@ pub fn set_tls_key(key: u64, val: u64) {
pub fn get_tls_key(key: u64) -> u64 {
syscall1(31, key)
}
pub fn new_mutex() -> u64 {
syscall0(32)
}
pub fn lock_mutex(mutex: u64) {
syscall1(33, mutex);
}
pub fn try_lock_mutex(mutex: u64) -> bool {
syscall1(34, mutex) != 0
}
pub fn unlock_mutex(mutex: u64) {
syscall1(35, mutex);
}
pub fn drop_mutex(mutex: u64) {
syscall1(36, mutex);
}

View File

@ -0,0 +1,53 @@
use crate::sys::sync::Mutex as RawMutex;
use crate::time::Duration;
use crate::sync::{Arc, Mutex};
pub struct Condvar {
wait_mutexes: Mutex<Vec<Arc<RawMutex>>>,
}
impl Condvar {
#[inline]
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_locks", since = "1.63.0"))]
pub const fn new() -> Condvar {
Condvar {
wait_mutexes: Mutex::new(Vec::new())
}
}
#[inline]
pub fn notify_one(&self) {
let Some(wait_mutex) = self.wait_mutexes.lock().unwrap().pop() else {
return;
};
unsafe { wait_mutex.unlock() };
}
#[inline]
pub fn notify_all(&self) {
let mut wait_mutexes = self.wait_mutexes.lock().unwrap();
for wait_mutex in wait_mutexes.drain(..) {
unsafe { wait_mutex.unlock() };
}
}
pub unsafe fn wait(&self, mutex: &RawMutex) {
unsafe { mutex.unlock(); }
let wait_mutex = Arc::new(RawMutex::new());
wait_mutex.lock();
self.wait_mutexes.lock().unwrap().push(wait_mutex.clone());
wait_mutex.lock();
wait_mutex.unlock();
mutex.lock();
}
pub unsafe fn wait_timeout(&self, mutex: &RawMutex, _dur: Duration) -> bool {
//panic!("condvar wait_timeout not supported");
unsafe { self.wait(mutex) };
true
}
}

View File

@ -30,6 +30,9 @@ cfg_if::cfg_if! {
} else if #[cfg(target_os = "xous")] {
mod xous;
pub use xous::Condvar;
} else if #[cfg(target_os = "mikros")] {
mod mikros;
pub use mikros::Condvar;
} else {
mod no_threads;
pub use no_threads::Condvar;

View File

@ -0,0 +1,44 @@
use crate::sync::OnceLock;
use crate::sys::syscalls::{new_mutex, lock_mutex, try_lock_mutex, unlock_mutex, drop_mutex};
pub struct Mutex {
mutex: OnceLock<u64>,
}
unsafe impl Send for Mutex {}
unsafe impl Sync for Mutex {} // no threads on this platform
impl Mutex {
#[inline]
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_locks", since = "1.63.0"))]
pub const fn new() -> Mutex {
Mutex { mutex: OnceLock::new() }
}
#[inline]
pub fn lock(&self) {
lock_mutex(self.get_mutex_id())
}
#[inline]
pub unsafe fn unlock(&self) {
unlock_mutex(self.get_mutex_id())
}
#[inline]
pub fn try_lock(&self) -> bool {
try_lock_mutex(self.get_mutex_id())
}
fn get_mutex_id(&self) -> u64 {
*self.mutex.get_or_init(|| new_mutex())
}
}
impl Drop for Mutex {
fn drop(&mut self) {
if let Some(&id) = self.mutex.get() {
drop_mutex(id);
}
}
}

View File

@ -32,6 +32,9 @@ cfg_if::cfg_if! {
} else if #[cfg(target_os = "xous")] {
mod xous;
pub use xous::Mutex;
} else if #[cfg(target_os = "mikros")] {
mod mikros;
pub use mikros::Mutex;
} else {
mod no_threads;
pub use no_threads::Mutex;

View File

@ -27,6 +27,7 @@ cfg_if::cfg_if! {
all(target_vendor = "fortanix", target_env = "sgx"),
target_os = "solid_asp3",
target_os = "xous",
target_os = "mikros",
))] {
mod queue;
pub use queue::{Once, OnceState};

View File

@ -17,6 +17,7 @@ cfg_if::cfg_if! {
all(target_os = "windows", target_vendor = "win7"),
all(target_vendor = "fortanix", target_env = "sgx"),
target_os = "xous",
target_os = "mikros",
))] {
mod queue;
pub use queue::RwLock;