Skip to content

Commit 883e433

Browse files
committed
rust: add the container_of macro
This is the Rust version of the macro with the same name in C. It produces a raw pointer to an outer type from a pointer to an inner field. Signed-off-by: Wedson Almeida Filho <[email protected]>
1 parent da1a2b6 commit 883e433

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

rust/kernel/lib.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#![feature(coerce_unsized)]
1717
#![feature(dispatch_from_dyn)]
1818
#![feature(new_uninit)]
19+
#![feature(offset_of)]
1920
#![feature(receiver_trait)]
2021
#![feature(return_position_impl_trait_in_trait)]
2122
#![feature(unsize)]
@@ -113,6 +114,38 @@ impl ThisModule {
113114
}
114115
}
115116

117+
/// Produces a pointer to an object from a pointer to one of its fields.
118+
///
119+
/// # Safety
120+
///
121+
/// Callers must ensure that the pointer to the field is in fact a pointer to the specified field,
122+
/// as opposed to a pointer to another object of the same type. If this condition is not met,
123+
/// any dereference of the resulting pointer is UB.
124+
///
125+
/// # Examples
126+
///
127+
/// ```
128+
/// # use kernel::container_of;
129+
/// struct Test {
130+
/// a: u64,
131+
/// b: u32,
132+
/// }
133+
///
134+
/// let test = Test { a: 10, b: 20 };
135+
/// let b_ptr = &test.b;
136+
/// let test_alias = container_of!(b_ptr, Test, b);
137+
/// assert!(core::ptr::eq(&test, test_alias));
138+
/// ```
139+
#[macro_export]
140+
macro_rules! container_of {
141+
($ptr:expr, $type:ty, $($f:tt)*) => {{
142+
let ptr = $ptr as *const _ as *const u8;
143+
let offset = ::core::mem::offset_of!($type, $($f)*);
144+
$crate::build_assert!(offset <= isize::MAX as usize);
145+
ptr.wrapping_sub(offset) as *const $type
146+
}}
147+
}
148+
116149
#[cfg(not(any(testlib, test)))]
117150
#[panic_handler]
118151
fn panic(info: &core::panic::PanicInfo<'_>) -> ! {

scripts/Makefile.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ $(obj)/%.lst: $(src)/%.c FORCE
262262
# Compile Rust sources (.rs)
263263
# ---------------------------------------------------------------------------
264264

265-
rust_allowed_features := new_uninit,return_position_impl_trait_in_trait
265+
rust_allowed_features := new_uninit,return_position_impl_trait_in_trait,offset_of
266266

267267
# `--out-dir` is required to avoid temporaries being created by `rustc` in the
268268
# current working directory, which may be not accessible in the out-of-tree

0 commit comments

Comments
 (0)