From 68a58e1dae9b893e740d9406ce9b0c7bf8824b4f Mon Sep 17 00:00:00 2001 From: pjht Date: Thu, 28 Nov 2024 13:41:12 -0600 Subject: [PATCH] mikros: Implement synchronization primitives --- library/std/src/sys/pal/mikros/syscalls.rs | 20 ++++++++ library/std/src/sys/sync/condvar/mikros.rs | 53 ++++++++++++++++++++++ library/std/src/sys/sync/condvar/mod.rs | 3 ++ library/std/src/sys/sync/mutex/mikros.rs | 44 ++++++++++++++++++ library/std/src/sys/sync/mutex/mod.rs | 3 ++ library/std/src/sys/sync/once/mod.rs | 1 + library/std/src/sys/sync/rwlock/mod.rs | 1 + 7 files changed, 125 insertions(+) create mode 100644 library/std/src/sys/sync/condvar/mikros.rs create mode 100644 library/std/src/sys/sync/mutex/mikros.rs diff --git a/library/std/src/sys/pal/mikros/syscalls.rs b/library/std/src/sys/pal/mikros/syscalls.rs index 944c0c63561..0e611120e21 100644 --- a/library/std/src/sys/pal/mikros/syscalls.rs +++ b/library/std/src/sys/pal/mikros/syscalls.rs @@ -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); +} diff --git a/library/std/src/sys/sync/condvar/mikros.rs b/library/std/src/sys/sync/condvar/mikros.rs new file mode 100644 index 00000000000..3050cc1555f --- /dev/null +++ b/library/std/src/sys/sync/condvar/mikros.rs @@ -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>>, +} + +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 + } +} diff --git a/library/std/src/sys/sync/condvar/mod.rs b/library/std/src/sys/sync/condvar/mod.rs index d0c998a5597..fa9de4cdd35 100644 --- a/library/std/src/sys/sync/condvar/mod.rs +++ b/library/std/src/sys/sync/condvar/mod.rs @@ -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; diff --git a/library/std/src/sys/sync/mutex/mikros.rs b/library/std/src/sys/sync/mutex/mikros.rs new file mode 100644 index 00000000000..67cf5de4a26 --- /dev/null +++ b/library/std/src/sys/sync/mutex/mikros.rs @@ -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, +} + +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); + } + } +} diff --git a/library/std/src/sys/sync/mutex/mod.rs b/library/std/src/sys/sync/mutex/mod.rs index 360df3fc4b5..88eb2a28fc3 100644 --- a/library/std/src/sys/sync/mutex/mod.rs +++ b/library/std/src/sys/sync/mutex/mod.rs @@ -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; diff --git a/library/std/src/sys/sync/once/mod.rs b/library/std/src/sys/sync/once/mod.rs index 0e38937b121..997f93444b2 100644 --- a/library/std/src/sys/sync/once/mod.rs +++ b/library/std/src/sys/sync/once/mod.rs @@ -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}; diff --git a/library/std/src/sys/sync/rwlock/mod.rs b/library/std/src/sys/sync/rwlock/mod.rs index 70ba6bf38ef..22da152f5f1 100644 --- a/library/std/src/sys/sync/rwlock/mod.rs +++ b/library/std/src/sys/sync/rwlock/mod.rs @@ -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;