Skip to content

Commit fc7bdba

Browse files
hoshinolinajannau
authored andcommitted
rust: sync: Add LockdepMap abstraction
This allows Rust code to explicitly integrate types with lockdep. Signed-off-by: Asahi Lina <lina@asahilina.net>
1 parent 0d8e7e2 commit fc7bdba

4 files changed

Lines changed: 61 additions & 0 deletions

File tree

rust/bindings/bindings_helper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/ioport.h>
2121
#include <linux/jiffies.h>
2222
#include <linux/jump_label.h>
23+
#include <linux/lockdep.h>
2324
#include <linux/mdio.h>
2425
#include <linux/miscdevice.h>
2526
#include <linux/of_device.h>

rust/helpers/helpers.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "io.c"
2020
#include "jump_label.c"
2121
#include "kunit.c"
22+
#include "lockdep.c"
2223
#include "mutex.c"
2324
#include "page.c"
2425
#include "platform.c"

rust/helpers/lockdep.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/instruction_pointer.h>
4+
#include <linux/lockdep.h>
5+
6+
void rust_helper_lock_acquire_ret(struct lockdep_map *lock, unsigned int subclass,
7+
int trylock, int read, int check,
8+
struct lockdep_map *nest_lock)
9+
{
10+
lock_acquire(lock, subclass, trylock, read, check, nest_lock, _RET_IP_);
11+
}
12+
13+
void rust_helper_lock_release_ret(struct lockdep_map *lock)
14+
{
15+
lock_release(lock, _RET_IP_);
16+
}

rust/kernel/sync/lockdep.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,3 +196,46 @@ pub(crate) fn caller_lock_class() -> (LockClassKey, &'static CStr) {
196196
}
197197
}
198198
}
199+
200+
pub(crate) struct LockdepMap(Opaque<bindings::lockdep_map>);
201+
pub(crate) struct LockdepGuard<'a>(&'a LockdepMap);
202+
203+
#[allow(dead_code)]
204+
impl LockdepMap {
205+
#[track_caller]
206+
pub(crate) fn new() -> Self {
207+
let map = Opaque::uninit();
208+
let (key, name) = caller_lock_class();
209+
210+
// SAFETY: Just calling the C API
211+
unsafe {
212+
bindings::lockdep_init_map_type(
213+
map.get(),
214+
name.as_char_ptr(),
215+
key.as_ptr(),
216+
0,
217+
bindings::lockdep_wait_type_LD_WAIT_INV as _,
218+
bindings::lockdep_wait_type_LD_WAIT_INV as _,
219+
bindings::lockdep_lock_type_LD_LOCK_NORMAL as _,
220+
)
221+
};
222+
223+
LockdepMap(map)
224+
}
225+
226+
#[inline(always)]
227+
pub(crate) fn lock(&self) -> LockdepGuard<'_> {
228+
// SAFETY: Just calling the C API
229+
unsafe { bindings::lock_acquire_ret(self.0.get(), 0, 0, 1, 1, core::ptr::null_mut()) };
230+
231+
LockdepGuard(self)
232+
}
233+
}
234+
235+
impl<'a> Drop for LockdepGuard<'a> {
236+
#[inline(always)]
237+
fn drop(&mut self) {
238+
// SAFETY: Just calling the C API
239+
unsafe { bindings::lock_release_ret(self.0 .0.get()) };
240+
}
241+
}

0 commit comments

Comments
 (0)