abi_definitions/task/
mutex.rs1use core::{
2 mem::{align_of, size_of},
3 ptr::drop_in_place,
4};
5use synchronization::blocking_mutex::{Mutex, raw::CriticalSectionRawMutex};
6use task::TaskIdentifier;
7
8use crate::XilaTaskIdentifier;
9
10#[derive(Debug, Clone, Copy, Default)]
11struct MutexState {
12 task: Option<TaskIdentifier>,
13 lock_count: u32, }
15
16pub struct RawMutex {
17 mutex: Mutex<CriticalSectionRawMutex, MutexState>,
18 recursive: bool,
19}
20
21impl RawMutex {
22 pub fn new(recursive: bool) -> Self {
23 Self {
24 mutex: Mutex::new(MutexState::default()),
25 recursive,
26 }
27 }
28
29 pub fn is_valid_pointer(pointer: *const RawMutex) -> bool {
30 !pointer.is_null() && (pointer as usize).is_multiple_of(align_of::<Self>())
31 }
32
33 pub unsafe fn from_pointer<'a>(pointer: *const RawMutex) -> Option<&'a Self> {
40 unsafe {
41 if !Self::is_valid_pointer(pointer) {
42 return None;
43 }
44 Some(&*pointer)
45 }
46 }
47
48 pub unsafe fn from_mutable_pointer<'a>(pointer: *mut RawMutex) -> Option<&'a mut Self> {
55 unsafe {
56 if !Self::is_valid_pointer(pointer) {
57 return None;
58 }
59 Some(&mut *pointer)
60 }
61 }
62
63 pub fn lock(&self, task: TaskIdentifier) -> bool {
64 unsafe {
65 self.mutex.lock_mut(|state| {
66 if let Some(owner) = state.task {
67 if owner == task && self.recursive {
68 state.lock_count += 1;
70 return true;
71 }
72 return false;
74 }
75
76 state.task = Some(task);
78 state.lock_count = 1;
79 true
80 })
81 }
82 }
83
84 pub fn unlock(&self, task: TaskIdentifier) -> bool {
85 unsafe {
86 self.mutex.lock_mut(|state| {
87 if let Some(owner) = state.task
89 && owner == task
90 {
91 if self.recursive && state.lock_count > 1 {
92 state.lock_count -= 1;
94 } else {
95 state.task = None;
97 state.lock_count = 0;
98 }
99 return true; }
101 false })
103 }
104 }
105}
106
107#[unsafe(no_mangle)]
108pub static RAW_MUTEX_SIZE: usize = size_of::<RawMutex>();
109
110#[unsafe(no_mangle)]
120pub unsafe extern "C" fn xila_initialize_mutex(mutex: *mut RawMutex) -> bool {
121 unsafe {
122 if mutex.is_null() {
123 return false;
124 }
125
126 if !(mutex as usize).is_multiple_of(align_of::<RawMutex>()) {
127 return false;
128 }
129
130 mutex.write(RawMutex::new(false));
131
132 true
133 }
134}
135
136#[unsafe(no_mangle)]
145pub unsafe extern "C" fn xila_initialize_recursive_mutex(mutex: *mut RawMutex) -> bool {
146 unsafe {
147 if mutex.is_null() {
148 return false;
149 }
150
151 if !(mutex as usize).is_multiple_of(align_of::<RawMutex>()) {
152 return false;
153 }
154
155 mutex.write(RawMutex::new(true));
156
157 true
158 }
159}
160
161#[unsafe(no_mangle)]
169pub unsafe extern "C" fn xila_lock_mutex(mutex: *mut RawMutex, task: XilaTaskIdentifier) -> bool {
170 unsafe {
171 let mutex = match RawMutex::from_mutable_pointer(mutex) {
172 Some(mutex) => mutex,
173 None => return false,
174 };
175
176 mutex.lock(task.into())
177 }
178}
179
180#[unsafe(no_mangle)]
189pub unsafe extern "C" fn xila_unlock_mutex(mutex: *mut RawMutex, task: XilaTaskIdentifier) -> bool {
190 unsafe {
191 let mutex = match RawMutex::from_mutable_pointer(mutex) {
192 Some(mutex) => mutex,
193 None => return false,
194 };
195
196 mutex.unlock(task.into())
197 }
198}
199
200#[unsafe(no_mangle)]
209pub unsafe extern "C" fn xila_destroy_mutex(mutex: *mut RawMutex) -> bool {
210 unsafe {
211 let mutex = match RawMutex::from_mutable_pointer(mutex) {
212 Some(mutex) => mutex,
213 None => return false,
214 };
215
216 drop_in_place(mutex);
218
219 true }
221}