Skip to content

Commit a1265d6

Browse files
wedsonafDanilo Krummrich
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 c4ec546 commit a1265d6

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
@@ -29,6 +29,7 @@
2929
#include <linux/gfp.h>
3030
#include <linux/highmem.h>
3131
#include <linux/mutex.h>
32+
#include <linux/rcupdate.h>
3233
#include <linux/refcount.h>
3334
#include <linux/sched/signal.h>
3435
#include <linux/slab.h>
@@ -200,6 +201,20 @@ rust_helper_krealloc(const void *objp, size_t new_size, gfp_t flags)
200201
}
201202
EXPORT_SYMBOL_GPL(rust_helper_krealloc);
202203

204+
/* rcu */
205+
void rust_helper_rcu_read_lock(void)
206+
{
207+
rcu_read_lock();
208+
}
209+
EXPORT_SYMBOL_GPL(rust_helper_rcu_read_lock);
210+
211+
void rust_helper_rcu_read_unlock(void)
212+
{
213+
rcu_read_unlock();
214+
}
215+
EXPORT_SYMBOL_GPL(rust_helper_rcu_read_unlock);
216+
/* end rcu */
217+
203218
/*
204219
* `bindgen` binds the C `size_t` type as the Rust `usize` type, so we can
205220
* 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)