Skip to content

Commit dea769c

Browse files
wedsonafdakr
authored andcommitted
rust: add rcu abstraction
Add a simple abstraction to guard critical code sections with an rcu read lock. Co-developed-by: Andreas Hindborg <[email protected]> Signed-off-by: Andreas Hindborg <[email protected]> Signed-off-by: Wedson Almeida Filho <[email protected]> Signed-off-by: Danilo Krummrich <[email protected]>
1 parent f5243a1 commit dea769c

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed

rust/helpers.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <linux/err.h>
2828
#include <linux/errname.h>
2929
#include <linux/mutex.h>
30+
#include <linux/rcupdate.h>
3031
#include <linux/refcount.h>
3132
#include <linux/sched/signal.h>
3233
#include <linux/slab.h>
@@ -166,6 +167,20 @@ rust_helper_krealloc(const void *objp, size_t new_size, gfp_t flags)
166167
}
167168
EXPORT_SYMBOL_GPL(rust_helper_krealloc);
168169

170+
/* rcu */
171+
void rust_helper_rcu_read_lock(void)
172+
{
173+
rcu_read_lock();
174+
}
175+
EXPORT_SYMBOL_GPL(rust_helper_rcu_read_lock);
176+
177+
void rust_helper_rcu_read_unlock(void)
178+
{
179+
rcu_read_unlock();
180+
}
181+
EXPORT_SYMBOL_GPL(rust_helper_rcu_read_unlock);
182+
/* end rcu */
183+
169184
/*
170185
* `bindgen` binds the C `size_t` type as the Rust `usize` type, so we can
171186
* use it in contexts where Rust expects a `usize` like slice (array) indices.

rust/kernel/sync.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ mod arc;
1111
mod condvar;
1212
pub mod lock;
1313
mod locked_by;
14+
pub mod rcu;
1415

1516
pub use arc::{Arc, ArcBorrow, UniqueArc};
1617
pub use condvar::{new_condvar, CondVar, CondVarTimeoutResult};

rust/kernel/sync/rcu.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! RCU support.
4+
//!
5+
//! C header: [`include/linux/rcupdate.h`](srctree/include/linux/rcupdate.h)
6+
7+
use crate::bindings;
8+
use core::marker::PhantomData;
9+
10+
/// Evidence that the RCU read side lock is held on the current thread/CPU.
11+
///
12+
/// The type is explicitly not `Send` because this property is per-thread/CPU.
13+
///
14+
/// # Invariants
15+
///
16+
/// The RCU read side lock is actually held while instances of this guard exist.
17+
pub struct Guard {
18+
_not_send: PhantomData<*mut ()>,
19+
}
20+
21+
impl Guard {
22+
/// Acquires the RCU read side lock and returns a guard.
23+
pub fn new() -> Self {
24+
// SAFETY: An FFI call with no additional requirements.
25+
unsafe { bindings::rcu_read_lock() };
26+
// INVARIANT: The RCU read side lock was just acquired above.
27+
Self {
28+
_not_send: PhantomData,
29+
}
30+
}
31+
32+
/// Explicitly releases the RCU read side lock.
33+
pub fn unlock(self) {}
34+
}
35+
36+
impl Default for Guard {
37+
fn default() -> Self {
38+
Self::new()
39+
}
40+
}
41+
42+
impl Drop for Guard {
43+
fn drop(&mut self) {
44+
// SAFETY: By the type invariants, the rcu read side is locked, so it is ok to unlock it.
45+
unsafe { bindings::rcu_read_unlock() };
46+
}
47+
}
48+
49+
/// Acquires the RCU read side lock.
50+
pub fn read_lock() -> Guard {
51+
Guard::new()
52+
}

0 commit comments

Comments
 (0)