Skip to content

Commit

Permalink
rust: sync: Add LockdepMap abstraction
Browse files Browse the repository at this point in the history
This allows Rust code to explicitly integrate types with lockdep.

Signed-off-by: Asahi Lina <[email protected]>
  • Loading branch information
asahilina committed May 28, 2023
1 parent c669504 commit a6f492f
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 0 deletions.
1 change: 1 addition & 0 deletions rust/bindings/bindings_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <linux/iosys-map.h>
#include <linux/io-pgtable.h>
#include <linux/ktime.h>
#include <linux/lockdep.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
Expand Down
16 changes: 16 additions & 0 deletions rust/helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/errname.h>
#include <linux/instruction_pointer.h>
#include <linux/lockdep.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
Expand Down Expand Up @@ -159,6 +161,20 @@ u64 rust_helper_siphash(const void *data, size_t len,
}
EXPORT_SYMBOL_GPL(rust_helper_siphash);

void rust_helper_lock_acquire_ret(struct lockdep_map *lock, unsigned int subclass,
int trylock, int read, int check,
struct lockdep_map *nest_lock)
{
lock_acquire(lock, subclass, trylock, read, check, nest_lock, _RET_IP_);
}
EXPORT_SYMBOL_GPL(rust_helper_lock_acquire_ret);

void rust_helper_lock_release_ret(struct lockdep_map *lock)
{
lock_release(lock, _RET_IP_);
}
EXPORT_SYMBOL_GPL(rust_helper_lock_release_ret);

void rust_helper_xa_init_flags(struct xarray *xa, gfp_t flags)
{
xa_init_flags(xa, flags);
Expand Down
40 changes: 40 additions & 0 deletions rust/kernel/sync/lockdep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,43 @@ pub(crate) fn caller_lock_class() -> (LockClassKey, &'static CStr) {
}
}
}

pub(crate) struct LockdepMap(Opaque<bindings::lockdep_map>);
pub(crate) struct LockdepGuard<'a>(&'a LockdepMap);

#[allow(dead_code)]
impl LockdepMap {
#[track_caller]
pub(crate) fn new() -> Self {
let map = Opaque::uninit();
let (key, name) = caller_lock_class();

unsafe {
bindings::lockdep_init_map_type(
map.get(),
name.as_char_ptr(),
key.as_ptr(),
0,
bindings::lockdep_wait_type_LD_WAIT_INV as _,
bindings::lockdep_wait_type_LD_WAIT_INV as _,
bindings::lockdep_lock_type_LD_LOCK_NORMAL as _,
)
};

LockdepMap(map)
}

#[inline(always)]
pub(crate) fn lock(&self) -> LockdepGuard<'_> {
unsafe { bindings::lock_acquire_ret(self.0.get(), 0, 0, 1, 1, core::ptr::null_mut()) };

LockdepGuard(self)
}
}

impl<'a> Drop for LockdepGuard<'a> {
#[inline(always)]
fn drop(&mut self) {
unsafe { bindings::lock_release_ret(self.0 .0.get()) };
}
}

0 comments on commit a6f492f

Please sign in to comment.