From c42cf578ca34c94ec8c5f03d7c2b1794e98df00e Mon Sep 17 00:00:00 2001 From: pjht Date: Thu, 28 Nov 2024 21:00:05 -0600 Subject: [PATCH] mikros: Add thread sleeping, condvar timeouts, and parking --- library/std/src/sys/pal/mikros/syscalls.rs | 8 ++++ library/std/src/sys/pal/mikros/thread.rs | 7 +-- library/std/src/sys/pal/mikros/time.rs | 2 +- library/std/src/sys/sync/condvar/mikros.rs | 47 +++++++++++++++---- library/std/src/sys/sync/mutex/mikros.rs | 20 +++++++- .../std/src/sys/sync/thread_parking/mikros.rs | 24 ++++++++++ .../std/src/sys/sync/thread_parking/mod.rs | 3 ++ 7 files changed, 96 insertions(+), 15 deletions(-) create mode 100644 library/std/src/sys/sync/thread_parking/mikros.rs diff --git a/library/std/src/sys/pal/mikros/syscalls.rs b/library/std/src/sys/pal/mikros/syscalls.rs index 978b210dae2..e4741ec125c 100644 --- a/library/std/src/sys/pal/mikros/syscalls.rs +++ b/library/std/src/sys/pal/mikros/syscalls.rs @@ -250,3 +250,11 @@ pub fn tick_freq() -> u64 { pub fn num_ticks() -> u64 { syscall0(38) } + +pub fn sleep(dur: u64) { + syscall1(39, dur); +} + +pub fn lock_mutex_timeout(mutex: u64, dur: u64) -> bool { + syscall2(40, mutex, dur) != 0 +} diff --git a/library/std/src/sys/pal/mikros/thread.rs b/library/std/src/sys/pal/mikros/thread.rs index 627474033f1..098d63e94ce 100644 --- a/library/std/src/sys/pal/mikros/thread.rs +++ b/library/std/src/sys/pal/mikros/thread.rs @@ -1,4 +1,4 @@ -use super::syscalls::{exit_thread, join_thread, new_thread}; +use super::syscalls::{self, exit_thread, join_thread, new_thread, tick_freq}; use super::unsupported; use crate::ffi::CStr; use crate::io; @@ -31,8 +31,9 @@ impl Thread { // nope } - pub fn sleep(_dur: Duration) { - panic!("can't sleep"); + pub fn sleep(dur: Duration) { + let dur = (dur * (tick_freq() as u32)).as_secs(); + syscalls::sleep(dur) } pub fn join(self) { diff --git a/library/std/src/sys/pal/mikros/time.rs b/library/std/src/sys/pal/mikros/time.rs index 2ccab5ffe71..9d985cc85e4 100644 --- a/library/std/src/sys/pal/mikros/time.rs +++ b/library/std/src/sys/pal/mikros/time.rs @@ -1,5 +1,5 @@ +use super::syscalls::{num_ticks, tick_freq}; use crate::time::Duration; -use super::syscalls::{tick_freq, num_ticks}; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Instant(Duration); diff --git a/library/std/src/sys/sync/condvar/mikros.rs b/library/std/src/sys/sync/condvar/mikros.rs index 3050cc1555f..82d9970d71d 100644 --- a/library/std/src/sys/sync/condvar/mikros.rs +++ b/library/std/src/sys/sync/condvar/mikros.rs @@ -1,6 +1,6 @@ +use crate::sync::{Arc, Mutex}; use crate::sys::sync::Mutex as RawMutex; use crate::time::Duration; -use crate::sync::{Arc, Mutex}; pub struct Condvar { wait_mutexes: Mutex>>, @@ -10,9 +10,7 @@ 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()) - } + Condvar { wait_mutexes: Mutex::new(Vec::new()) } } #[inline] @@ -32,7 +30,9 @@ impl Condvar { } pub unsafe fn wait(&self, mutex: &RawMutex) { - unsafe { mutex.unlock(); } + unsafe { + mutex.unlock(); + } let wait_mutex = Arc::new(RawMutex::new()); wait_mutex.lock(); @@ -40,14 +40,41 @@ impl Condvar { self.wait_mutexes.lock().unwrap().push(wait_mutex.clone()); wait_mutex.lock(); - wait_mutex.unlock(); + unsafe { + 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 + pub unsafe fn wait_timeout(&self, mutex: &RawMutex, dur: Duration) -> bool { + unsafe { + mutex.unlock(); + } + + let wait_mutex = Arc::new(RawMutex::new()); + wait_mutex.lock(); + + self.wait_mutexes.lock().unwrap().push(wait_mutex.clone()); + + let notified = wait_mutex.lock_timeout(dur); + + if notified { + unsafe { + wait_mutex.unlock(); + }; + } else { + self.wait_mutexes.lock().unwrap().retain(|e| *e != wait_mutex); + if wait_mutex.try_lock() { + unsafe { + wait_mutex.unlock(); + }; + self.notify_one(); + } + } + + mutex.lock(); + + notified } } diff --git a/library/std/src/sys/sync/mutex/mikros.rs b/library/std/src/sys/sync/mutex/mikros.rs index 67cf5de4a26..16d7c9f0d60 100644 --- a/library/std/src/sys/sync/mutex/mikros.rs +++ b/library/std/src/sys/sync/mutex/mikros.rs @@ -1,5 +1,8 @@ use crate::sync::OnceLock; -use crate::sys::syscalls::{new_mutex, lock_mutex, try_lock_mutex, unlock_mutex, drop_mutex}; +use crate::sys::syscalls::{ + drop_mutex, lock_mutex, lock_mutex_timeout, new_mutex, tick_freq, try_lock_mutex, unlock_mutex, +}; +use crate::time::Duration; pub struct Mutex { mutex: OnceLock, @@ -33,6 +36,11 @@ impl Mutex { fn get_mutex_id(&self) -> u64 { *self.mutex.get_or_init(|| new_mutex()) } + + pub fn lock_timeout(&self, dur: Duration) -> bool { + let dur = (dur * (tick_freq() as u32)).as_secs(); + lock_mutex_timeout(self.get_mutex_id(), dur) + } } impl Drop for Mutex { @@ -42,3 +50,13 @@ impl Drop for Mutex { } } } + +impl PartialEq for Mutex { + fn eq(&self, other: &Self) -> bool { + if let Some(&id) = self.mutex.get() { + if let Some(&other_id) = other.mutex.get() { id == other_id } else { false } + } else { + false + } + } +} diff --git a/library/std/src/sys/sync/thread_parking/mikros.rs b/library/std/src/sys/sync/thread_parking/mikros.rs new file mode 100644 index 00000000000..56001b38c2c --- /dev/null +++ b/library/std/src/sys/sync/thread_parking/mikros.rs @@ -0,0 +1,24 @@ +use crate::pin::Pin; +use crate::sys::sync::Mutex; +use crate::time::Duration; + +pub struct Parker { + mutex: Mutex, +} + +impl Parker { + pub unsafe fn new_in_place(parker: *mut Parker) { + let mutex = Mutex::new(); + mutex.lock(); + unsafe { parker.write(Parker { mutex }) } + } + pub unsafe fn park(self: Pin<&Self>) { + self.get_ref().mutex.lock() + } + pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) { + self.get_ref().mutex.lock_timeout(dur); + } + pub fn unpark(self: Pin<&Self>) { + unsafe { self.get_ref().mutex.unlock() } + } +} diff --git a/library/std/src/sys/sync/thread_parking/mod.rs b/library/std/src/sys/sync/thread_parking/mod.rs index f4d8fa0a58c..cb19d8725a6 100644 --- a/library/std/src/sys/sync/thread_parking/mod.rs +++ b/library/std/src/sys/sync/thread_parking/mod.rs @@ -32,6 +32,9 @@ cfg_if::cfg_if! { } else if #[cfg(target_family = "unix")] { mod pthread; pub use pthread::Parker; + } else if #[cfg(target_os = "mikros")] { + mod mikros; + pub use mikros::Parker; } else { mod unsupported; pub use unsupported::Parker;