Skip to content

Commit f149fe4

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 029e452 commit f149fe4

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/firmware.h>
2121
#include <linux/fs.h>
2222
#include <linux/jiffies.h>
23+
#include <linux/lockdep.h>
2324
#include <linux/mdio.h>
2425
#include <linux/of_device.h>
2526
#include <linux/pci.h>

rust/helpers/helpers.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "err.c"
1717
#include "io.c"
1818
#include "kunit.c"
19+
#include "lockdep.c"
1920
#include "mutex.c"
2021
#include "page.c"
2122
#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
@@ -198,3 +198,46 @@ pub(crate) fn caller_lock_class() -> (LockClassKey, &'static CStr) {
198198
}
199199
}
200200
}
201+
202+
pub(crate) struct LockdepMap(Opaque<bindings::lockdep_map>);
203+
pub(crate) struct LockdepGuard<'a>(&'a LockdepMap);
204+
205+
#[allow(dead_code)]
206+
impl LockdepMap {
207+
#[track_caller]
208+
pub(crate) fn new() -> Self {
209+
let map = Opaque::uninit();
210+
let (key, name) = caller_lock_class();
211+
212+
// SAFETY: Just calling the C API
213+
unsafe {
214+
bindings::lockdep_init_map_type(
215+
map.get(),
216+
name.as_char_ptr(),
217+
key.as_ptr(),
218+
0,
219+
bindings::lockdep_wait_type_LD_WAIT_INV as _,
220+
bindings::lockdep_wait_type_LD_WAIT_INV as _,
221+
bindings::lockdep_lock_type_LD_LOCK_NORMAL as _,
222+
)
223+
};
224+
225+
LockdepMap(map)
226+
}
227+
228+
#[inline(always)]
229+
pub(crate) fn lock(&self) -> LockdepGuard<'_> {
230+
// SAFETY: Just calling the C API
231+
unsafe { bindings::lock_acquire_ret(self.0.get(), 0, 0, 1, 1, core::ptr::null_mut()) };
232+
233+
LockdepGuard(self)
234+
}
235+
}
236+
237+
impl<'a> Drop for LockdepGuard<'a> {
238+
#[inline(always)]
239+
fn drop(&mut self) {
240+
// SAFETY: Just calling the C API
241+
unsafe { bindings::lock_release_ret(self.0 .0.get()) };
242+
}
243+
}

0 commit comments

Comments
 (0)