Skip to content

Commit c9be2e0

Browse files
committed
rust: hide bindings::lock_class_key from drivers
This is in preparation for using lock classes in gpio drivers and executors. (Which is a requirement imposed by the C implementation, not something new to Rust.) This takes us closer to making the `bindings` module private to the `kernel` crate. Signed-off-by: Wedson Almeida Filho <[email protected]>
1 parent 7bd1ccf commit c9be2e0

File tree

10 files changed

+81
-120
lines changed

10 files changed

+81
-120
lines changed

rust/kernel/device.rs

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{
1111
bindings,
1212
revocable::{Revocable, RevocableGuard},
1313
str::CStr,
14-
sync::{NeedsLockClass, RevocableMutex, RevocableMutexGuard, UniqueRef},
14+
sync::{LockClassKey, NeedsLockClass, RevocableMutex, RevocableMutexGuard, UniqueRef},
1515
Result,
1616
};
1717
use core::{
@@ -240,26 +240,13 @@ pub struct Data<T, U, V> {
240240
#[macro_export]
241241
macro_rules! new_device_data {
242242
($reg:expr, $res:expr, $gen:expr, $name:literal) => {{
243-
static mut CLASS1: core::mem::MaybeUninit<$crate::bindings::lock_class_key> =
244-
core::mem::MaybeUninit::uninit();
245-
static mut CLASS2: core::mem::MaybeUninit<$crate::bindings::lock_class_key> =
246-
core::mem::MaybeUninit::uninit();
243+
static CLASS1: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
244+
static CLASS2: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
247245
let regs = $reg;
248246
let res = $res;
249247
let gen = $gen;
250248
let name = $crate::c_str!($name);
251-
// SAFETY: `CLASS1` and `CLASS2` are never used by Rust code directly; the C portion of the
252-
// kernel may change it though.
253-
unsafe {
254-
$crate::device::Data::try_new(
255-
regs,
256-
res,
257-
gen,
258-
name,
259-
CLASS1.as_mut_ptr(),
260-
CLASS2.as_mut_ptr(),
261-
)
262-
}
249+
$crate::device::Data::try_new(regs, res, gen, name, &CLASS1, &CLASS2)
263250
}};
264251
}
265252

@@ -268,18 +255,13 @@ impl<T, U, V> Data<T, U, V> {
268255
///
269256
/// It is recommended that the [`new_device_data`] macro be used as it automatically creates
270257
/// the lock classes.
271-
///
272-
/// # Safety
273-
///
274-
/// `key1` and `key2` must point to valid memory locations and remain valid until `self` is
275-
/// dropped.
276-
pub unsafe fn try_new(
258+
pub fn try_new(
277259
registrations: T,
278260
resources: U,
279261
general: V,
280262
name: &'static CStr,
281-
key1: *mut bindings::lock_class_key,
282-
key2: *mut bindings::lock_class_key,
263+
key1: &'static LockClassKey,
264+
key2: &'static LockClassKey,
283265
) -> Result<Pin<UniqueRef<Self>>> {
284266
let mut ret = Pin::from(UniqueRef::try_new(Self {
285267
// SAFETY: We call `RevocableMutex::init` below.
@@ -290,9 +272,7 @@ impl<T, U, V> Data<T, U, V> {
290272

291273
// SAFETY: `Data::registrations` is pinned when `Data` is.
292274
let pinned = unsafe { ret.as_mut().map_unchecked_mut(|d| &mut d.registrations) };
293-
294-
// SAFETY: The safety requirements of this function satisfy those of `RevocableMutex::init`.
295-
unsafe { pinned.init(name, key1, key2) };
275+
pinned.init(name, key1, key2);
296276
Ok(ret)
297277
}
298278

rust/kernel/sync.rs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
//! ```
2323
2424
use crate::{bindings, str::CStr};
25-
use core::pin::Pin;
25+
use core::{cell::UnsafeCell, mem::MaybeUninit, pin::Pin};
2626

2727
mod arc;
2828
mod condvar;
@@ -48,25 +48,37 @@ pub use rwsem::{RevocableRwSemaphore, RevocableRwSemaphoreGuard, RwSemaphore};
4848
pub use seqlock::{SeqLock, SeqLockReadGuard};
4949
pub use spinlock::{RawSpinLock, SpinLock};
5050

51+
/// Represents a lockdep class. It's a wrapper around C's `lock_class_key`.
52+
#[repr(transparent)]
53+
pub struct LockClassKey(UnsafeCell<MaybeUninit<bindings::lock_class_key>>);
54+
55+
// SAFETY: This is a wrapper around a lock class key, so it is safe to use references to it from
56+
// any thread.
57+
unsafe impl Sync for LockClassKey {}
58+
59+
impl LockClassKey {
60+
/// Creates a new lock class key.
61+
pub const fn new() -> Self {
62+
Self(UnsafeCell::new(MaybeUninit::uninit()))
63+
}
64+
65+
fn get(&self) -> *mut bindings::lock_class_key {
66+
self.0.get().cast()
67+
}
68+
}
69+
5170
/// Safely initialises an object that has an `init` function that takes a name and a lock class as
5271
/// arguments, examples of these are [`Mutex`] and [`SpinLock`]. Each of them also provides a more
5372
/// specialised name that uses this macro.
5473
#[doc(hidden)]
5574
#[macro_export]
5675
macro_rules! init_with_lockdep {
5776
($obj:expr, $name:expr) => {{
58-
static mut CLASS1: core::mem::MaybeUninit<$crate::bindings::lock_class_key> =
59-
core::mem::MaybeUninit::uninit();
60-
static mut CLASS2: core::mem::MaybeUninit<$crate::bindings::lock_class_key> =
61-
core::mem::MaybeUninit::uninit();
77+
static CLASS1: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
78+
static CLASS2: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
6279
let obj = $obj;
6380
let name = $crate::c_str!($name);
64-
// SAFETY: `CLASS1` and `CLASS2` are never used by Rust code directly; the C portion of the
65-
// kernel may change it though.
66-
#[allow(unused_unsafe)]
67-
unsafe {
68-
$crate::sync::NeedsLockClass::init(obj, name, CLASS1.as_mut_ptr(), CLASS2.as_mut_ptr())
69-
};
81+
$crate::sync::NeedsLockClass::init(obj, name, &CLASS1, &CLASS2)
7082
}};
7183
}
7284

@@ -79,16 +91,11 @@ pub trait NeedsLockClass {
7991
///
8092
/// Callers are encouraged to use the [`init_with_lockdep`] macro as it automatically creates a
8193
/// new lock class on each usage.
82-
///
83-
/// # Safety
84-
///
85-
/// `key1` and `key2` must point to valid memory locations and remain valid until `self` is
86-
/// dropped.
87-
unsafe fn init(
94+
fn init(
8895
self: Pin<&mut Self>,
8996
name: &'static CStr,
90-
key1: *mut bindings::lock_class_key,
91-
key2: *mut bindings::lock_class_key,
97+
key1: &'static LockClassKey,
98+
key2: &'static LockClassKey,
9299
);
93100
}
94101

rust/kernel/sync/condvar.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
//! This module allows Rust code to use the kernel's [`struct wait_queue_head`] as a condition
66
//! variable.
77
8-
use super::{Guard, Lock, LockInfo, NeedsLockClass};
8+
use super::{Guard, Lock, LockClassKey, LockInfo, NeedsLockClass};
99
use crate::{bindings, str::CStr, task::Task, Opaque};
1010
use core::{marker::PhantomPinned, pin::Pin};
1111

@@ -127,12 +127,14 @@ impl CondVar {
127127
}
128128

129129
impl NeedsLockClass for CondVar {
130-
unsafe fn init(
130+
fn init(
131131
self: Pin<&mut Self>,
132132
name: &'static CStr,
133-
key: *mut bindings::lock_class_key,
134-
_: *mut bindings::lock_class_key,
133+
key: &'static LockClassKey,
134+
_: &'static LockClassKey,
135135
) {
136-
unsafe { bindings::__init_waitqueue_head(self.wait_list.get(), name.as_char_ptr(), key) };
136+
unsafe {
137+
bindings::__init_waitqueue_head(self.wait_list.get(), name.as_char_ptr(), key.get())
138+
};
137139
}
138140
}

rust/kernel/sync/guard.rs

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
//! the ([`Lock`]) trait. It also contains the definition of the trait, which can be leveraged by
77
//! other constructs to work on generic locking primitives.
88
9-
use super::NeedsLockClass;
10-
use crate::{bindings, str::CStr, Bool, False, True};
9+
use super::{LockClassKey, NeedsLockClass};
10+
use crate::{str::CStr, Bool, False, True};
1111
use core::pin::Pin;
1212

1313
/// Allows mutual exclusion primitives that implement the [`Lock`] trait to automatically unlock
@@ -144,26 +144,16 @@ pub trait LockFactory {
144144
/// A lock that can be initialised with a single lock class key.
145145
pub trait LockIniter {
146146
/// Initialises the lock instance so that it can be safely used.
147-
///
148-
/// # Safety
149-
///
150-
/// `key` must point to a valid memory location that will remain valid until the lock is
151-
/// dropped.
152-
unsafe fn init_lock(
153-
self: Pin<&mut Self>,
154-
name: &'static CStr,
155-
key: *mut bindings::lock_class_key,
156-
);
147+
fn init_lock(self: Pin<&mut Self>, name: &'static CStr, key: &'static LockClassKey);
157148
}
158149

159150
impl<L: LockIniter> NeedsLockClass for L {
160-
unsafe fn init(
151+
fn init(
161152
self: Pin<&mut Self>,
162153
name: &'static CStr,
163-
key: *mut bindings::lock_class_key,
164-
_: *mut bindings::lock_class_key,
154+
key: &'static LockClassKey,
155+
_: &'static LockClassKey,
165156
) {
166-
// SAFETY: The safety requirements of this function satisfy those of `init_lock`.
167-
unsafe { self.init_lock(name, key) };
157+
self.init_lock(name, key);
168158
}
169159
}

rust/kernel/sync/mutex.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//!
55
//! This module allows Rust code to use the kernel's [`struct mutex`].
66
7-
use super::{Guard, Lock, LockFactory, LockIniter, WriteLock};
7+
use super::{Guard, Lock, LockClassKey, LockFactory, LockIniter, WriteLock};
88
use crate::{bindings, str::CStr, Opaque};
99
use core::{cell::UnsafeCell, marker::PhantomPinned, pin::Pin};
1010

@@ -82,12 +82,8 @@ impl<T> LockFactory for Mutex<T> {
8282
}
8383

8484
impl<T> LockIniter for Mutex<T> {
85-
unsafe fn init_lock(
86-
self: Pin<&mut Self>,
87-
name: &'static CStr,
88-
key: *mut bindings::lock_class_key,
89-
) {
90-
unsafe { bindings::__mutex_init(self.mutex.get(), name.as_char_ptr(), key) };
85+
fn init_lock(self: Pin<&mut Self>, name: &'static CStr, key: &'static LockClassKey) {
86+
unsafe { bindings::__mutex_init(self.mutex.get(), name.as_char_ptr(), key.get()) };
9187
}
9288
}
9389

rust/kernel/sync/revocable.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
//! Synchronisation primitives where access to their contents can be revoked at runtime.
44
55
use crate::{
6-
bindings,
76
str::CStr,
8-
sync::{Guard, Lock, LockFactory, LockInfo, NeedsLockClass, ReadLock, WriteLock},
7+
sync::{Guard, Lock, LockClassKey, LockFactory, LockInfo, NeedsLockClass, ReadLock, WriteLock},
98
True,
109
};
1110
use core::{
@@ -130,18 +129,15 @@ impl<F: LockFactory, T> NeedsLockClass for Revocable<F, T>
130129
where
131130
F::LockedType<Inner<T>>: NeedsLockClass,
132131
{
133-
unsafe fn init(
132+
fn init(
134133
self: Pin<&mut Self>,
135134
name: &'static CStr,
136-
key1: *mut bindings::lock_class_key,
137-
key2: *mut bindings::lock_class_key,
135+
key1: &'static LockClassKey,
136+
key2: &'static LockClassKey,
138137
) {
139138
// SAFETY: `inner` is pinned when `self` is.
140139
let inner = unsafe { self.map_unchecked_mut(|r| &mut r.inner) };
141-
142-
// SAFETY: The safety requirements of this function satisfy the ones for `inner.init`
143-
// (they're the same).
144-
unsafe { inner.init(name, key1, key2) };
140+
inner.init(name, key1, key2);
145141
}
146142
}
147143

rust/kernel/sync/rwsem.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
//!
77
//! C header: [`include/linux/rwsem.h`](../../../../include/linux/rwsem.h)
88
9-
use super::{mutex::EmptyGuardContext, Guard, Lock, LockFactory, LockIniter, ReadLock, WriteLock};
9+
use super::{
10+
mutex::EmptyGuardContext, Guard, Lock, LockClassKey, LockFactory, LockIniter, ReadLock,
11+
WriteLock,
12+
};
1013
use crate::{bindings, str::CStr, Opaque};
1114
use core::{cell::UnsafeCell, marker::PhantomPinned, pin::Pin};
1215

@@ -95,12 +98,8 @@ impl<T> LockFactory for RwSemaphore<T> {
9598
}
9699

97100
impl<T> LockIniter for RwSemaphore<T> {
98-
unsafe fn init_lock(
99-
self: Pin<&mut Self>,
100-
name: &'static CStr,
101-
key: *mut bindings::lock_class_key,
102-
) {
103-
unsafe { bindings::__init_rwsem(self.rwsem.get(), name.as_char_ptr(), key) };
101+
fn init_lock(self: Pin<&mut Self>, name: &'static CStr, key: &'static LockClassKey) {
102+
unsafe { bindings::__init_rwsem(self.rwsem.get(), name.as_char_ptr(), key.get()) };
104103
}
105104
}
106105

rust/kernel/sync/seqlock.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//!
88
//! See <https://www.kernel.org/doc/Documentation/locking/seqlock.rst>.
99
10-
use super::{Guard, Lock, LockFactory, LockIniter, NeedsLockClass, ReadLock};
10+
use super::{Guard, Lock, LockClassKey, LockFactory, LockIniter, NeedsLockClass, ReadLock};
1111
use crate::{bindings, str::CStr, Opaque};
1212
use core::{cell::UnsafeCell, marker::PhantomPinned, ops::Deref, pin::Pin};
1313

@@ -130,18 +130,17 @@ impl<L: Lock + ?Sized> SeqLock<L> {
130130
}
131131

132132
impl<L: LockIniter + Lock + ?Sized> NeedsLockClass for SeqLock<L> {
133-
unsafe fn init(
133+
fn init(
134134
mut self: Pin<&mut Self>,
135135
name: &'static CStr,
136-
key1: *mut bindings::lock_class_key,
137-
key2: *mut bindings::lock_class_key,
136+
key1: &'static LockClassKey,
137+
key2: &'static LockClassKey,
138138
) {
139139
// SAFETY: `write_lock` is pinned when `self` is.
140140
let pinned = unsafe { self.as_mut().map_unchecked_mut(|s| &mut s.write_lock) };
141-
// SAFETY: `key1` is valid by the safety requirements of this function.
142-
unsafe { pinned.init_lock(name, key1) };
143-
// SAFETY: `key2` is valid by the safety requirements of this function.
144-
unsafe { bindings::__seqcount_init(self.count.get(), name.as_char_ptr(), key2) };
141+
pinned.init_lock(name, key1);
142+
// SAFETY: `key2` is valid as it has a static lifetime.
143+
unsafe { bindings::__seqcount_init(self.count.get(), name.as_char_ptr(), key2.get()) };
145144
}
146145
}
147146

rust/kernel/sync/smutex.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
//! When the waiter queue is non-empty, unlocking the mutex always results in the first waiter being
4747
//! popped form the queue and awakened.
4848
49-
use super::{mutex::EmptyGuardContext, Guard, Lock, LockFactory, LockIniter};
49+
use super::{mutex::EmptyGuardContext, Guard, Lock, LockClassKey, LockFactory, LockIniter};
5050
use crate::{bindings, str::CStr, Opaque};
5151
use core::sync::atomic::{AtomicUsize, Ordering};
5252
use core::{cell::UnsafeCell, pin::Pin};
@@ -153,12 +153,7 @@ impl<T> LockFactory for Mutex<T> {
153153
}
154154

155155
impl<T> LockIniter for Mutex<T> {
156-
unsafe fn init_lock(
157-
self: Pin<&mut Self>,
158-
_name: &'static CStr,
159-
_key: *mut bindings::lock_class_key,
160-
) {
161-
}
156+
fn init_lock(self: Pin<&mut Self>, _name: &'static CStr, _key: &'static LockClassKey) {}
162157
}
163158

164159
// SAFETY: The mutex implementation ensures mutual exclusion.

0 commit comments

Comments
 (0)