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> {
actual_data: default_values,
actual_data: init_values,
mutex: mutex::RawMutex::new(),
}
}

View File

@ -1,11 +1,13 @@
use crate::check_global_threading_available;
use super::osal;
// for now, this is an implementation based on FreeRTOS, where we can preallocate mutexes
// this allows us to assume that mutexes are valid starting from their creation until end of runtime
// and so we do not use the global_threading lock
// TODO we do not discern between a mutex (holding the descriptor) and a clone (pointing to the
// original descriptor), waisting some memory
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 {
@ -14,26 +16,59 @@ pub struct RawMutexGuard {
impl Drop for RawMutexGuard {
fn drop(&mut self) {
//TODO do we need some check here?
unsafe{osal::give_mutex(self.handle)};
check_global_threading_available!(); // tell me when you reach this one!
// 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 {
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 {
handle: handle
handle: None,
descriptor: [0; 10],
}
}
pub fn take(&self) -> Result<RawMutexGuard,()> {
match unsafe {osal::take_mutex(self.handle)} {
1 => Ok(RawMutexGuard { handle: self.handle }),
_ => Err(()) //TODO error code
fn initialize(&mut self) {
// check_global_threading_available!(); we have a token, so this is redundant
if self.handle != None {
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
}
}
}