Skip to content

Commit 974a03e

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 974a03e

File tree

3 files changed

+134
-0
lines changed

3 files changed

+134
-0
lines changed

drivers/char/rust_example/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#![feature(global_asm)]
55

66
use kernel::prelude::*;
7+
use kernel::sync::Mutex;
78

89
module! {
910
type: RustExample,
@@ -36,6 +37,12 @@ impl KernelModule for RustExample {
3637
println!("Parameters:");
3738
println!(" my_bool: {}", my_bool.read());
3839
println!(" my_i32: {}", my_i32.read());
40+
41+
let rust_mutex = Mutex::new(1, "rust_mutex");
42+
println!("rust_mutex: {:?}", rust_mutex);
43+
let guard = rust_mutex.lock();
44+
println!("data: {:?}", guard);
45+
drop(guard);
3946
Ok(RustExample {
4047
message: "on the heap!".to_owned(),
4148
})

rust/kernel/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
use core::cell::UnsafeCell;
4+
use core::ops::{Deref, DerefMut};
5+
use core::fmt;
6+
7+
use crate::bindings;
8+
9+
#[cfg(CONFIG_DEBUG_SPINLOCK)]
10+
compile_error!("CONFIG_DEBUG_SPINLOCK not yet implemented");
11+
12+
#[cfg(CONFIG_DEBUG_MUTEX)]
13+
compile_error!("CONFIG_DEBUG_MUTEX not yet implemented");
14+
15+
pub struct Mutex<T: Send> {
16+
lock: bindings::mutex,
17+
data: UnsafeCell<T>,
18+
}
19+
20+
impl<T: Send> Mutex<T> {
21+
/// Create a new Mutex
22+
pub fn new(data: T, name: &'static str) -> Self {
23+
24+
let lock = bindings::mutex::default();
25+
// TODO: debug foo
26+
27+
Self {
28+
data: UnsafeCell::new(data),
29+
lock
30+
}
31+
}
32+
33+
/// acquire a lock on the mutex
34+
pub fn lock<'a>(&'a self) -> MutexGuard<'a, T> {
35+
unsafe {
36+
bindings::mutex_lock(&self.lock as *const bindings::mutex as *mut bindings::mutex);
37+
}
38+
MutexGuard { inner: &self }
39+
}
40+
41+
/// try to acquire the lock, returns none on failure
42+
pub fn try_lock<'a>(&'a self) -> Option<MutexGuard<'a, T>> {
43+
let ret = unsafe { bindings::mutex_trylock(&self.lock as *const bindings::mutex as *mut bindings::mutex) };
44+
if ret == 1 {
45+
Some(MutexGuard { inner: &self })
46+
} else {
47+
None
48+
}
49+
}
50+
51+
/// test if the mutex is locked
52+
pub fn is_locked(&self) -> bool {
53+
unsafe {
54+
bindings::mutex_is_locked(&self.lock as *const bindings::mutex as *mut bindings::mutex)
55+
}
56+
}
57+
58+
fn unlock(&self) {
59+
unsafe {
60+
bindings::mutex_unlock(&self.lock as *const bindings::mutex as *mut bindings::mutex);
61+
}
62+
}
63+
}
64+
65+
unsafe impl<T: Send> Send for Mutex<T> { }
66+
unsafe impl<T: Send> Sync for Mutex<T> { }
67+
68+
impl<T: Send + fmt::Debug> fmt::Debug for Mutex<T> {
69+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70+
// kindly borrowed from std::sync::Mutex
71+
match self.try_lock() {
72+
Some(guard) => f.debug_struct("Mutex").field("data", &guard).finish(),
73+
None => {
74+
struct LockedPlaceholder;
75+
impl fmt::Debug for LockedPlaceholder {
76+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77+
f.write_str("<locked>")
78+
}
79+
}
80+
81+
f.debug_struct("Mutex").field("data", &LockedPlaceholder).finish()
82+
},
83+
}
84+
}
85+
}
86+
87+
pub struct MutexGuard<'a, T: Send> {
88+
inner: &'a Mutex<T>,
89+
}
90+
91+
92+
unsafe impl<'a, T: Send> Send for MutexGuard<'a, T> { }
93+
unsafe impl<'a, T: Send> Sync for MutexGuard<'a, T> { }
94+
95+
impl<'a, T: Send> Deref for MutexGuard<'a, T> {
96+
type Target = T;
97+
98+
fn deref(&self) -> &Self::Target {
99+
unsafe { &*self.inner.data.get() }
100+
}
101+
}
102+
103+
impl<'a, T: Send> DerefMut for MutexGuard<'a, T> {
104+
fn deref_mut(&mut self) -> &mut Self::Target {
105+
unsafe { &mut *self.inner.data.get() }
106+
}
107+
}
108+
109+
impl<'a, T: Send + fmt::Debug> fmt::Debug for MutexGuard<'a, T> {
110+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111+
fmt::Debug::fmt(self.deref(), f)
112+
}
113+
}
114+
115+
impl<'a, T: Send + fmt::Display> fmt::Display for MutexGuard<'a, T> {
116+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117+
fmt::Display::fmt(self.deref(), f)
118+
}
119+
}
120+
121+
impl<'a, T: Send> Drop for MutexGuard<'a, T> {
122+
fn drop(&mut self) {
123+
self.inner.unlock();
124+
}
125+
}

0 commit comments

Comments
 (0)