forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 488
Expand file tree
/
Copy pathsync.rs
More file actions
145 lines (124 loc) · 4.17 KB
/
sync.rs
File metadata and controls
145 lines (124 loc) · 4.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// SPDX-License-Identifier: GPL-2.0
use core::cell::UnsafeCell;
use core::fmt;
use core::ops::{Deref, DerefMut};
use crate::bindings;
pub struct Mutex<T: ?Sized> {
lock: bindings::mutex,
data: UnsafeCell<T>,
}
impl<T> Mutex<T> {
/// Create a new Mutex
pub fn new(data: T, _name: &'static str) -> Self {
let lock = bindings::mutex::default();
// TODO: write mutex debug traces like .magic.
// TODO: use name in the debug version
Self {
data: UnsafeCell::new(data),
lock,
}
}
}
impl<T: ?Sized> Mutex<T> {
/// acquire a lock on the mutex
/// # unsafe
/// This is unsafe, as it returns a second lock if one is already help by the current process
// with CONFIG_DEBUG_LOCK_ALLOW mutex_lock is a macro, which calls mutex_lock_nested(&mutex, 0)
#[cfg(CONFIG_DEBUG_LOCK_ALLOC)]
pub unsafe fn lock<'a>(&'a self) -> MutexGuard<'a, T> {
unsafe {
bindings::mutex_lock_nested(
&self.lock as *const bindings::mutex as *mut bindings::mutex,
0,
);
}
MutexGuard { inner: &self }
}
/// acquire a lock on the mutex
/// # unsafe
/// This is unsafe, as it returns a second lock if one is already help by the current process
#[cfg(not(CONFIG_DEBUG_LOCK_ALLOC))]
pub unsafe fn lock<'a>(&'a self) -> MutexGuard<'a, T> {
unsafe {
bindings::mutex_lock(&self.lock as *const bindings::mutex as *mut bindings::mutex);
}
MutexGuard { inner: &self }
}
/// try to acquire the lock, returns none on failure
/// # unsafe
/// This is unsafe, as it returns a second lock if one is already help by the current process
pub unsafe fn trylock<'a>(&'a self) -> Option<MutexGuard<'a, T>> {
let ret = unsafe {
bindings::mutex_trylock(&self.lock as *const bindings::mutex as *mut bindings::mutex)
};
if ret == 1 {
Some(MutexGuard { inner: &self })
} else {
None
}
}
/// test if the mutex is locked
pub fn is_locked(&self) -> bool {
unsafe {
bindings::mutex_is_locked(&self.lock as *const bindings::mutex as *mut bindings::mutex)
}
}
fn unlock(&self) {
unsafe {
bindings::mutex_unlock(&self.lock as *const bindings::mutex as *mut bindings::mutex);
}
}
}
unsafe impl<T: ?Sized> Send for Mutex<T> {}
unsafe impl<T: ?Sized + Send> Sync for Mutex<T> {}
impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// kindly borrowed from std::sync::Mutex
match unsafe { self.trylock() } {
Some(guard) => f.debug_struct("Mutex").field("data", &guard).finish(),
None => {
struct LockedPlaceholder;
impl fmt::Debug for LockedPlaceholder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("<locked>")
}
}
f.debug_struct("Mutex")
.field("data", &LockedPlaceholder)
.finish()
}
}
}
}
#[must_use]
pub struct MutexGuard<'a, T: ?Sized> {
inner: &'a Mutex<T>,
}
impl<'a, T: ?Sized> !Send for MutexGuard<'a, T> {}
unsafe impl<'a, T: ?Sized> Sync for MutexGuard<'a, T> {}
impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.inner.data.get() }
}
}
impl<'a, T: ?Sized> DerefMut for MutexGuard<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.inner.data.get() }
}
}
impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.deref(), f)
}
}
impl<'a, T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.deref(), f)
}
}
impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
fn drop(&mut self) {
self.inner.unlock();
}
}