Skip to content

Commit c432c07

Browse files
committed
Create a Mutex<T> type backed by the kernel mutex type
Signed-off-by: Finn Behrens <[email protected]>
1 parent 514443c commit c432c07

File tree

2 files changed

+143
-1
lines changed

2 files changed

+143
-1
lines changed

rust/kernel/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! The `kernel` crate
44
55
#![no_std]
6-
#![feature(allocator_api, alloc_error_handler)]
6+
#![feature(allocator_api, alloc_error_handler, const_fn_union)]
77

88
// Ensure conditional compilation based on the kernel configuration works;
99
// otherwise we may silently break things like initcall handling.
@@ -24,6 +24,8 @@ pub mod prelude;
2424
pub mod printk;
2525
pub mod random;
2626

27+
pub mod sync;
28+
2729
#[cfg(CONFIG_SYSCTL)]
2830
pub mod sysctl;
2931

rust/kernel/src/sync.rs

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
use core::cell::UnsafeCell;
2+
use core::ops::{Deref, DerefMut};
3+
4+
use crate::bindings;
5+
6+
#[cfg(CONFIG_DEBUG_SPINLOCK)]
7+
compile_error!("CONFIG_DEBUG_SPINLOCK not yet implemented");
8+
9+
#[cfg(CONFIG_DEBUG_MUTEX)]
10+
compile_error!("CONFIG_DEBUG_MUTEX not yet implemented");
11+
12+
fn new_spinlock(_name: &'static str) -> bindings::spinlock {
13+
#[repr(C)]
14+
union USpinLock {
15+
none: (),
16+
some: bindings::spinlock,
17+
};
18+
19+
let lock = unsafe { USpinLock { none: {} }.some }; // FIXME: quick hack. revert and implement CONFIG_DEBUG_SPINLOCK
20+
21+
lock
22+
}
23+
24+
/*pub struct SpinLock<T> {
25+
lock: bindings::spinlock,
26+
data: T,
27+
}
28+
29+
impl<T> SpinLock<T> {
30+
pub fn new(data: T, name: &'static str) -> Self {
31+
let lock = new_spinlock(name);
32+
33+
Self {
34+
data,
35+
lock,
36+
}
37+
}
38+
39+
pub fn lock<'a>(&'a self) -> SpinLockGuard<'a, T> {
40+
todo!("implement spinlockguard")
41+
}
42+
}
43+
44+
45+
pub struct SpinLockGuard<'a, T: 'a> {
46+
lock: &'a SpinLock<T>
47+
}*/
48+
49+
pub struct Mutex<T> {
50+
lock: *mut bindings::mutex,
51+
data: UnsafeCell<T>,
52+
}
53+
54+
impl<T> Mutex<T> {
55+
/// Create a new Mutex
56+
pub fn new(data: T, name: &'static str) -> Self {
57+
unsafe {
58+
let ret = Self::new_uninit(data, name);
59+
ret.init(name);
60+
ret
61+
}
62+
}
63+
64+
/// Create a new Mutex without spinlock and queue.
65+
/// This is used for const declarations
66+
pub const unsafe fn new_uninit(data: T, _name: &'static str) -> Self {
67+
#[repr(C)]
68+
union UMutex {
69+
none: (),
70+
some: bindings::mutex,
71+
};
72+
73+
let lock = UMutex { none: () }.some;
74+
let lock: *const bindings::mutex = &lock;
75+
// TODO: debug foo
76+
Self {
77+
data: UnsafeCell::new(data),
78+
lock: lock as *mut bindings::mutex,
79+
}
80+
}
81+
82+
/// Init a Mutex from a new_uninit
83+
pub unsafe fn init(&self, name: &'static str) {
84+
(*self.lock).wait_list = bindings::list_head {
85+
prev: &mut (*self.lock).wait_list,
86+
next: &mut (*self.lock).wait_list,
87+
};
88+
89+
(*self.lock).wait_lock = new_spinlock(name);
90+
}
91+
92+
/// acquire a lock on the mutex
93+
pub fn lock<'a>(&'a self) -> MutexGuard<'a, T> {
94+
unsafe {
95+
bindings::mutex_lock(self.lock);
96+
}
97+
MutexGuard { inner: &self }
98+
}
99+
100+
/// try to acquire the lock, returns none on failure
101+
pub fn try_lock<'a>(&'a self) -> Option<MutexGuard<'a, T>> {
102+
let ret = unsafe { bindings::mutex_trylock(self.lock) };
103+
if ret == 1 {
104+
Some(MutexGuard { inner: &self })
105+
} else {
106+
None
107+
}
108+
}
109+
110+
fn unlock(&self) {
111+
unsafe {
112+
bindings::mutex_unlock(self.lock);
113+
}
114+
}
115+
//TODO try_lock()
116+
}
117+
118+
pub struct MutexGuard<'a, T> {
119+
inner: &'a Mutex<T>,
120+
}
121+
122+
impl<'a, T> Deref for MutexGuard<'a, T> {
123+
type Target = T;
124+
125+
fn deref(&self) -> &Self::Target {
126+
unsafe { &*self.inner.data.get() }
127+
}
128+
}
129+
130+
impl<'a, T> DerefMut for MutexGuard<'a, T> {
131+
fn deref_mut(&mut self) -> &mut Self::Target {
132+
unsafe { &mut *self.inner.data.get() }
133+
}
134+
}
135+
136+
impl<'a, T> Drop for MutexGuard<'a, T> {
137+
fn drop(&mut self) {
138+
self.inner.unlock();
139+
}
140+
}

0 commit comments

Comments
 (0)