1use core::cell::UnsafeCell;
10use core::mem;
11
12#[cfg(windows)]
13use winapi::um::synchapi::{AcquireSRWLockExclusive, DeleteCriticalSection, EnterCriticalSection,
14 InitializeCriticalSection, LeaveCriticalSection,
15 ReleaseSRWLockExclusive};
16
17#[cfg(unix)]
18use libc;
19
20mod raw {
21 #[cfg(unix)]
22 pub use libc::pthread_mutex_t;
23 #[cfg(windows)]
24 pub use winapi::um::minwinbase::CRITICAL_SECTION;
25 #[cfg(windows)]
26 pub use winapi::um::synchapi::SRWLOCK;
27 #[cfg(any(target_os = "macos", target_os = "ios"))]
28 #[repr(C)]
29 pub struct OSSpinLock(pub i32);
30}
31
32use RawMutex;
33
34pub trait UnsafeRawOsMutex {
39 unsafe fn init(_mutex: *mut Self) {}
43
44 unsafe fn destroy(_mutex: *mut Self) {}
48
49 unsafe fn lock(mutex: *mut Self);
53
54 unsafe fn unlock(mutex: *mut Self);
58}
59
60pub struct RawOsMutex<T: UnsafeRawOsMutex> {
104 #[doc(hidden)]
105 pub __inner: UnsafeCell<T>,
106}
107
108unsafe impl<T: UnsafeRawOsMutex> Send for RawOsMutex<T> {}
109unsafe impl<T: UnsafeRawOsMutex> Sync for RawOsMutex<T> {}
110
111impl<T: UnsafeRawOsMutex> RawMutex for RawOsMutex<T> {
112 unsafe fn init(&mut self) {
113 T::init(self.__inner.get());
114 }
115
116 unsafe fn lock(&self) {
117 T::lock(self.__inner.get());
118 }
119
120 unsafe fn unlock(&self) {
121 T::unlock(self.__inner.get());
122 }
123
124 unsafe fn destroy(&self) {
125 T::destroy(self.__inner.get());
126 }
127}
128
129#[macro_export]
153macro_rules! raw_os_mutex_new {
154 ($e:expr) => {
155 $crate::RawOsMutex {
156 __inner: $crate::UnsafeCell::new($e),
157 }
158 };
159}
160
161#[cfg(windows)]
163pub type SRWLOCK = RawOsMutex<raw::SRWLOCK>;
164
165#[cfg(windows)]
166impl UnsafeRawOsMutex for raw::SRWLOCK {
167 #[inline]
168 unsafe fn lock(mutex: *mut Self) {
169 AcquireSRWLockExclusive(mutex);
170 }
171
172 #[inline]
173 unsafe fn unlock(mutex: *mut Self) {
174 ReleaseSRWLockExclusive(mutex);
175 }
176}
177
178#[cfg(windows)]
179#[doc(hidden)]
180pub use winapi::um::synchapi::SRWLOCK_INIT;
181
182#[cfg(windows)]
194#[macro_export]
195macro_rules! srwlock_new {
196 () => {
197 raw_os_mutex_new!($crate::SRWLOCK_INIT)
198 };
199}
200
201#[cfg(windows)]
202impl Default for SRWLOCK {
203 #[inline]
204 fn default() -> Self {
205 srwlock_new!()
206 }
207}
208
209#[cfg(windows)]
211#[allow(non_camel_case_types)]
212pub type CRITICAL_SECTION = RawOsMutex<raw::CRITICAL_SECTION>;
213
214#[cfg(windows)]
215impl UnsafeRawOsMutex for raw::CRITICAL_SECTION {
216 #[inline]
217 unsafe fn init(mutex: *mut Self) {
218 InitializeCriticalSection(mutex);
219 }
220
221 #[inline]
222 unsafe fn lock(mutex: *mut Self) {
223 EnterCriticalSection(mutex);
224 }
225
226 #[inline]
227 unsafe fn unlock(mutex: *mut Self) {
228 LeaveCriticalSection(mutex);
229 }
230
231 #[inline]
232 unsafe fn destroy(mutex: *mut Self) {
233 DeleteCriticalSection(mutex);
234 }
235}
236
237#[cfg(windows)]
238impl Default for CRITICAL_SECTION {
239 #[inline]
240 fn default() -> Self {
241 unsafe { mem::uninitialized() }
242 }
243}
244
245#[cfg(unix)]
246#[doc(hidden)]
247pub use libc::PTHREAD_MUTEX_INITIALIZER;
248
249#[cfg(unix)]
251#[allow(non_camel_case_types)]
252pub type pthread_mutex_t = RawOsMutex<raw::pthread_mutex_t>;
253
254#[cfg(unix)]
255impl UnsafeRawOsMutex for raw::pthread_mutex_t {
256 unsafe fn init(mutex: *mut Self) {
257 let mut attr: libc::pthread_mutexattr_t = mem::uninitialized();
258 let r = libc::pthread_mutexattr_init(&mut attr);
259 debug_assert_eq!(r, 0);
260 let r = libc::pthread_mutexattr_settype(&mut attr, libc::PTHREAD_MUTEX_NORMAL);
261 debug_assert_eq!(r, 0);
262 let r = libc::pthread_mutex_init(mutex, &attr);
263 debug_assert_eq!(r, 0);
264 let r = libc::pthread_mutexattr_destroy(&mut attr);
265 debug_assert_eq!(r, 0);
266 }
267
268 #[inline]
269 unsafe fn lock(mutex: *mut Self) {
270 libc::pthread_mutex_lock(mutex);
271 }
272
273 #[inline]
274 unsafe fn unlock(mutex: *mut Self) {
275 libc::pthread_mutex_unlock(mutex);
276 }
277
278 #[inline]
279 unsafe fn destroy(mutex: *mut Self) {
280 libc::pthread_mutex_destroy(mutex);
281 }
282}
283
284#[cfg(unix)]
296#[macro_export]
297macro_rules! pthread_mutex_new {
298 () => {
299 raw_os_mutex_new!($crate::PTHREAD_MUTEX_INITIALIZER)
300 };
301 ($e:expr) => {
302 raw_os_mutex_new!($e)
303 };
304}
305
306#[cfg(unix)]
307impl Default for pthread_mutex_t {
308 #[inline]
309 fn default() -> Self {
310 pthread_mutex_new!()
311 }
312}
313
314#[cfg(any(target_os = "macos", target_os = "ios"))]
315#[doc(hidden)]
316pub const OS_SPINLOCK_INIT: raw::OSSpinLock = raw::OSSpinLock(0);
317
318#[cfg(any(target_os = "macos", target_os = "ios"))]
319#[link(name = "System")]
320extern "C" {
321 fn OSSpinLockLock(lock: *mut raw::OSSpinLock);
322 fn OSSpinLockUnlock(lock: *mut raw::OSSpinLock);
323}
324
325#[cfg(any(target_os = "macos", target_os = "ios"))]
327pub type OSSpinLock = RawOsMutex<raw::OSSpinLock>;
328
329#[cfg(any(target_os = "macos", target_os = "ios"))]
330impl UnsafeRawOsMutex for raw::OSSpinLock {
331 #[inline]
332 unsafe fn lock(mutex: *mut Self) {
333 OSSpinLockLock(mutex);
334 }
335
336 #[inline]
337 unsafe fn unlock(mutex: *mut Self) {
338 OSSpinLockUnlock(mutex);
339 }
340}
341
342#[cfg(any(target_os = "macos", target_os = "ios"))]
354#[macro_export]
355macro_rules! osspinlock_new {
356 () => {
357 raw_os_mutex_new!($crate::OS_SPINLOCK_INIT)
358 };
359}
360
361#[cfg(any(target_os = "macos", target_os = "ios"))]
362impl Default for OSSpinLock {
363 #[inline]
364 fn default() -> Self {
365 osspinlock_new!()
366 }
367}