Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rust: pin-init: examples, tests: add conditional compilation in order to compile under any feature combination

In the CI, all examples & tests should be run under all feature
combinations. Currently several examples & tests use `std` without
conditionally enabling it. Thus make them all compile under any feature
combination by conditionally disabling the code that uses e.g. `std`.

Link: https://github.com/Rust-for-Linux/pin-init/pull/50/commits/fdfb70efddbc711b4543c850ee38a2f5a8d17cb6
Link: https://lore.kernel.org/all/20250523125424.192843-2-lossin@kernel.org
Signed-off-by: Benno Lossin <lossin@kernel.org>

authored by

Benno Lossin and committed by
Benno Lossin
58cebd68 e832374c

+121 -90
+15 -11
rust/pin-init/examples/big_struct_in_place.rs
··· 4 4 5 5 // Struct with size over 1GiB 6 6 #[derive(Debug)] 7 + #[allow(dead_code)] 7 8 pub struct BigStruct { 8 9 buf: [u8; 1024 * 1024 * 1024], 9 10 a: u64, ··· 26 25 } 27 26 28 27 fn main() { 29 - // we want to initialize the struct in-place, otherwise we would get a stackoverflow 30 - let buf: Box<BigStruct> = Box::init(init!(BigStruct { 31 - buf <- zeroed(), 32 - a: 7, 33 - b: 186, 34 - c: 7789, 35 - d: 34, 36 - managed_buf <- ManagedBuf::new(), 37 - })) 38 - .unwrap(); 39 - println!("{}", core::mem::size_of_val(&*buf)); 28 + #[cfg(any(feature = "std", feature = "alloc"))] 29 + { 30 + // we want to initialize the struct in-place, otherwise we would get a stackoverflow 31 + let buf: Box<BigStruct> = Box::init(init!(BigStruct { 32 + buf <- zeroed(), 33 + a: 7, 34 + b: 186, 35 + c: 7789, 36 + d: 34, 37 + managed_buf <- ManagedBuf::new(), 38 + })) 39 + .unwrap(); 40 + println!("{}", core::mem::size_of_val(&*buf)); 41 + } 40 42 }
+9 -1
rust/pin-init/examples/linked_list.rs
··· 14 14 15 15 use pin_init::*; 16 16 17 - #[expect(unused_attributes)] 17 + #[allow(unused_attributes)] 18 18 mod error; 19 + #[allow(unused_imports)] 19 20 use error::Error; 20 21 21 22 #[pin_data(PinnedDrop)] ··· 40 39 } 41 40 42 41 #[inline] 42 + #[allow(dead_code)] 43 43 pub fn insert_next(list: &ListHead) -> impl PinInit<Self, Infallible> + '_ { 44 44 try_pin_init!(&this in Self { 45 45 prev: list.next.prev().replace(unsafe { Link::new_unchecked(this)}), ··· 114 112 } 115 113 116 114 #[inline] 115 + #[allow(dead_code)] 117 116 fn prev(&self) -> &Link { 118 117 unsafe { &(*self.0.get().as_ptr()).prev } 119 118 } ··· 141 138 } 142 139 143 140 #[allow(dead_code)] 141 + #[cfg(not(any(feature = "std", feature = "alloc")))] 142 + fn main() {} 143 + 144 + #[allow(dead_code)] 144 145 #[cfg_attr(test, test)] 146 + #[cfg(any(feature = "std", feature = "alloc"))] 145 147 fn main() -> Result<(), Error> { 146 148 let a = Box::pin_init(ListHead::new())?; 147 149 stack_pin_init!(let b = ListHead::insert_next(&a));
+56 -41
rust/pin-init/examples/mutex.rs
··· 12 12 pin::Pin, 13 13 sync::atomic::{AtomicBool, Ordering}, 14 14 }; 15 + #[cfg(feature = "std")] 15 16 use std::{ 16 17 sync::Arc, 17 - thread::{self, park, sleep, Builder, Thread}, 18 + thread::{self, sleep, Builder, Thread}, 18 19 time::Duration, 19 20 }; 20 21 21 22 use pin_init::*; 22 - #[expect(unused_attributes)] 23 + #[allow(unused_attributes)] 23 24 #[path = "./linked_list.rs"] 24 25 pub mod linked_list; 25 26 use linked_list::*; ··· 37 36 .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) 38 37 .is_err() 39 38 { 39 + #[cfg(feature = "std")] 40 40 while self.inner.load(Ordering::Relaxed) { 41 41 thread::yield_now(); 42 42 } ··· 96 94 // println!("wait list length: {}", self.wait_list.size()); 97 95 while self.locked.get() { 98 96 drop(sguard); 99 - park(); 97 + #[cfg(feature = "std")] 98 + thread::park(); 100 99 sguard = self.spin_lock.acquire(); 101 100 } 102 101 // This does have an effect, as the ListHead inside wait_entry implements Drop! ··· 134 131 let sguard = self.mtx.spin_lock.acquire(); 135 132 self.mtx.locked.set(false); 136 133 if let Some(list_field) = self.mtx.wait_list.next() { 137 - let wait_entry = list_field.as_ptr().cast::<WaitEntry>(); 138 - unsafe { (*wait_entry).thread.unpark() }; 134 + let _wait_entry = list_field.as_ptr().cast::<WaitEntry>(); 135 + #[cfg(feature = "std")] 136 + unsafe { 137 + (*_wait_entry).thread.unpark() 138 + }; 139 139 } 140 140 drop(sguard); 141 141 } ··· 165 159 struct WaitEntry { 166 160 #[pin] 167 161 wait_list: ListHead, 162 + #[cfg(feature = "std")] 168 163 thread: Thread, 169 164 } 170 165 171 166 impl WaitEntry { 172 167 #[inline] 173 168 fn insert_new(list: &ListHead) -> impl PinInit<Self> + '_ { 174 - pin_init!(Self { 175 - thread: thread::current(), 176 - wait_list <- ListHead::insert_prev(list), 177 - }) 169 + #[cfg(feature = "std")] 170 + { 171 + pin_init!(Self { 172 + thread: thread::current(), 173 + wait_list <- ListHead::insert_prev(list), 174 + }) 175 + } 176 + #[cfg(not(feature = "std"))] 177 + { 178 + pin_init!(Self { 179 + wait_list <- ListHead::insert_prev(list), 180 + }) 181 + } 178 182 } 179 183 } 180 184 181 - #[cfg(not(any(feature = "std", feature = "alloc")))] 182 - fn main() {} 183 - 184 - #[allow(dead_code)] 185 185 #[cfg_attr(test, test)] 186 - #[cfg(any(feature = "std", feature = "alloc"))] 186 + #[allow(dead_code)] 187 187 fn main() { 188 - let mtx: Pin<Arc<CMutex<usize>>> = Arc::pin_init(CMutex::new(0)).unwrap(); 189 - let mut handles = vec![]; 190 - let thread_count = 20; 191 - let workload = if cfg!(miri) { 100 } else { 1_000 }; 192 - for i in 0..thread_count { 193 - let mtx = mtx.clone(); 194 - handles.push( 195 - Builder::new() 196 - .name(format!("worker #{i}")) 197 - .spawn(move || { 198 - for _ in 0..workload { 199 - *mtx.lock() += 1; 200 - } 201 - println!("{i} halfway"); 202 - sleep(Duration::from_millis((i as u64) * 10)); 203 - for _ in 0..workload { 204 - *mtx.lock() += 1; 205 - } 206 - println!("{i} finished"); 207 - }) 208 - .expect("should not fail"), 209 - ); 188 + #[cfg(feature = "std")] 189 + { 190 + let mtx: Pin<Arc<CMutex<usize>>> = Arc::pin_init(CMutex::new(0)).unwrap(); 191 + let mut handles = vec![]; 192 + let thread_count = 20; 193 + let workload = if cfg!(miri) { 100 } else { 1_000 }; 194 + for i in 0..thread_count { 195 + let mtx = mtx.clone(); 196 + handles.push( 197 + Builder::new() 198 + .name(format!("worker #{i}")) 199 + .spawn(move || { 200 + for _ in 0..workload { 201 + *mtx.lock() += 1; 202 + } 203 + println!("{i} halfway"); 204 + sleep(Duration::from_millis((i as u64) * 10)); 205 + for _ in 0..workload { 206 + *mtx.lock() += 1; 207 + } 208 + println!("{i} finished"); 209 + }) 210 + .expect("should not fail"), 211 + ); 212 + } 213 + for h in handles { 214 + h.join().expect("thread panicked"); 215 + } 216 + println!("{:?}", &*mtx.lock()); 217 + assert_eq!(*mtx.lock(), workload * thread_count * 2); 210 218 } 211 - for h in handles { 212 - h.join().expect("thread panicked"); 213 - } 214 - println!("{:?}", &*mtx.lock()); 215 - assert_eq!(*mtx.lock(), workload * thread_count * 2); 216 219 }
+3
rust/pin-init/examples/pthread_mutex.rs
··· 44 44 pub enum Error { 45 45 #[allow(dead_code)] 46 46 IO(std::io::Error), 47 + #[allow(dead_code)] 47 48 Alloc, 48 49 } 49 50 ··· 62 61 } 63 62 64 63 impl<T> PThreadMutex<T> { 64 + #[allow(dead_code)] 65 65 pub fn new(data: T) -> impl PinInit<Self, Error> { 66 66 fn init_raw() -> impl PinInit<UnsafeCell<libc::pthread_mutex_t>, Error> { 67 67 let init = |slot: *mut UnsafeCell<libc::pthread_mutex_t>| { ··· 105 103 }? Error) 106 104 } 107 105 106 + #[allow(dead_code)] 108 107 pub fn lock(&self) -> PThreadMutexGuard<'_, T> { 109 108 // SAFETY: raw is always initialized 110 109 unsafe { libc::pthread_mutex_lock(self.raw.get()) };
+38 -37
rust/pin-init/examples/static_init.rs
··· 3 3 #![allow(clippy::undocumented_unsafe_blocks)] 4 4 #![cfg_attr(feature = "alloc", feature(allocator_api))] 5 5 #![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))] 6 + #![allow(unused_imports)] 6 7 7 8 use core::{ 8 9 cell::{Cell, UnsafeCell}, ··· 13 12 time::Duration, 14 13 }; 15 14 use pin_init::*; 15 + #[cfg(feature = "std")] 16 16 use std::{ 17 17 sync::Arc, 18 18 thread::{sleep, Builder}, 19 19 }; 20 20 21 - #[expect(unused_attributes)] 21 + #[allow(unused_attributes)] 22 22 mod mutex; 23 23 use mutex::*; 24 24 ··· 84 82 85 83 pub static COUNT: StaticInit<CMutex<usize>, CountInit> = StaticInit::new(CountInit); 86 84 87 - #[cfg(not(any(feature = "std", feature = "alloc")))] 88 - fn main() {} 89 - 90 - #[cfg(any(feature = "std", feature = "alloc"))] 91 85 fn main() { 92 - let mtx: Pin<Arc<CMutex<usize>>> = Arc::pin_init(CMutex::new(0)).unwrap(); 93 - let mut handles = vec![]; 94 - let thread_count = 20; 95 - let workload = 1_000; 96 - for i in 0..thread_count { 97 - let mtx = mtx.clone(); 98 - handles.push( 99 - Builder::new() 100 - .name(format!("worker #{i}")) 101 - .spawn(move || { 102 - for _ in 0..workload { 103 - *COUNT.lock() += 1; 104 - std::thread::sleep(std::time::Duration::from_millis(10)); 105 - *mtx.lock() += 1; 106 - std::thread::sleep(std::time::Duration::from_millis(10)); 107 - *COUNT.lock() += 1; 108 - } 109 - println!("{i} halfway"); 110 - sleep(Duration::from_millis((i as u64) * 10)); 111 - for _ in 0..workload { 112 - std::thread::sleep(std::time::Duration::from_millis(10)); 113 - *mtx.lock() += 1; 114 - } 115 - println!("{i} finished"); 116 - }) 117 - .expect("should not fail"), 118 - ); 86 + #[cfg(feature = "std")] 87 + { 88 + let mtx: Pin<Arc<CMutex<usize>>> = Arc::pin_init(CMutex::new(0)).unwrap(); 89 + let mut handles = vec![]; 90 + let thread_count = 20; 91 + let workload = 1_000; 92 + for i in 0..thread_count { 93 + let mtx = mtx.clone(); 94 + handles.push( 95 + Builder::new() 96 + .name(format!("worker #{i}")) 97 + .spawn(move || { 98 + for _ in 0..workload { 99 + *COUNT.lock() += 1; 100 + std::thread::sleep(std::time::Duration::from_millis(10)); 101 + *mtx.lock() += 1; 102 + std::thread::sleep(std::time::Duration::from_millis(10)); 103 + *COUNT.lock() += 1; 104 + } 105 + println!("{i} halfway"); 106 + sleep(Duration::from_millis((i as u64) * 10)); 107 + for _ in 0..workload { 108 + std::thread::sleep(std::time::Duration::from_millis(10)); 109 + *mtx.lock() += 1; 110 + } 111 + println!("{i} finished"); 112 + }) 113 + .expect("should not fail"), 114 + ); 115 + } 116 + for h in handles { 117 + h.join().expect("thread panicked"); 118 + } 119 + println!("{:?}, {:?}", &*mtx.lock(), &*COUNT.lock()); 120 + assert_eq!(*mtx.lock(), workload * thread_count * 2); 119 121 } 120 - for h in handles { 121 - h.join().expect("thread panicked"); 122 - } 123 - println!("{:?}, {:?}", &*mtx.lock(), &*COUNT.lock()); 124 - assert_eq!(*mtx.lock(), workload * thread_count * 2); 125 122 }