1 /* 2 * Copyright (c) 2024 Google Inc. All rights reserved 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files 6 * (the "Software"), to deal in the Software without restriction, 7 * including without limitation the rights to use, copy, modify, merge, 8 * publish, distribute, sublicense, and/or sell copies of the Software, 9 * and to permit persons to whom the Software is furnished to do so, 10 * subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24 /// Helper macro for container_of and container_of_mut. Exported so it can be 25 /// used by those macros and not meant to be used directly. 26 #[macro_export] 27 macro_rules! container_of_const_or_mut { 28 ($ptr:ident, $T:ty, $m:ident, $const_or_mut:ident) => {{ 29 // SAFETY: The caller must ensure that $ptr is a pointer to the $m 30 // field in an object of type $T. This means that $ptr came from 31 // addr_of!((*original_ptr).$m) so subtracting the offset of $m from 32 // $ptr will restore the original pointer. 33 let original_ptr = (($ptr).byte_sub(core::mem::offset_of!($T, $m)) as *$const_or_mut $T); 34 35 // Check that type of $ptr matches type of $T.$m. This detects a 36 // subclass of bugs at compile time where the wrong field or pointer 37 // is passed and two types does not match. 38 // 39 // SAFETY: This should not generate any code. 40 let _always_true = core::ptr::addr_of!((*original_ptr).$m) == $ptr; 41 42 original_ptr 43 }}; 44 } 45 46 /// Get the pointer to a struct from a pointer to an embedded field. 47 /// Matches the C containerof define in include/shared/lk/macros.h. 48 /// Const version. 49 #[macro_export] 50 macro_rules! container_of { 51 ($ptr:ident, $T:ty, $m:ident) => { 52 $crate::container_of_const_or_mut!($ptr, $T, $m, const) 53 }; 54 } 55 56 /// Get the pointer to a struct from a pointer to an embedded field. 57 /// Matches the C containerof define in include/shared/lk/macros.h. 58 /// Mutable version. 59 /// 60 /// To convert a pointer received by C code to a reference to a wrapping 61 /// rust struct a helper function could be used like so: 62 /// struct A {} 63 /// struct B { 64 /// a: A, 65 /// } 66 /// /// # SAFETY 67 /// /// 68 /// /// ptr_a must point to the a field in a B struct 69 /// unsafe fn ptr_a_to_ref_b<'a>(ptr_a: *mut A) -> &'a mut B { 70 /// unsafe { &mut *container_of_mut!(ptr_a, B, a) } 71 /// } 72 #[macro_export] 73 macro_rules! container_of_mut { 74 ($ptr:ident, $T:ty, $m:ident) => { 75 $crate::container_of_const_or_mut!($ptr, $T, $m, mut) 76 }; 77 } 78