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: change examples to the user-space version

Replace the examples in the documentation by the ones from the
user-space version and introduce the standalone examples from the
user-space version such as the `CMutex<T>` type.

The `CMutex<T>` example from the pinned-init repository [1] is used in
several documentation examples in the user-space version instead of the
kernel `Mutex<T>` type (as it's not available). In order to split off
the pin-init crate, all examples need to be free of kernel-specific
types.

Link: https://github.com/rust-for-Linux/pinned-init [1]
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Fiona Behrens <me@kloenk.dev>
Tested-by: Andreas Hindborg <a.hindborg@kernel.org>
Link: https://lore.kernel.org/r/20250308110339.2997091-6-benno.lossin@proton.me
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>

authored by

Benno Lossin and committed by
Miguel Ojeda
84837cf6 4b11798e

+915 -186
+39
rust/pin-init/examples/big_struct_in_place.rs
··· 1 + // SPDX-License-Identifier: Apache-2.0 OR MIT 2 + 3 + use pin_init::*; 4 + 5 + // Struct with size over 1GiB 6 + #[derive(Debug)] 7 + pub struct BigStruct { 8 + buf: [u8; 1024 * 1024 * 1024], 9 + a: u64, 10 + b: u64, 11 + c: u64, 12 + d: u64, 13 + managed_buf: ManagedBuf, 14 + } 15 + 16 + #[derive(Debug)] 17 + pub struct ManagedBuf { 18 + buf: [u8; 1024 * 1024], 19 + } 20 + 21 + impl ManagedBuf { 22 + pub fn new() -> impl Init<Self> { 23 + init!(ManagedBuf { buf <- zeroed() }) 24 + } 25 + } 26 + 27 + fn main() { 28 + // we want to initialize the struct in-place, otherwise we would get a stackoverflow 29 + let buf: Box<BigStruct> = Box::init(init!(BigStruct { 30 + buf <- zeroed(), 31 + a: 7, 32 + b: 186, 33 + c: 7789, 34 + d: 34, 35 + managed_buf <- ManagedBuf::new(), 36 + })) 37 + .unwrap(); 38 + println!("{}", core::mem::size_of_val(&*buf)); 39 + }
+27
rust/pin-init/examples/error.rs
··· 1 + // SPDX-License-Identifier: Apache-2.0 OR MIT 2 + 3 + #![cfg_attr(feature = "alloc", feature(allocator_api))] 4 + 5 + use core::convert::Infallible; 6 + 7 + #[cfg(feature = "alloc")] 8 + use std::alloc::AllocError; 9 + 10 + #[derive(Debug)] 11 + pub struct Error; 12 + 13 + impl From<Infallible> for Error { 14 + fn from(e: Infallible) -> Self { 15 + match e {} 16 + } 17 + } 18 + 19 + #[cfg(feature = "alloc")] 20 + impl From<AllocError> for Error { 21 + fn from(_: AllocError) -> Self { 22 + Self 23 + } 24 + } 25 + 26 + #[allow(dead_code)] 27 + fn main() {}
+161
rust/pin-init/examples/linked_list.rs
··· 1 + // SPDX-License-Identifier: Apache-2.0 OR MIT 2 + 3 + #![allow(clippy::undocumented_unsafe_blocks)] 4 + #![cfg_attr(feature = "alloc", feature(allocator_api))] 5 + 6 + use core::{ 7 + cell::Cell, 8 + convert::Infallible, 9 + marker::PhantomPinned, 10 + pin::Pin, 11 + ptr::{self, NonNull}, 12 + }; 13 + 14 + use pin_init::*; 15 + 16 + #[expect(unused_attributes)] 17 + mod error; 18 + use error::Error; 19 + 20 + #[pin_data(PinnedDrop)] 21 + #[repr(C)] 22 + #[derive(Debug)] 23 + pub struct ListHead { 24 + next: Link, 25 + prev: Link, 26 + #[pin] 27 + pin: PhantomPinned, 28 + } 29 + 30 + impl ListHead { 31 + #[inline] 32 + pub fn new() -> impl PinInit<Self, Infallible> { 33 + try_pin_init!(&this in Self { 34 + next: unsafe { Link::new_unchecked(this) }, 35 + prev: unsafe { Link::new_unchecked(this) }, 36 + pin: PhantomPinned, 37 + }? Infallible) 38 + } 39 + 40 + #[inline] 41 + pub fn insert_next(list: &ListHead) -> impl PinInit<Self, Infallible> + '_ { 42 + try_pin_init!(&this in Self { 43 + prev: list.next.prev().replace(unsafe { Link::new_unchecked(this)}), 44 + next: list.next.replace(unsafe { Link::new_unchecked(this)}), 45 + pin: PhantomPinned, 46 + }? Infallible) 47 + } 48 + 49 + #[inline] 50 + pub fn insert_prev(list: &ListHead) -> impl PinInit<Self, Infallible> + '_ { 51 + try_pin_init!(&this in Self { 52 + next: list.prev.next().replace(unsafe { Link::new_unchecked(this)}), 53 + prev: list.prev.replace(unsafe { Link::new_unchecked(this)}), 54 + pin: PhantomPinned, 55 + }? Infallible) 56 + } 57 + 58 + #[inline] 59 + pub fn next(&self) -> Option<NonNull<Self>> { 60 + if ptr::eq(self.next.as_ptr(), self) { 61 + None 62 + } else { 63 + Some(unsafe { NonNull::new_unchecked(self.next.as_ptr() as *mut Self) }) 64 + } 65 + } 66 + 67 + #[allow(dead_code)] 68 + pub fn size(&self) -> usize { 69 + let mut size = 1; 70 + let mut cur = self.next.clone(); 71 + while !ptr::eq(self, cur.cur()) { 72 + cur = cur.next().clone(); 73 + size += 1; 74 + } 75 + size 76 + } 77 + } 78 + 79 + #[pinned_drop] 80 + impl PinnedDrop for ListHead { 81 + //#[inline] 82 + fn drop(self: Pin<&mut Self>) { 83 + if !ptr::eq(self.next.as_ptr(), &*self) { 84 + let next = unsafe { &*self.next.as_ptr() }; 85 + let prev = unsafe { &*self.prev.as_ptr() }; 86 + next.prev.set(&self.prev); 87 + prev.next.set(&self.next); 88 + } 89 + } 90 + } 91 + 92 + #[repr(transparent)] 93 + #[derive(Clone, Debug)] 94 + struct Link(Cell<NonNull<ListHead>>); 95 + 96 + impl Link { 97 + /// # Safety 98 + /// 99 + /// The contents of the pointer should form a consistent circular 100 + /// linked list; for example, a "next" link should be pointed back 101 + /// by the target `ListHead`'s "prev" link and a "prev" link should be 102 + /// pointed back by the target `ListHead`'s "next" link. 103 + #[inline] 104 + unsafe fn new_unchecked(ptr: NonNull<ListHead>) -> Self { 105 + Self(Cell::new(ptr)) 106 + } 107 + 108 + #[inline] 109 + fn next(&self) -> &Link { 110 + unsafe { &(*self.0.get().as_ptr()).next } 111 + } 112 + 113 + #[inline] 114 + fn prev(&self) -> &Link { 115 + unsafe { &(*self.0.get().as_ptr()).prev } 116 + } 117 + 118 + #[allow(dead_code)] 119 + fn cur(&self) -> &ListHead { 120 + unsafe { &*self.0.get().as_ptr() } 121 + } 122 + 123 + #[inline] 124 + fn replace(&self, other: Link) -> Link { 125 + unsafe { Link::new_unchecked(self.0.replace(other.0.get())) } 126 + } 127 + 128 + #[inline] 129 + fn as_ptr(&self) -> *const ListHead { 130 + self.0.get().as_ptr() 131 + } 132 + 133 + #[inline] 134 + fn set(&self, val: &Link) { 135 + self.0.set(val.0.get()); 136 + } 137 + } 138 + 139 + #[allow(dead_code)] 140 + #[cfg_attr(test, test)] 141 + fn main() -> Result<(), Error> { 142 + let a = Box::pin_init(ListHead::new())?; 143 + stack_pin_init!(let b = ListHead::insert_next(&a)); 144 + stack_pin_init!(let c = ListHead::insert_next(&a)); 145 + stack_pin_init!(let d = ListHead::insert_next(&b)); 146 + let e = Box::pin_init(ListHead::insert_next(&b))?; 147 + println!("a ({a:p}): {a:?}"); 148 + println!("b ({b:p}): {b:?}"); 149 + println!("c ({c:p}): {c:?}"); 150 + println!("d ({d:p}): {d:?}"); 151 + println!("e ({e:p}): {e:?}"); 152 + let mut inspect = &*a; 153 + while let Some(next) = inspect.next() { 154 + println!("({inspect:p}): {inspect:?}"); 155 + inspect = unsafe { &*next.as_ptr() }; 156 + if core::ptr::eq(inspect, &*a) { 157 + break; 158 + } 159 + } 160 + Ok(()) 161 + }
+209
rust/pin-init/examples/mutex.rs
··· 1 + // SPDX-License-Identifier: Apache-2.0 OR MIT 2 + 3 + #![allow(clippy::undocumented_unsafe_blocks)] 4 + #![cfg_attr(feature = "alloc", feature(allocator_api))] 5 + #![allow(clippy::missing_safety_doc)] 6 + 7 + use core::{ 8 + cell::{Cell, UnsafeCell}, 9 + marker::PhantomPinned, 10 + ops::{Deref, DerefMut}, 11 + pin::Pin, 12 + sync::atomic::{AtomicBool, Ordering}, 13 + }; 14 + use std::{ 15 + sync::Arc, 16 + thread::{self, park, sleep, Builder, Thread}, 17 + time::Duration, 18 + }; 19 + 20 + use pin_init::*; 21 + #[expect(unused_attributes)] 22 + #[path = "./linked_list.rs"] 23 + pub mod linked_list; 24 + use linked_list::*; 25 + 26 + pub struct SpinLock { 27 + inner: AtomicBool, 28 + } 29 + 30 + impl SpinLock { 31 + #[inline] 32 + pub fn acquire(&self) -> SpinLockGuard<'_> { 33 + while self 34 + .inner 35 + .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) 36 + .is_err() 37 + { 38 + while self.inner.load(Ordering::Relaxed) { 39 + thread::yield_now(); 40 + } 41 + } 42 + SpinLockGuard(self) 43 + } 44 + 45 + #[inline] 46 + #[allow(clippy::new_without_default)] 47 + pub const fn new() -> Self { 48 + Self { 49 + inner: AtomicBool::new(false), 50 + } 51 + } 52 + } 53 + 54 + pub struct SpinLockGuard<'a>(&'a SpinLock); 55 + 56 + impl Drop for SpinLockGuard<'_> { 57 + #[inline] 58 + fn drop(&mut self) { 59 + self.0.inner.store(false, Ordering::Release); 60 + } 61 + } 62 + 63 + #[pin_data] 64 + pub struct CMutex<T> { 65 + #[pin] 66 + wait_list: ListHead, 67 + spin_lock: SpinLock, 68 + locked: Cell<bool>, 69 + #[pin] 70 + data: UnsafeCell<T>, 71 + } 72 + 73 + impl<T> CMutex<T> { 74 + #[inline] 75 + pub fn new(val: impl PinInit<T>) -> impl PinInit<Self> { 76 + pin_init!(CMutex { 77 + wait_list <- ListHead::new(), 78 + spin_lock: SpinLock::new(), 79 + locked: Cell::new(false), 80 + data <- unsafe { 81 + pin_init_from_closure(|slot: *mut UnsafeCell<T>| { 82 + val.__pinned_init(slot.cast::<T>()) 83 + }) 84 + }, 85 + }) 86 + } 87 + 88 + #[inline] 89 + pub fn lock(&self) -> Pin<CMutexGuard<'_, T>> { 90 + let mut sguard = self.spin_lock.acquire(); 91 + if self.locked.get() { 92 + stack_pin_init!(let wait_entry = WaitEntry::insert_new(&self.wait_list)); 93 + // println!("wait list length: {}", self.wait_list.size()); 94 + while self.locked.get() { 95 + drop(sguard); 96 + park(); 97 + sguard = self.spin_lock.acquire(); 98 + } 99 + // This does have an effect, as the ListHead inside wait_entry implements Drop! 100 + #[expect(clippy::drop_non_drop)] 101 + drop(wait_entry); 102 + } 103 + self.locked.set(true); 104 + unsafe { 105 + Pin::new_unchecked(CMutexGuard { 106 + mtx: self, 107 + _pin: PhantomPinned, 108 + }) 109 + } 110 + } 111 + 112 + #[allow(dead_code)] 113 + pub fn get_data_mut(self: Pin<&mut Self>) -> &mut T { 114 + // SAFETY: we have an exclusive reference and thus nobody has access to data. 115 + unsafe { &mut *self.data.get() } 116 + } 117 + } 118 + 119 + unsafe impl<T: Send> Send for CMutex<T> {} 120 + unsafe impl<T: Send> Sync for CMutex<T> {} 121 + 122 + pub struct CMutexGuard<'a, T> { 123 + mtx: &'a CMutex<T>, 124 + _pin: PhantomPinned, 125 + } 126 + 127 + impl<T> Drop for CMutexGuard<'_, T> { 128 + #[inline] 129 + fn drop(&mut self) { 130 + let sguard = self.mtx.spin_lock.acquire(); 131 + self.mtx.locked.set(false); 132 + if let Some(list_field) = self.mtx.wait_list.next() { 133 + let wait_entry = list_field.as_ptr().cast::<WaitEntry>(); 134 + unsafe { (*wait_entry).thread.unpark() }; 135 + } 136 + drop(sguard); 137 + } 138 + } 139 + 140 + impl<T> Deref for CMutexGuard<'_, T> { 141 + type Target = T; 142 + 143 + #[inline] 144 + fn deref(&self) -> &Self::Target { 145 + unsafe { &*self.mtx.data.get() } 146 + } 147 + } 148 + 149 + impl<T> DerefMut for CMutexGuard<'_, T> { 150 + #[inline] 151 + fn deref_mut(&mut self) -> &mut Self::Target { 152 + unsafe { &mut *self.mtx.data.get() } 153 + } 154 + } 155 + 156 + #[pin_data] 157 + #[repr(C)] 158 + struct WaitEntry { 159 + #[pin] 160 + wait_list: ListHead, 161 + thread: Thread, 162 + } 163 + 164 + impl WaitEntry { 165 + #[inline] 166 + fn insert_new(list: &ListHead) -> impl PinInit<Self> + '_ { 167 + pin_init!(Self { 168 + thread: thread::current(), 169 + wait_list <- ListHead::insert_prev(list), 170 + }) 171 + } 172 + } 173 + 174 + #[cfg(not(any(feature = "std", feature = "alloc")))] 175 + fn main() {} 176 + 177 + #[allow(dead_code)] 178 + #[cfg_attr(test, test)] 179 + #[cfg(any(feature = "std", feature = "alloc"))] 180 + fn main() { 181 + let mtx: Pin<Arc<CMutex<usize>>> = Arc::pin_init(CMutex::new(0)).unwrap(); 182 + let mut handles = vec![]; 183 + let thread_count = 20; 184 + let workload = if cfg!(miri) { 100 } else { 1_000 }; 185 + for i in 0..thread_count { 186 + let mtx = mtx.clone(); 187 + handles.push( 188 + Builder::new() 189 + .name(format!("worker #{i}")) 190 + .spawn(move || { 191 + for _ in 0..workload { 192 + *mtx.lock() += 1; 193 + } 194 + println!("{i} halfway"); 195 + sleep(Duration::from_millis((i as u64) * 10)); 196 + for _ in 0..workload { 197 + *mtx.lock() += 1; 198 + } 199 + println!("{i} finished"); 200 + }) 201 + .expect("should not fail"), 202 + ); 203 + } 204 + for h in handles { 205 + h.join().expect("thread panicked"); 206 + } 207 + println!("{:?}", &*mtx.lock()); 208 + assert_eq!(*mtx.lock(), workload * thread_count * 2); 209 + }
+178
rust/pin-init/examples/pthread_mutex.rs
··· 1 + // SPDX-License-Identifier: Apache-2.0 OR MIT 2 + 3 + // inspired by https://github.com/nbdd0121/pin-init/blob/trunk/examples/pthread_mutex.rs 4 + #![allow(clippy::undocumented_unsafe_blocks)] 5 + #![cfg_attr(feature = "alloc", feature(allocator_api))] 6 + #[cfg(not(windows))] 7 + mod pthread_mtx { 8 + #[cfg(feature = "alloc")] 9 + use core::alloc::AllocError; 10 + use core::{ 11 + cell::UnsafeCell, 12 + marker::PhantomPinned, 13 + mem::MaybeUninit, 14 + ops::{Deref, DerefMut}, 15 + pin::Pin, 16 + }; 17 + use pin_init::*; 18 + use std::convert::Infallible; 19 + 20 + #[pin_data(PinnedDrop)] 21 + pub struct PThreadMutex<T> { 22 + #[pin] 23 + raw: UnsafeCell<libc::pthread_mutex_t>, 24 + data: UnsafeCell<T>, 25 + #[pin] 26 + pin: PhantomPinned, 27 + } 28 + 29 + unsafe impl<T: Send> Send for PThreadMutex<T> {} 30 + unsafe impl<T: Send> Sync for PThreadMutex<T> {} 31 + 32 + #[pinned_drop] 33 + impl<T> PinnedDrop for PThreadMutex<T> { 34 + fn drop(self: Pin<&mut Self>) { 35 + unsafe { 36 + libc::pthread_mutex_destroy(self.raw.get()); 37 + } 38 + } 39 + } 40 + 41 + #[derive(Debug)] 42 + pub enum Error { 43 + #[expect(dead_code)] 44 + IO(std::io::Error), 45 + Alloc, 46 + } 47 + 48 + impl From<Infallible> for Error { 49 + fn from(e: Infallible) -> Self { 50 + match e {} 51 + } 52 + } 53 + 54 + #[cfg(feature = "alloc")] 55 + impl From<AllocError> for Error { 56 + fn from(_: AllocError) -> Self { 57 + Self::Alloc 58 + } 59 + } 60 + 61 + impl<T> PThreadMutex<T> { 62 + pub fn new(data: T) -> impl PinInit<Self, Error> { 63 + fn init_raw() -> impl PinInit<UnsafeCell<libc::pthread_mutex_t>, Error> { 64 + let init = |slot: *mut UnsafeCell<libc::pthread_mutex_t>| { 65 + // we can cast, because `UnsafeCell` has the same layout as T. 66 + let slot: *mut libc::pthread_mutex_t = slot.cast(); 67 + let mut attr = MaybeUninit::uninit(); 68 + let attr = attr.as_mut_ptr(); 69 + // SAFETY: ptr is valid 70 + let ret = unsafe { libc::pthread_mutexattr_init(attr) }; 71 + if ret != 0 { 72 + return Err(Error::IO(std::io::Error::from_raw_os_error(ret))); 73 + } 74 + // SAFETY: attr is initialized 75 + let ret = unsafe { 76 + libc::pthread_mutexattr_settype(attr, libc::PTHREAD_MUTEX_NORMAL) 77 + }; 78 + if ret != 0 { 79 + // SAFETY: attr is initialized 80 + unsafe { libc::pthread_mutexattr_destroy(attr) }; 81 + return Err(Error::IO(std::io::Error::from_raw_os_error(ret))); 82 + } 83 + // SAFETY: slot is valid 84 + unsafe { slot.write(libc::PTHREAD_MUTEX_INITIALIZER) }; 85 + // SAFETY: attr and slot are valid ptrs and attr is initialized 86 + let ret = unsafe { libc::pthread_mutex_init(slot, attr) }; 87 + // SAFETY: attr was initialized 88 + unsafe { libc::pthread_mutexattr_destroy(attr) }; 89 + if ret != 0 { 90 + return Err(Error::IO(std::io::Error::from_raw_os_error(ret))); 91 + } 92 + Ok(()) 93 + }; 94 + // SAFETY: mutex has been initialized 95 + unsafe { pin_init_from_closure(init) } 96 + } 97 + try_pin_init!(Self { 98 + data: UnsafeCell::new(data), 99 + raw <- init_raw(), 100 + pin: PhantomPinned, 101 + }? Error) 102 + } 103 + 104 + pub fn lock(&self) -> PThreadMutexGuard<'_, T> { 105 + // SAFETY: raw is always initialized 106 + unsafe { libc::pthread_mutex_lock(self.raw.get()) }; 107 + PThreadMutexGuard { mtx: self } 108 + } 109 + } 110 + 111 + pub struct PThreadMutexGuard<'a, T> { 112 + mtx: &'a PThreadMutex<T>, 113 + } 114 + 115 + impl<T> Drop for PThreadMutexGuard<'_, T> { 116 + fn drop(&mut self) { 117 + // SAFETY: raw is always initialized 118 + unsafe { libc::pthread_mutex_unlock(self.mtx.raw.get()) }; 119 + } 120 + } 121 + 122 + impl<T> Deref for PThreadMutexGuard<'_, T> { 123 + type Target = T; 124 + 125 + fn deref(&self) -> &Self::Target { 126 + unsafe { &*self.mtx.data.get() } 127 + } 128 + } 129 + 130 + impl<T> DerefMut for PThreadMutexGuard<'_, T> { 131 + fn deref_mut(&mut self) -> &mut Self::Target { 132 + unsafe { &mut *self.mtx.data.get() } 133 + } 134 + } 135 + } 136 + 137 + #[cfg_attr(test, test)] 138 + fn main() { 139 + #[cfg(all(any(feature = "std", feature = "alloc"), not(windows)))] 140 + { 141 + use core::pin::Pin; 142 + use pin_init::*; 143 + use pthread_mtx::*; 144 + use std::{ 145 + sync::Arc, 146 + thread::{sleep, Builder}, 147 + time::Duration, 148 + }; 149 + let mtx: Pin<Arc<PThreadMutex<usize>>> = Arc::try_pin_init(PThreadMutex::new(0)).unwrap(); 150 + let mut handles = vec![]; 151 + let thread_count = 20; 152 + let workload = 1_000_000; 153 + for i in 0..thread_count { 154 + let mtx = mtx.clone(); 155 + handles.push( 156 + Builder::new() 157 + .name(format!("worker #{i}")) 158 + .spawn(move || { 159 + for _ in 0..workload { 160 + *mtx.lock() += 1; 161 + } 162 + println!("{i} halfway"); 163 + sleep(Duration::from_millis((i as u64) * 10)); 164 + for _ in 0..workload { 165 + *mtx.lock() += 1; 166 + } 167 + println!("{i} finished"); 168 + }) 169 + .expect("should not fail"), 170 + ); 171 + } 172 + for h in handles { 173 + h.join().expect("thread panicked"); 174 + } 175 + println!("{:?}", &*mtx.lock()); 176 + assert_eq!(*mtx.lock(), workload * thread_count * 2); 177 + } 178 + }
+122
rust/pin-init/examples/static_init.rs
··· 1 + // SPDX-License-Identifier: Apache-2.0 OR MIT 2 + 3 + #![allow(clippy::undocumented_unsafe_blocks)] 4 + #![cfg_attr(feature = "alloc", feature(allocator_api))] 5 + 6 + use core::{ 7 + cell::{Cell, UnsafeCell}, 8 + mem::MaybeUninit, 9 + ops, 10 + pin::Pin, 11 + time::Duration, 12 + }; 13 + use pin_init::*; 14 + use std::{ 15 + sync::Arc, 16 + thread::{sleep, Builder}, 17 + }; 18 + 19 + #[expect(unused_attributes)] 20 + mod mutex; 21 + use mutex::*; 22 + 23 + pub struct StaticInit<T, I> { 24 + cell: UnsafeCell<MaybeUninit<T>>, 25 + init: Cell<Option<I>>, 26 + lock: SpinLock, 27 + present: Cell<bool>, 28 + } 29 + 30 + unsafe impl<T: Sync, I> Sync for StaticInit<T, I> {} 31 + unsafe impl<T: Send, I> Send for StaticInit<T, I> {} 32 + 33 + impl<T, I: PinInit<T>> StaticInit<T, I> { 34 + pub const fn new(init: I) -> Self { 35 + Self { 36 + cell: UnsafeCell::new(MaybeUninit::uninit()), 37 + init: Cell::new(Some(init)), 38 + lock: SpinLock::new(), 39 + present: Cell::new(false), 40 + } 41 + } 42 + } 43 + 44 + impl<T, I: PinInit<T>> ops::Deref for StaticInit<T, I> { 45 + type Target = T; 46 + fn deref(&self) -> &Self::Target { 47 + if self.present.get() { 48 + unsafe { (*self.cell.get()).assume_init_ref() } 49 + } else { 50 + println!("acquire spinlock on static init"); 51 + let _guard = self.lock.acquire(); 52 + println!("rechecking present..."); 53 + std::thread::sleep(std::time::Duration::from_millis(200)); 54 + if self.present.get() { 55 + return unsafe { (*self.cell.get()).assume_init_ref() }; 56 + } 57 + println!("doing init"); 58 + let ptr = self.cell.get().cast::<T>(); 59 + match self.init.take() { 60 + Some(f) => unsafe { f.__pinned_init(ptr).unwrap() }, 61 + None => unsafe { core::hint::unreachable_unchecked() }, 62 + } 63 + self.present.set(true); 64 + unsafe { (*self.cell.get()).assume_init_ref() } 65 + } 66 + } 67 + } 68 + 69 + pub struct CountInit; 70 + 71 + unsafe impl PinInit<CMutex<usize>> for CountInit { 72 + unsafe fn __pinned_init( 73 + self, 74 + slot: *mut CMutex<usize>, 75 + ) -> Result<(), core::convert::Infallible> { 76 + let init = CMutex::new(0); 77 + std::thread::sleep(std::time::Duration::from_millis(1000)); 78 + unsafe { init.__pinned_init(slot) } 79 + } 80 + } 81 + 82 + pub static COUNT: StaticInit<CMutex<usize>, CountInit> = StaticInit::new(CountInit); 83 + 84 + #[cfg(not(any(feature = "std", feature = "alloc")))] 85 + fn main() {} 86 + 87 + #[cfg(any(feature = "std", feature = "alloc"))] 88 + fn main() { 89 + let mtx: Pin<Arc<CMutex<usize>>> = Arc::pin_init(CMutex::new(0)).unwrap(); 90 + let mut handles = vec![]; 91 + let thread_count = 20; 92 + let workload = 1_000; 93 + for i in 0..thread_count { 94 + let mtx = mtx.clone(); 95 + handles.push( 96 + Builder::new() 97 + .name(format!("worker #{i}")) 98 + .spawn(move || { 99 + for _ in 0..workload { 100 + *COUNT.lock() += 1; 101 + std::thread::sleep(std::time::Duration::from_millis(10)); 102 + *mtx.lock() += 1; 103 + std::thread::sleep(std::time::Duration::from_millis(10)); 104 + *COUNT.lock() += 1; 105 + } 106 + println!("{i} halfway"); 107 + sleep(Duration::from_millis((i as u64) * 10)); 108 + for _ in 0..workload { 109 + std::thread::sleep(std::time::Duration::from_millis(10)); 110 + *mtx.lock() += 1; 111 + } 112 + println!("{i} finished"); 113 + }) 114 + .expect("should not fail"), 115 + ); 116 + } 117 + for h in handles { 118 + h.join().expect("thread panicked"); 119 + } 120 + println!("{:?}, {:?}", &*mtx.lock(), &*COUNT.lock()); 121 + assert_eq!(*mtx.lock(), workload * thread_count * 2); 122 + }
+179 -186
rust/pin-init/src/lib.rs
··· 33 33 //! 34 34 //! ```rust,ignore 35 35 //! # #![expect(clippy::disallowed_names)] 36 - //! use kernel::sync::{new_mutex, Mutex}; 36 + //! # #![feature(allocator_api)] 37 + //! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*; 37 38 //! # use core::pin::Pin; 39 + //! use pin_init::*; 40 + //! 38 41 //! #[pin_data] 39 42 //! struct Foo { 40 43 //! #[pin] 41 - //! a: Mutex<usize>, 44 + //! a: CMutex<usize>, 42 45 //! b: u32, 43 46 //! } 44 47 //! 45 48 //! let foo = pin_init!(Foo { 46 - //! a <- new_mutex!(42, "Foo::a"), 49 + //! a <- CMutex::new(42), 47 50 //! b: 24, 48 51 //! }); 52 + //! # let _ = Box::pin_init(foo); 49 53 //! ``` 50 54 //! 51 55 //! `foo` now is of the type [`impl PinInit<Foo>`]. We can now use any smart pointer that we like ··· 57 53 //! 58 54 //! ```rust,ignore 59 55 //! # #![expect(clippy::disallowed_names)] 60 - //! # use kernel::sync::{new_mutex, Mutex}; 61 - //! # use core::pin::Pin; 56 + //! # #![feature(allocator_api)] 57 + //! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*; 58 + //! # use core::{alloc::AllocError, pin::Pin}; 59 + //! # use pin_init::*; 60 + //! # 62 61 //! # #[pin_data] 63 62 //! # struct Foo { 64 63 //! # #[pin] 65 - //! # a: Mutex<usize>, 64 + //! # a: CMutex<usize>, 66 65 //! # b: u32, 67 66 //! # } 67 + //! # 68 68 //! # let foo = pin_init!(Foo { 69 - //! # a <- new_mutex!(42, "Foo::a"), 69 + //! # a <- CMutex::new(42), 70 70 //! # b: 24, 71 71 //! # }); 72 - //! let foo: Result<Pin<KBox<Foo>>> = KBox::pin_init(foo, GFP_KERNEL); 72 + //! let foo: Result<Pin<Box<Foo>>, AllocError> = Box::pin_init(foo); 73 73 //! ``` 74 74 //! 75 75 //! For more information see the [`pin_init!`] macro. ··· 84 76 //! above method only works for types where you can access the fields. 85 77 //! 86 78 //! ```rust,ignore 87 - //! # use kernel::sync::{new_mutex, Arc, Mutex}; 88 - //! let mtx: Result<Arc<Mutex<usize>>> = 89 - //! Arc::pin_init(new_mutex!(42, "example::mtx"), GFP_KERNEL); 79 + //! # #![feature(allocator_api)] 80 + //! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*; 81 + //! # use pin_init::*; 82 + //! # use std::sync::Arc; 83 + //! # use core::pin::Pin; 84 + //! let mtx: Result<Pin<Arc<CMutex<usize>>>, _> = Arc::pin_init(CMutex::new(42)); 90 85 //! ``` 91 86 //! 92 87 //! To declare an init macro/function you just return an [`impl PinInit<T, E>`]: 93 88 //! 94 89 //! ```rust,ignore 95 - //! # use kernel::{sync::Mutex, new_mutex, init::PinInit, try_pin_init}; 90 + //! # #![feature(allocator_api)] 91 + //! # use pin_init::*; 92 + //! # #[path = "../examples/error.rs"] mod error; use error::Error; 93 + //! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*; 96 94 //! #[pin_data] 97 95 //! struct DriverData { 98 96 //! #[pin] 99 - //! status: Mutex<i32>, 100 - //! buffer: KBox<[u8; 1_000_000]>, 97 + //! status: CMutex<i32>, 98 + //! buffer: Box<[u8; 1_000_000]>, 101 99 //! } 102 100 //! 103 101 //! impl DriverData { 104 102 //! fn new() -> impl PinInit<Self, Error> { 105 103 //! try_pin_init!(Self { 106 - //! status <- new_mutex!(0, "DriverData::status"), 107 - //! buffer: KBox::init(kernel::init::zeroed(), GFP_KERNEL)?, 108 - //! }) 104 + //! status <- CMutex::new(0), 105 + //! buffer: Box::init(pin_init::zeroed())?, 106 + //! }? Error) 109 107 //! } 110 108 //! } 111 109 //! ``` ··· 131 117 //! `slot` gets called. 132 118 //! 133 119 //! ```rust,ignore 134 - //! # #![expect(unreachable_pub, clippy::disallowed_names)] 135 - //! use kernel::{init, types::Opaque}; 136 - //! use core::{ptr::addr_of_mut, marker::PhantomPinned, pin::Pin}; 137 - //! # mod bindings { 138 - //! # #![expect(non_camel_case_types)] 139 - //! # #![expect(clippy::missing_safety_doc)] 140 - //! # pub struct foo; 141 - //! # pub unsafe fn init_foo(_ptr: *mut foo) {} 142 - //! # pub unsafe fn destroy_foo(_ptr: *mut foo) {} 143 - //! # pub unsafe fn enable_foo(_ptr: *mut foo, _flags: u32) -> i32 { 0 } 144 - //! # } 145 - //! # // `Error::from_errno` is `pub(crate)` in the `kernel` crate, thus provide a workaround. 146 - //! # trait FromErrno { 147 - //! # fn from_errno(errno: kernel::ffi::c_int) -> Error { 148 - //! # // Dummy error that can be constructed outside the `kernel` crate. 149 - //! # Error::from(core::fmt::Error) 150 - //! # } 151 - //! # } 152 - //! # impl FromErrno for Error {} 120 + //! # #![feature(extern_types)] 121 + //! use pin_init::*; 122 + //! use core::{ 123 + //! ptr::addr_of_mut, 124 + //! marker::PhantomPinned, 125 + //! cell::UnsafeCell, 126 + //! pin::Pin, 127 + //! mem::MaybeUninit, 128 + //! }; 129 + //! mod bindings { 130 + //! extern "C" { 131 + //! pub type foo; 132 + //! pub fn init_foo(ptr: *mut foo); 133 + //! pub fn destroy_foo(ptr: *mut foo); 134 + //! #[must_use = "you must check the error return code"] 135 + //! pub fn enable_foo(ptr: *mut foo, flags: u32) -> i32; 136 + //! } 137 + //! } 138 + //! 153 139 //! /// # Invariants 154 140 //! /// 155 141 //! /// `foo` is always initialized 156 142 //! #[pin_data(PinnedDrop)] 157 143 //! pub struct RawFoo { 158 144 //! #[pin] 159 - //! foo: Opaque<bindings::foo>, 160 - //! #[pin] 161 145 //! _p: PhantomPinned, 146 + //! #[pin] 147 + //! foo: UnsafeCell<MaybeUninit<bindings::foo>>, 162 148 //! } 163 149 //! 164 150 //! impl RawFoo { 165 - //! pub fn new(flags: u32) -> impl PinInit<Self, Error> { 151 + //! pub fn new(flags: u32) -> impl PinInit<Self, i32> { 166 152 //! // SAFETY: 167 153 //! // - when the closure returns `Ok(())`, then it has successfully initialized and 168 154 //! // enabled `foo`, 169 155 //! // - when it returns `Err(e)`, then it has cleaned up before 170 156 //! unsafe { 171 - //! init::pin_init_from_closure(move |slot: *mut Self| { 157 + //! pin_init_from_closure(move |slot: *mut Self| { 172 158 //! // `slot` contains uninit memory, avoid creating a reference. 173 159 //! let foo = addr_of_mut!((*slot).foo); 160 + //! let foo = UnsafeCell::raw_get(foo).cast::<bindings::foo>(); 174 161 //! 175 162 //! // Initialize the `foo` 176 - //! bindings::init_foo(Opaque::raw_get(foo)); 163 + //! bindings::init_foo(foo); 177 164 //! 178 165 //! // Try to enable it. 179 - //! let err = bindings::enable_foo(Opaque::raw_get(foo), flags); 166 + //! let err = bindings::enable_foo(foo, flags); 180 167 //! if err != 0 { 181 168 //! // Enabling has failed, first clean up the foo and then return the error. 182 - //! bindings::destroy_foo(Opaque::raw_get(foo)); 183 - //! return Err(Error::from_errno(err)); 169 + //! bindings::destroy_foo(foo); 170 + //! Err(err) 171 + //! } else { 172 + //! // All fields of `RawFoo` have been initialized, since `_p` is a ZST. 173 + //! Ok(()) 184 174 //! } 185 - //! 186 - //! // All fields of `RawFoo` have been initialized, since `_p` is a ZST. 187 - //! Ok(()) 188 175 //! }) 189 176 //! } 190 177 //! } ··· 195 180 //! impl PinnedDrop for RawFoo { 196 181 //! fn drop(self: Pin<&mut Self>) { 197 182 //! // SAFETY: Since `foo` is initialized, destroying is safe. 198 - //! unsafe { bindings::destroy_foo(self.foo.get()) }; 183 + //! unsafe { bindings::destroy_foo(self.foo.get().cast::<bindings::foo>()) }; 199 184 //! } 200 185 //! } 201 186 //! ``` ··· 250 235 /// # Examples 251 236 /// 252 237 /// ```ignore 253 - /// # #![feature(lint_reasons)] 254 - /// # use kernel::prelude::*; 255 - /// # use std::{sync::Mutex, process::Command}; 256 - /// # use kernel::macros::pin_data; 238 + /// # #![feature(allocator_api)] 239 + /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*; 240 + /// use pin_init::pin_data; 241 + /// 242 + /// enum Command { 243 + /// /* ... */ 244 + /// } 245 + /// 257 246 /// #[pin_data] 258 247 /// struct DriverData { 259 248 /// #[pin] 260 - /// queue: Mutex<KVec<Command>>, 261 - /// buf: KBox<[u8; 1024 * 1024]>, 249 + /// queue: CMutex<Vec<Command>>, 250 + /// buf: Box<[u8; 1024 * 1024]>, 262 251 /// } 263 252 /// ``` 264 253 /// 265 254 /// ```ignore 266 - /// # #![feature(lint_reasons)] 267 - /// # use kernel::prelude::*; 268 - /// # use std::{sync::Mutex, process::Command}; 269 - /// # use core::pin::Pin; 270 - /// # pub struct Info; 271 - /// # mod bindings { 272 - /// # pub unsafe fn destroy_info(_ptr: *mut super::Info) {} 273 - /// # } 274 - /// use kernel::macros::{pin_data, pinned_drop}; 255 + /// # #![feature(allocator_api)] 256 + /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*; 257 + /// # mod bindings { pub struct info; pub unsafe fn destroy_info(_: *mut info) {} } 258 + /// use core::pin::Pin; 259 + /// use pin_init::{pin_data, pinned_drop, PinnedDrop}; 260 + /// 261 + /// enum Command { 262 + /// /* ... */ 263 + /// } 275 264 /// 276 265 /// #[pin_data(PinnedDrop)] 277 266 /// struct DriverData { 278 267 /// #[pin] 279 - /// queue: Mutex<KVec<Command>>, 280 - /// buf: KBox<[u8; 1024 * 1024]>, 281 - /// raw_info: *mut Info, 268 + /// queue: CMutex<Vec<Command>>, 269 + /// buf: Box<[u8; 1024 * 1024]>, 270 + /// raw_info: *mut bindings::info, 282 271 /// } 283 272 /// 284 273 /// #[pinned_drop] ··· 291 272 /// unsafe { bindings::destroy_info(self.raw_info) }; 292 273 /// } 293 274 /// } 294 - /// # fn main() {} 295 275 /// ``` 296 276 /// 297 277 /// [`pin_init!`]: crate::pin_init ··· 303 285 /// # Examples 304 286 /// 305 287 /// ```ignore 306 - /// # #![feature(lint_reasons)] 307 - /// # use kernel::prelude::*; 308 - /// # use macros::{pin_data, pinned_drop}; 309 - /// # use std::{sync::Mutex, process::Command}; 310 - /// # use core::pin::Pin; 311 - /// # mod bindings { 312 - /// # pub struct Info; 313 - /// # pub unsafe fn destroy_info(_ptr: *mut Info) {} 314 - /// # } 288 + /// # #![feature(allocator_api)] 289 + /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*; 290 + /// # mod bindings { pub struct info; pub unsafe fn destroy_info(_: *mut info) {} } 291 + /// use core::pin::Pin; 292 + /// use pin_init::{pin_data, pinned_drop, PinnedDrop}; 293 + /// 294 + /// enum Command { 295 + /// /* ... */ 296 + /// } 297 + /// 315 298 /// #[pin_data(PinnedDrop)] 316 299 /// struct DriverData { 317 300 /// #[pin] 318 - /// queue: Mutex<KVec<Command>>, 319 - /// buf: KBox<[u8; 1024 * 1024]>, 320 - /// raw_info: *mut bindings::Info, 301 + /// queue: CMutex<Vec<Command>>, 302 + /// buf: Box<[u8; 1024 * 1024]>, 303 + /// raw_info: *mut bindings::info, 321 304 /// } 322 305 /// 323 306 /// #[pinned_drop] ··· 337 318 /// # Examples 338 319 /// 339 320 /// ```ignore 340 - /// use kernel::macros::Zeroable; 321 + /// use pin_init::Zeroable; 341 322 /// 342 323 /// #[derive(Zeroable)] 343 324 /// pub struct DriverData { ··· 354 335 /// 355 336 /// ```rust,ignore 356 337 /// # #![expect(clippy::disallowed_names)] 357 - /// # use kernel::{init, macros::pin_data, pin_init, stack_pin_init, init::*, sync::Mutex, new_mutex}; 338 + /// # #![feature(allocator_api)] 339 + /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*; 340 + /// # use pin_init::*; 358 341 /// # use core::pin::Pin; 359 342 /// #[pin_data] 360 343 /// struct Foo { 361 344 /// #[pin] 362 - /// a: Mutex<usize>, 345 + /// a: CMutex<usize>, 363 346 /// b: Bar, 364 347 /// } 365 348 /// ··· 371 350 /// } 372 351 /// 373 352 /// stack_pin_init!(let foo = pin_init!(Foo { 374 - /// a <- new_mutex!(42), 353 + /// a <- CMutex::new(42), 375 354 /// b: Bar { 376 355 /// x: 64, 377 356 /// }, 378 357 /// })); 379 358 /// let foo: Pin<&mut Foo> = foo; 380 - /// pr_info!("a: {}", &*foo.a.lock()); 359 + /// println!("a: {}", &*foo.a.lock()); 381 360 /// ``` 382 361 /// 383 362 /// # Syntax ··· 408 387 /// 409 388 /// ```rust,ignore 410 389 /// # #![expect(clippy::disallowed_names)] 411 - /// # use kernel::{ 412 - /// # init, 413 - /// # pin_init, 414 - /// # stack_try_pin_init, 415 - /// # init::*, 416 - /// # sync::Mutex, 417 - /// # new_mutex, 418 - /// # alloc::AllocError, 419 - /// # }; 420 - /// # use macros::pin_data; 421 - /// # use core::pin::Pin; 390 + /// # #![feature(allocator_api)] 391 + /// # #[path = "../examples/error.rs"] mod error; use error::Error; 392 + /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*; 393 + /// # use pin_init::*; 422 394 /// #[pin_data] 423 395 /// struct Foo { 424 396 /// #[pin] 425 - /// a: Mutex<usize>, 426 - /// b: KBox<Bar>, 397 + /// a: CMutex<usize>, 398 + /// b: Box<Bar>, 427 399 /// } 428 400 /// 429 401 /// struct Bar { 430 402 /// x: u32, 431 403 /// } 432 404 /// 433 - /// stack_try_pin_init!(let foo: Result<Pin<&mut Foo>, AllocError> = pin_init!(Foo { 434 - /// a <- new_mutex!(42), 435 - /// b: KBox::new(Bar { 405 + /// stack_try_pin_init!(let foo: Foo = try_pin_init!(Foo { 406 + /// a <- CMutex::new(42), 407 + /// b: Box::try_new(Bar { 436 408 /// x: 64, 437 - /// }, GFP_KERNEL)?, 438 - /// })); 409 + /// })?, 410 + /// }? Error)); 439 411 /// let foo = foo.unwrap(); 440 - /// pr_info!("a: {}", &*foo.a.lock()); 412 + /// println!("a: {}", &*foo.a.lock()); 441 413 /// ``` 442 414 /// 443 415 /// ```rust,ignore 444 416 /// # #![expect(clippy::disallowed_names)] 445 - /// # use kernel::{ 446 - /// # init, 447 - /// # pin_init, 448 - /// # stack_try_pin_init, 449 - /// # init::*, 450 - /// # sync::Mutex, 451 - /// # new_mutex, 452 - /// # alloc::AllocError, 453 - /// # }; 454 - /// # use macros::pin_data; 455 - /// # use core::pin::Pin; 417 + /// # #![feature(allocator_api)] 418 + /// # #[path = "../examples/error.rs"] mod error; use error::Error; 419 + /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*; 420 + /// # use pin_init::*; 456 421 /// #[pin_data] 457 422 /// struct Foo { 458 423 /// #[pin] 459 - /// a: Mutex<usize>, 460 - /// b: KBox<Bar>, 424 + /// a: CMutex<usize>, 425 + /// b: Box<Bar>, 461 426 /// } 462 427 /// 463 428 /// struct Bar { 464 429 /// x: u32, 465 430 /// } 466 431 /// 467 - /// stack_try_pin_init!(let foo: Pin<&mut Foo> =? pin_init!(Foo { 468 - /// a <- new_mutex!(42), 469 - /// b: KBox::new(Bar { 432 + /// stack_try_pin_init!(let foo: Foo =? try_pin_init!(Foo { 433 + /// a <- CMutex::new(42), 434 + /// b: Box::try_new(Bar { 470 435 /// x: 64, 471 - /// }, GFP_KERNEL)?, 472 - /// })); 473 - /// pr_info!("a: {}", &*foo.a.lock()); 474 - /// # Ok::<_, AllocError>(()) 436 + /// })?, 437 + /// }? Error)); 438 + /// println!("a: {}", &*foo.a.lock()); 439 + /// # Ok::<_, Error>(()) 475 440 /// ``` 476 441 /// 477 442 /// # Syntax ··· 487 480 /// The syntax is almost identical to that of a normal `struct` initializer: 488 481 /// 489 482 /// ```rust,ignore 490 - /// # use kernel::{init, pin_init, macros::pin_data, init::*}; 483 + /// # use pin_init::*; 491 484 /// # use core::pin::Pin; 492 485 /// #[pin_data] 493 486 /// struct Foo { ··· 510 503 /// }, 511 504 /// }); 512 505 /// # initializer } 513 - /// # KBox::pin_init(demo(), GFP_KERNEL).unwrap(); 506 + /// # Box::pin_init(demo()).unwrap(); 514 507 /// ``` 515 508 /// 516 509 /// Arbitrary Rust expressions can be used to set the value of a variable. ··· 531 524 /// To create an initializer function, simply declare it like this: 532 525 /// 533 526 /// ```rust,ignore 534 - /// # use kernel::{init, pin_init, init::*}; 527 + /// # use pin_init::*; 535 528 /// # use core::pin::Pin; 536 529 /// # #[pin_data] 537 530 /// # struct Foo { ··· 558 551 /// 559 552 /// ```rust,ignore 560 553 /// # #![expect(clippy::disallowed_names)] 561 - /// # use kernel::{init, pin_init, macros::pin_data, init::*}; 554 + /// # use pin_init::*; 562 555 /// # use core::pin::Pin; 563 556 /// # #[pin_data] 564 557 /// # struct Foo { ··· 579 572 /// # }) 580 573 /// # } 581 574 /// # } 582 - /// let foo = KBox::pin_init(Foo::new(), GFP_KERNEL); 575 + /// let foo = Box::pin_init(Foo::new()); 583 576 /// ``` 584 577 /// 585 578 /// They can also easily embed it into their own `struct`s: 586 579 /// 587 580 /// ```rust,ignore 588 - /// # use kernel::{init, pin_init, macros::pin_data, init::*}; 581 + /// # use pin_init::*; 589 582 /// # use core::pin::Pin; 590 583 /// # #[pin_data] 591 584 /// # struct Foo { ··· 644 637 /// For instance: 645 638 /// 646 639 /// ```rust,ignore 647 - /// # use kernel::{macros::{Zeroable, pin_data}, pin_init}; 640 + /// # use pin_init::*; 648 641 /// # use core::{ptr::addr_of_mut, marker::PhantomPinned}; 649 642 /// #[pin_data] 650 643 /// #[derive(Zeroable)] ··· 707 700 /// # Examples 708 701 /// 709 702 /// ```rust,ignore 710 - /// use kernel::{init::{self, PinInit}, error::Error}; 703 + /// # #![feature(allocator_api)] 704 + /// # #[path = "../examples/error.rs"] mod error; use error::Error; 705 + /// use pin_init::*; 711 706 /// #[pin_data] 712 707 /// struct BigBuf { 713 - /// big: KBox<[u8; 1024 * 1024 * 1024]>, 708 + /// big: Box<[u8; 1024 * 1024 * 1024]>, 714 709 /// small: [u8; 1024 * 1024], 715 710 /// ptr: *mut u8, 716 711 /// } ··· 720 711 /// impl BigBuf { 721 712 /// fn new() -> impl PinInit<Self, Error> { 722 713 /// try_pin_init!(Self { 723 - /// big: KBox::init(init::zeroed(), GFP_KERNEL)?, 714 + /// big: Box::init(init::zeroed())?, 724 715 /// small: [0; 1024 * 1024], 725 716 /// ptr: core::ptr::null_mut(), 726 717 /// }? Error) 727 718 /// } 728 719 /// } 720 + /// # let _ = Box::pin_init(BigBuf::new()); 729 721 /// ``` 730 722 // For a detailed example of how this macro works, see the module documentation of the hidden 731 723 // module `__internal` inside of `init/__internal.rs`. ··· 813 803 /// # Examples 814 804 /// 815 805 /// ```rust,ignore 816 - /// use kernel::{alloc::KBox, init::{PinInit, zeroed}, error::Error}; 806 + /// # #![feature(allocator_api)] 807 + /// # use core::alloc::AllocError; 808 + /// use pin_init::*; 817 809 /// struct BigBuf { 818 - /// big: KBox<[u8; 1024 * 1024 * 1024]>, 810 + /// big: Box<[u8; 1024 * 1024 * 1024]>, 819 811 /// small: [u8; 1024 * 1024], 820 812 /// } 821 813 /// 822 814 /// impl BigBuf { 823 - /// fn new() -> impl Init<Self, Error> { 815 + /// fn new() -> impl Init<Self, AllocError> { 824 816 /// try_init!(Self { 825 - /// big: KBox::init(zeroed(), GFP_KERNEL)?, 817 + /// big: Box::init(zeroed())?, 826 818 /// small: [0; 1024 * 1024], 827 - /// }? Error) 819 + /// }? AllocError) 828 820 /// } 829 821 /// } 830 822 /// ``` ··· 871 859 /// 872 860 /// This will succeed: 873 861 /// ```ignore 874 - /// use kernel::assert_pinned; 862 + /// use pin_init::assert_pinned; 875 863 /// #[pin_data] 876 864 /// struct MyStruct { 877 865 /// #[pin] ··· 882 870 /// ``` 883 871 /// 884 872 /// This will fail: 885 - // TODO: replace with `compile_fail` when supported. 886 - /// ```ignore 887 - /// use kernel::assert_pinned; 873 + /// ```compile_fail,ignore 874 + /// use pin_init::assert_pinned; 888 875 /// #[pin_data] 889 876 /// struct MyStruct { 890 877 /// some_field: u64, ··· 896 885 /// work around this, you may pass the `inline` parameter to the macro. The `inline` parameter can 897 886 /// only be used when the macro is invoked from a function body. 898 887 /// ```ignore 899 - /// use kernel::assert_pinned; 888 + /// use pin_init::assert_pinned; 900 889 /// #[pin_data] 901 890 /// struct Foo<T> { 902 891 /// #[pin] ··· 974 963 /// # Examples 975 964 /// 976 965 /// ```rust,ignore 977 - /// # #![expect(clippy::disallowed_names)] 978 - /// use kernel::{types::Opaque, init::pin_init_from_closure}; 979 - /// #[repr(C)] 980 - /// struct RawFoo([u8; 16]); 981 - /// extern "C" { 982 - /// fn init_foo(_: *mut RawFoo); 983 - /// } 984 - /// 985 - /// #[pin_data] 986 - /// struct Foo { 987 - /// #[pin] 988 - /// raw: Opaque<RawFoo>, 989 - /// } 990 - /// 991 - /// impl Foo { 992 - /// fn setup(self: Pin<&mut Self>) { 993 - /// pr_info!("Setting up foo"); 994 - /// } 995 - /// } 996 - /// 997 - /// let foo = pin_init!(Foo { 998 - /// // SAFETY: TODO. 999 - /// raw <- unsafe { 1000 - /// Opaque::ffi_init(|s| { 1001 - /// init_foo(s); 1002 - /// }) 1003 - /// }, 1004 - /// }).pin_chain(|foo| { 1005 - /// foo.setup(); 966 + /// # #![feature(allocator_api)] 967 + /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*; 968 + /// # use pin_init::*; 969 + /// let mtx_init = CMutex::new(42); 970 + /// // Make the initializer print the value. 971 + /// let mtx_init = mtx_init.pin_chain(|mtx| { 972 + /// println!("{:?}", mtx.get_data_mut()); 1006 973 /// Ok(()) 1007 974 /// }); 1008 975 /// ``` ··· 1065 1076 /// 1066 1077 /// ```rust,ignore 1067 1078 /// # #![expect(clippy::disallowed_names)] 1068 - /// use kernel::{types::Opaque, init::{self, init_from_closure}}; 1079 + /// use pin_init::{init_from_closure, zeroed}; 1069 1080 /// struct Foo { 1070 1081 /// buf: [u8; 1_000_000], 1071 1082 /// } ··· 1077 1088 /// } 1078 1089 /// 1079 1090 /// let foo = init!(Foo { 1080 - /// buf <- init::zeroed() 1091 + /// buf <- zeroed() 1081 1092 /// }).chain(|foo| { 1082 1093 /// foo.setup(); 1083 1094 /// Ok(()) ··· 1176 1187 /// # Examples 1177 1188 /// 1178 1189 /// ```rust,ignore 1179 - /// use kernel::{alloc::KBox, error::Error, init::init_array_from_fn}; 1180 - /// let array: KBox<[usize; 1_000]> = 1181 - /// KBox::init::<Error>(init_array_from_fn(|i| i), GFP_KERNEL)?; 1190 + /// # use pin_init::*; 1191 + /// use pin_init::init_array_from_fn; 1192 + /// let array: Box<[usize; 1_000]> = Box::init(init_array_from_fn(|i| i)).unwrap(); 1182 1193 /// assert_eq!(array.len(), 1_000); 1183 - /// # Ok::<(), Error>(()) 1184 1194 /// ``` 1185 1195 pub fn init_array_from_fn<I, const N: usize, T, E>( 1186 1196 mut make_init: impl FnMut(usize) -> I, ··· 1220 1232 /// # Examples 1221 1233 /// 1222 1234 /// ```rust,ignore 1223 - /// use kernel::{sync::{Arc, Mutex}, init::pin_init_array_from_fn, new_mutex}; 1224 - /// let array: Arc<[Mutex<usize>; 1_000]> = 1225 - /// Arc::pin_init(pin_init_array_from_fn(|i| new_mutex!(i)), GFP_KERNEL)?; 1235 + /// # #![feature(allocator_api)] 1236 + /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*; 1237 + /// # use pin_init::*; 1238 + /// # use core::pin::Pin; 1239 + /// use pin_init::pin_init_array_from_fn; 1240 + /// use std::sync::Arc; 1241 + /// let array: Pin<Arc<[CMutex<usize>; 1_000]>> = 1242 + /// Arc::pin_init(pin_init_array_from_fn(|i| CMutex::new(i))).unwrap(); 1226 1243 /// assert_eq!(array.len(), 1_000); 1227 - /// # Ok::<(), Error>(()) 1228 1244 /// ``` 1229 1245 pub fn pin_init_array_from_fn<I, const N: usize, T, E>( 1230 1246 mut make_init: impl FnMut(usize) -> I, ··· 1413 1421 /// Use [`pinned_drop`] to implement this trait safely: 1414 1422 /// 1415 1423 /// ```rust,ignore 1416 - /// # use kernel::sync::Mutex; 1417 - /// use kernel::macros::pinned_drop; 1424 + /// # #![feature(allocator_api)] 1425 + /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*; 1426 + /// # use pin_init::*; 1418 1427 /// use core::pin::Pin; 1419 1428 /// #[pin_data(PinnedDrop)] 1420 1429 /// struct Foo { 1421 1430 /// #[pin] 1422 - /// mtx: Mutex<usize>, 1431 + /// mtx: CMutex<usize>, 1423 1432 /// } 1424 1433 /// 1425 1434 /// #[pinned_drop] 1426 1435 /// impl PinnedDrop for Foo { 1427 1436 /// fn drop(self: Pin<&mut Self>) { 1428 - /// pr_info!("Foo is being dropped!"); 1437 + /// println!("Foo is being dropped!"); 1429 1438 /// } 1430 1439 /// } 1431 1440 /// ```