mutex refinements

This commit is contained in:
Ulrich Mohr 2024-02-06 14:44:09 +01:00
parent 6beb438508
commit 7ba3f23add
2 changed files with 52 additions and 25 deletions

View File

@ -52,9 +52,9 @@ impl<T: Clone + Default> OwnedDataset<T> {
} }
} }
pub fn new_default(default_values: T) -> OwnedDataset<T> { pub fn new_init_values(init_values: T) -> OwnedDataset<T> {
OwnedDataset::<T> { OwnedDataset::<T> {
actual_data: default_values, actual_data: init_values,
mutex: mutex::RawMutex::new(), mutex: mutex::RawMutex::new(),
} }
} }

View File

@ -1,11 +1,13 @@
use crate::check_global_threading_available;
use super::osal; use super::osal;
// for now, this is an implementation based on FreeRTOS, where we can preallocate mutexes // TODO we do not discern between a mutex (holding the descriptor) and a clone (pointing to the
// this allows us to assume that mutexes are valid starting from their creation until end of runtime // original descriptor), waisting some memory
// and so we do not use the global_threading lock
pub struct RawMutex { pub struct RawMutex {
handle: *const core::ffi::c_void handle: Option<*const core::ffi::c_void>,
descriptor: [u8; 10], //TODO which size?
} }
pub struct RawMutexGuard { pub struct RawMutexGuard {
@ -14,26 +16,59 @@ pub struct RawMutexGuard {
impl Drop for RawMutexGuard { impl Drop for RawMutexGuard {
fn drop(&mut self) { fn drop(&mut self) {
//TODO do we need some check here? check_global_threading_available!(); // tell me when you reach this one!
unsafe{osal::give_mutex(self.handle)}; // We use nullptr as marker for an uninitialized mutex, which we
// must not give
if self.handle != 0 as *const core::ffi::c_void {
unsafe { osal::give_mutex(self.handle) };
}
} }
} }
impl RawMutex { impl RawMutex {
pub fn new() -> Self { pub fn new() -> Self {
let handle = unsafe {osal::create_mutex()};
if handle == 0 as *const core::ffi::c_void {
panic!("Could not create mutex")
}
Self { Self {
handle: handle handle: None,
descriptor: [0; 10],
} }
} }
pub fn take(&self) -> Result<RawMutexGuard,()> { fn initialize(&mut self) {
match unsafe {osal::take_mutex(self.handle)} { // check_global_threading_available!(); we have a token, so this is redundant
1 => Ok(RawMutexGuard { handle: self.handle }), if self.handle != None {
_ => Err(()) //TODO error code return;
}
// TODO verify handle size
let handle = unsafe { osal::create_mutex() };
if handle == 0 as *const core::ffi::c_void {
panic!("Could not create mutex")
}
self.handle = Some(handle);
}
pub fn take(&self) -> Result<RawMutexGuard, ()> {
check_global_threading_available!();
if let Some(handle) = self.handle {
return match unsafe { osal::take_mutex(handle) } {
1 => Ok(RawMutexGuard { handle: handle }),
_ => Err(()), // Only when timeout expired (we have none) TODO error code
};
} else {
// nullptr makes the guard do nothing
Ok(RawMutexGuard {
handle: 0 as *const core::ffi::c_void,
})
}
}
// TODO protect with token
pub fn clone(&self) -> Self {
let mut_self = self as *const Self as *mut Self; //oh look, a C developer wrote this
unsafe { (*mut_self).initialize() }; //TODO this might be safe (we are in init), but does not look very good
// At this point self.handle must be valid, initialize would have panicked otherwise
Self {
handle: self.handle,
descriptor: [0; 10],
} }
} }
@ -51,11 +86,3 @@ impl RawMutex {
// } // }
// } // }
} }
impl Clone for RawMutex {
fn clone(&self) -> Self {
Self {
handle: self.handle
}
}
}