diff --git a/mission_rust/src/fsrc/datasets/mod.rs b/mission_rust/src/fsrc/datasets/mod.rs index fd12f2a..0485888 100644 --- a/mission_rust/src/fsrc/datasets/mod.rs +++ b/mission_rust/src/fsrc/datasets/mod.rs @@ -52,9 +52,9 @@ impl OwnedDataset { } } - pub fn new_default(default_values: T) -> OwnedDataset { + pub fn new_init_values(init_values: T) -> OwnedDataset { OwnedDataset:: { - actual_data: default_values, + actual_data: init_values, mutex: mutex::RawMutex::new(), } } diff --git a/mission_rust/src/fsrc/mutex.rs b/mission_rust/src/fsrc/mutex.rs index 3aeae00..a17073e 100644 --- a/mission_rust/src/fsrc/mutex.rs +++ b/mission_rust/src/fsrc/mutex.rs @@ -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 { - 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 { + 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 - } - } -} \ No newline at end of file