mikros: Add thread sleeping, condvar timeouts, and parking
This commit is contained in:
parent
f4ab2ecd1b
commit
c42cf578ca
@ -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
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
24
library/std/src/sys/sync/thread_parking/mikros.rs
Normal file
24
library/std/src/sys/sync/thread_parking/mikros.rs
Normal 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() }
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user