Skip to content

Commit b72fb80

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 b72fb80

File tree

3 files changed

+128
-1
lines changed

3 files changed

+128
-1
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: 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: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
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> {
16+
lock: bindings::mutex,
17+
data: UnsafeCell<T>,
18+
}
19+
20+
impl<T> 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+
impl<T: fmt::Debug> fmt::Debug for Mutex<T> {
66+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67+
// kindly borrowed from std::sync::Mutex
68+
match self.try_lock() {
69+
Some(guard) => f.debug_struct("Mutex").field("data", &guard).finish(),
70+
None => {
71+
struct LockedPlaceholder;
72+
impl fmt::Debug for LockedPlaceholder {
73+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74+
f.write_str("<locked>")
75+
}
76+
}
77+
78+
f.debug_struct("Mutex").field("data", &LockedPlaceholder).finish()
79+
},
80+
}
81+
}
82+
}
83+
84+
pub struct MutexGuard<'a, T> {
85+
inner: &'a Mutex<T>,
86+
}
87+
88+
impl<'a, T> Deref for MutexGuard<'a, T> {
89+
type Target = T;
90+
91+
fn deref(&self) -> &Self::Target {
92+
unsafe { &*self.inner.data.get() }
93+
}
94+
}
95+
96+
impl<'a, T> DerefMut for MutexGuard<'a, T> {
97+
fn deref_mut(&mut self) -> &mut Self::Target {
98+
unsafe { &mut *self.inner.data.get() }
99+
}
100+
}
101+
102+
impl<'a, T: fmt::Debug> fmt::Debug for MutexGuard<'a, T> {
103+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104+
fmt::Debug::fmt(self.deref(), f)
105+
}
106+
}
107+
108+
impl<'a, T: fmt::Display> fmt::Display for MutexGuard<'a, T> {
109+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110+
fmt::Display::fmt(self.deref(), f)
111+
}
112+
}
113+
114+
impl<'a, T> Drop for MutexGuard<'a, T> {
115+
fn drop(&mut self) {
116+
self.inner.unlock();
117+
}
118+
}

0 commit comments

Comments
 (0)