mikros: Add thread sleeping, condvar timeouts, and parking

This commit is contained in:
pjht 2024-11-28 21:00:05 -06:00
parent f4ab2ecd1b
commit c42cf578ca
Signed by: pjht
GPG Key ID: 7B5F6AFBEC7EE78E
7 changed files with 96 additions and 15 deletions

View File

@ -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
}

View File

@ -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) {

View File

@ -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);

View File

@ -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<Vec<Arc<RawMutex>>>,
@ -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
}
}

View File

@ -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<u64>,
@ -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
}
}
}

View File

@ -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() }
}
}

View File

@ -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;