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.

Merge tag 'rust-xarray-for-v6.16' of https://github.com/Rust-for-Linux/linux into rust-next

Pull XArray updates from Andreas Hindborg:
"Introduce Rust support for the 'xarray' data structure:

- Add a Rust abstraction for the 'xarray' data structure. This
abstraction allows Rust code to leverage the 'xarray' to store
types that implement 'ForeignOwnable'. This support is a dependency
for memory backing feature of the Rust null block driver, which is
waiting to be merged.

- Set up an entry in MAINTAINERS for the XArray Rust support. Patches
will go to the new Rust XArray tree and then via the Rust subsystem
tree for now.

'kernel' crate:

- Allow 'ForeignOwnable' to carry information about the pointed-to
type. This helps asserting alignment requirements for the pointer
passed to the foreign language."

* tag 'rust-xarray-for-v6.16' of https://github.com/Rust-for-Linux/linux:
MAINTAINERS: add entry for Rust XArray API
rust: xarray: Add an abstraction for XArray
rust: types: add `ForeignOwnable::PointedTo`

+392 -49
+11
MAINTAINERS
··· 26408 26408 F: lib/xarray.c 26409 26409 F: tools/testing/radix-tree 26410 26410 26411 + XARRAY API [RUST] 26412 + M: Tamir Duberstein <tamird@gmail.com> 26413 + M: Andreas Hindborg <a.hindborg@kernel.org> 26414 + L: rust-for-linux@vger.kernel.org 26415 + S: Supported 26416 + W: https://rust-for-linux.com 26417 + B: https://github.com/Rust-for-Linux/linux/issues 26418 + C: https://rust-for-linux.zulipchat.com 26419 + T: git https://github.com/Rust-for-Linux/linux.git xarray-next 26420 + F: rust/kernel/xarray.rs 26421 + 26411 26422 XBOX DVD IR REMOTE 26412 26423 M: Benjamin Valentin <benpicco@googlemail.com> 26413 26424 S: Maintained
+6
rust/bindings/bindings_helper.h
··· 37 37 #include <linux/tracepoint.h> 38 38 #include <linux/wait.h> 39 39 #include <linux/workqueue.h> 40 + #include <linux/xarray.h> 40 41 #include <trace/events/rust_sample.h> 41 42 42 43 #if defined(CONFIG_DRM_PANIC_SCREEN_QR_CODE) ··· 56 55 const gfp_t RUST_CONST_HELPER___GFP_HIGHMEM = ___GFP_HIGHMEM; 57 56 const gfp_t RUST_CONST_HELPER___GFP_NOWARN = ___GFP_NOWARN; 58 57 const blk_features_t RUST_CONST_HELPER_BLK_FEAT_ROTATIONAL = BLK_FEAT_ROTATIONAL; 58 + 59 + const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT; 60 + 61 + const gfp_t RUST_CONST_HELPER_XA_FLAGS_ALLOC = XA_FLAGS_ALLOC; 62 + const gfp_t RUST_CONST_HELPER_XA_FLAGS_ALLOC1 = XA_FLAGS_ALLOC1;
+1
rust/helpers/helpers.c
··· 38 38 #include "vmalloc.c" 39 39 #include "wait.c" 40 40 #include "workqueue.c" 41 + #include "xarray.c"
+28
rust/helpers/xarray.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/xarray.h> 4 + 5 + int rust_helper_xa_err(void *entry) 6 + { 7 + return xa_err(entry); 8 + } 9 + 10 + void rust_helper_xa_init_flags(struct xarray *xa, gfp_t flags) 11 + { 12 + return xa_init_flags(xa, flags); 13 + } 14 + 15 + int rust_helper_xa_trylock(struct xarray *xa) 16 + { 17 + return xa_trylock(xa); 18 + } 19 + 20 + void rust_helper_xa_lock(struct xarray *xa) 21 + { 22 + return xa_lock(xa); 23 + } 24 + 25 + void rust_helper_xa_unlock(struct xarray *xa) 26 + { 27 + return xa_unlock(xa); 28 + }
+20 -18
rust/kernel/alloc/kbox.rs
··· 360 360 } 361 361 } 362 362 363 - impl<T: 'static, A> ForeignOwnable for Box<T, A> 363 + // SAFETY: The `into_foreign` function returns a pointer that is well-aligned. 364 + unsafe impl<T: 'static, A> ForeignOwnable for Box<T, A> 364 365 where 365 366 A: Allocator, 366 367 { 368 + type PointedTo = T; 367 369 type Borrowed<'a> = &'a T; 368 370 type BorrowedMut<'a> = &'a mut T; 369 371 370 - fn into_foreign(self) -> *mut crate::ffi::c_void { 371 - Box::into_raw(self).cast() 372 + fn into_foreign(self) -> *mut Self::PointedTo { 373 + Box::into_raw(self) 372 374 } 373 375 374 - unsafe fn from_foreign(ptr: *mut crate::ffi::c_void) -> Self { 376 + unsafe fn from_foreign(ptr: *mut Self::PointedTo) -> Self { 375 377 // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous 376 378 // call to `Self::into_foreign`. 377 - unsafe { Box::from_raw(ptr.cast()) } 379 + unsafe { Box::from_raw(ptr) } 378 380 } 379 381 380 - unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> &'a T { 382 + unsafe fn borrow<'a>(ptr: *mut Self::PointedTo) -> &'a T { 381 383 // SAFETY: The safety requirements of this method ensure that the object remains alive and 382 384 // immutable for the duration of 'a. 383 - unsafe { &*ptr.cast() } 385 + unsafe { &*ptr } 384 386 } 385 387 386 - unsafe fn borrow_mut<'a>(ptr: *mut crate::ffi::c_void) -> &'a mut T { 387 - let ptr = ptr.cast(); 388 + unsafe fn borrow_mut<'a>(ptr: *mut Self::PointedTo) -> &'a mut T { 388 389 // SAFETY: The safety requirements of this method ensure that the pointer is valid and that 389 390 // nothing else will access the value for the duration of 'a. 390 391 unsafe { &mut *ptr } 391 392 } 392 393 } 393 394 394 - impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>> 395 + // SAFETY: The `into_foreign` function returns a pointer that is well-aligned. 396 + unsafe impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>> 395 397 where 396 398 A: Allocator, 397 399 { 400 + type PointedTo = T; 398 401 type Borrowed<'a> = Pin<&'a T>; 399 402 type BorrowedMut<'a> = Pin<&'a mut T>; 400 403 401 - fn into_foreign(self) -> *mut crate::ffi::c_void { 404 + fn into_foreign(self) -> *mut Self::PointedTo { 402 405 // SAFETY: We are still treating the box as pinned. 403 - Box::into_raw(unsafe { Pin::into_inner_unchecked(self) }).cast() 406 + Box::into_raw(unsafe { Pin::into_inner_unchecked(self) }) 404 407 } 405 408 406 - unsafe fn from_foreign(ptr: *mut crate::ffi::c_void) -> Self { 409 + unsafe fn from_foreign(ptr: *mut Self::PointedTo) -> Self { 407 410 // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous 408 411 // call to `Self::into_foreign`. 409 - unsafe { Pin::new_unchecked(Box::from_raw(ptr.cast())) } 412 + unsafe { Pin::new_unchecked(Box::from_raw(ptr)) } 410 413 } 411 414 412 - unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> Pin<&'a T> { 415 + unsafe fn borrow<'a>(ptr: *mut Self::PointedTo) -> Pin<&'a T> { 413 416 // SAFETY: The safety requirements for this function ensure that the object is still alive, 414 417 // so it is safe to dereference the raw pointer. 415 418 // The safety requirements of `from_foreign` also ensure that the object remains alive for 416 419 // the lifetime of the returned value. 417 - let r = unsafe { &*ptr.cast() }; 420 + let r = unsafe { &*ptr }; 418 421 419 422 // SAFETY: This pointer originates from a `Pin<Box<T>>`. 420 423 unsafe { Pin::new_unchecked(r) } 421 424 } 422 425 423 - unsafe fn borrow_mut<'a>(ptr: *mut crate::ffi::c_void) -> Pin<&'a mut T> { 424 - let ptr = ptr.cast(); 426 + unsafe fn borrow_mut<'a>(ptr: *mut Self::PointedTo) -> Pin<&'a mut T> { 425 427 // SAFETY: The safety requirements for this function ensure that the object is still alive, 426 428 // so it is safe to dereference the raw pointer. 427 429 // The safety requirements of `from_foreign` also ensure that the object remains alive for
+1
rust/kernel/lib.rs
··· 102 102 pub mod types; 103 103 pub mod uaccess; 104 104 pub mod workqueue; 105 + pub mod xarray; 105 106 106 107 #[doc(hidden)] 107 108 pub use bindings;
+5 -5
rust/kernel/miscdevice.rs
··· 200 200 // type. 201 201 // 202 202 // SAFETY: The open call of a file can access the private data. 203 - unsafe { (*raw_file).private_data = ptr.into_foreign() }; 203 + unsafe { (*raw_file).private_data = ptr.into_foreign().cast() }; 204 204 205 205 0 206 206 } ··· 211 211 /// must be associated with a `MiscDeviceRegistration<T>`. 212 212 unsafe extern "C" fn release(_inode: *mut bindings::inode, file: *mut bindings::file) -> c_int { 213 213 // SAFETY: The release call of a file owns the private data. 214 - let private = unsafe { (*file).private_data }; 214 + let private = unsafe { (*file).private_data }.cast(); 215 215 // SAFETY: The release call of a file owns the private data. 216 216 let ptr = unsafe { <T::Ptr as ForeignOwnable>::from_foreign(private) }; 217 217 ··· 228 228 /// `file` must be a valid file that is associated with a `MiscDeviceRegistration<T>`. 229 229 unsafe extern "C" fn ioctl(file: *mut bindings::file, cmd: c_uint, arg: c_ulong) -> c_long { 230 230 // SAFETY: The ioctl call of a file can access the private data. 231 - let private = unsafe { (*file).private_data }; 231 + let private = unsafe { (*file).private_data }.cast(); 232 232 // SAFETY: Ioctl calls can borrow the private data of the file. 233 233 let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) }; 234 234 ··· 253 253 arg: c_ulong, 254 254 ) -> c_long { 255 255 // SAFETY: The compat ioctl call of a file can access the private data. 256 - let private = unsafe { (*file).private_data }; 256 + let private = unsafe { (*file).private_data }.cast(); 257 257 // SAFETY: Ioctl calls can borrow the private data of the file. 258 258 let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) }; 259 259 ··· 274 274 /// - `seq_file` must be a valid `struct seq_file` that we can write to. 275 275 unsafe extern "C" fn show_fdinfo(seq_file: *mut bindings::seq_file, file: *mut bindings::file) { 276 276 // SAFETY: The release call of a file owns the private data. 277 - let private = unsafe { (*file).private_data }; 277 + let private = unsafe { (*file).private_data }.cast(); 278 278 // SAFETY: Ioctl calls can borrow the private data of the file. 279 279 let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) }; 280 280 // SAFETY:
+1 -1
rust/kernel/pci.rs
··· 89 89 extern "C" fn remove_callback(pdev: *mut bindings::pci_dev) { 90 90 // SAFETY: The PCI bus only ever calls the remove callback with a valid pointer to a 91 91 // `struct pci_dev`. 92 - let ptr = unsafe { bindings::pci_get_drvdata(pdev) }; 92 + let ptr = unsafe { bindings::pci_get_drvdata(pdev) }.cast(); 93 93 94 94 // SAFETY: `remove_callback` is only ever called after a successful call to 95 95 // `probe_callback`, hence it's guaranteed that `ptr` points to a valid and initialized
+1 -1
rust/kernel/platform.rs
··· 80 80 81 81 extern "C" fn remove_callback(pdev: *mut bindings::platform_device) { 82 82 // SAFETY: `pdev` is a valid pointer to a `struct platform_device`. 83 - let ptr = unsafe { bindings::platform_get_drvdata(pdev) }; 83 + let ptr = unsafe { bindings::platform_get_drvdata(pdev) }.cast(); 84 84 85 85 // SAFETY: `remove_callback` is only ever called after a successful call to 86 86 // `probe_callback`, hence it's guaranteed that `ptr` points to a valid and initialized
+12 -9
rust/kernel/sync/arc.rs
··· 140 140 _p: PhantomData<ArcInner<T>>, 141 141 } 142 142 143 + #[doc(hidden)] 143 144 #[pin_data] 144 145 #[repr(C)] 145 - struct ArcInner<T: ?Sized> { 146 + pub struct ArcInner<T: ?Sized> { 146 147 refcount: Opaque<bindings::refcount_t>, 147 148 data: T, 148 149 } ··· 372 371 } 373 372 } 374 373 375 - impl<T: 'static> ForeignOwnable for Arc<T> { 374 + // SAFETY: The `into_foreign` function returns a pointer that is well-aligned. 375 + unsafe impl<T: 'static> ForeignOwnable for Arc<T> { 376 + type PointedTo = ArcInner<T>; 376 377 type Borrowed<'a> = ArcBorrow<'a, T>; 377 378 type BorrowedMut<'a> = Self::Borrowed<'a>; 378 379 379 - fn into_foreign(self) -> *mut crate::ffi::c_void { 380 - ManuallyDrop::new(self).ptr.as_ptr().cast() 380 + fn into_foreign(self) -> *mut Self::PointedTo { 381 + ManuallyDrop::new(self).ptr.as_ptr() 381 382 } 382 383 383 - unsafe fn from_foreign(ptr: *mut crate::ffi::c_void) -> Self { 384 + unsafe fn from_foreign(ptr: *mut Self::PointedTo) -> Self { 384 385 // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous 385 386 // call to `Self::into_foreign`. 386 - let inner = unsafe { NonNull::new_unchecked(ptr.cast::<ArcInner<T>>()) }; 387 + let inner = unsafe { NonNull::new_unchecked(ptr) }; 387 388 388 389 // SAFETY: By the safety requirement of this function, we know that `ptr` came from 389 390 // a previous call to `Arc::into_foreign`, which guarantees that `ptr` is valid and ··· 393 390 unsafe { Self::from_inner(inner) } 394 391 } 395 392 396 - unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> ArcBorrow<'a, T> { 393 + unsafe fn borrow<'a>(ptr: *mut Self::PointedTo) -> ArcBorrow<'a, T> { 397 394 // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous 398 395 // call to `Self::into_foreign`. 399 - let inner = unsafe { NonNull::new_unchecked(ptr.cast::<ArcInner<T>>()) }; 396 + let inner = unsafe { NonNull::new_unchecked(ptr) }; 400 397 401 398 // SAFETY: The safety requirements of `from_foreign` ensure that the object remains alive 402 399 // for the lifetime of the returned value. 403 400 unsafe { ArcBorrow::new(inner) } 404 401 } 405 402 406 - unsafe fn borrow_mut<'a>(ptr: *mut crate::ffi::c_void) -> ArcBorrow<'a, T> { 403 + unsafe fn borrow_mut<'a>(ptr: *mut Self::PointedTo) -> ArcBorrow<'a, T> { 407 404 // SAFETY: The safety requirements for `borrow_mut` are a superset of the safety 408 405 // requirements for `borrow`. 409 406 unsafe { Self::borrow(ptr) }
+31 -15
rust/kernel/types.rs
··· 18 18 /// 19 19 /// This trait is meant to be used in cases when Rust objects are stored in C objects and 20 20 /// eventually "freed" back to Rust. 21 - pub trait ForeignOwnable: Sized { 21 + /// 22 + /// # Safety 23 + /// 24 + /// Implementers must ensure that [`into_foreign`] returns a pointer which meets the alignment 25 + /// requirements of [`PointedTo`]. 26 + /// 27 + /// [`into_foreign`]: Self::into_foreign 28 + /// [`PointedTo`]: Self::PointedTo 29 + pub unsafe trait ForeignOwnable: Sized { 30 + /// Type used when the value is foreign-owned. In practical terms only defines the alignment of 31 + /// the pointer. 32 + type PointedTo; 33 + 22 34 /// Type used to immutably borrow a value that is currently foreign-owned. 23 35 type Borrowed<'a>; 24 36 ··· 39 27 40 28 /// Converts a Rust-owned object to a foreign-owned one. 41 29 /// 42 - /// The foreign representation is a pointer to void. There are no guarantees for this pointer. 43 - /// For example, it might be invalid, dangling or pointing to uninitialized memory. Using it in 44 - /// any way except for [`from_foreign`], [`try_from_foreign`], [`borrow`], or [`borrow_mut`] can 45 - /// result in undefined behavior. 30 + /// # Guarantees 31 + /// 32 + /// The return value is guaranteed to be well-aligned, but there are no other guarantees for 33 + /// this pointer. For example, it might be null, dangling, or point to uninitialized memory. 34 + /// Using it in any way except for [`ForeignOwnable::from_foreign`], [`ForeignOwnable::borrow`], 35 + /// [`ForeignOwnable::try_from_foreign`] can result in undefined behavior. 46 36 /// 47 37 /// [`from_foreign`]: Self::from_foreign 48 38 /// [`try_from_foreign`]: Self::try_from_foreign 49 39 /// [`borrow`]: Self::borrow 50 40 /// [`borrow_mut`]: Self::borrow_mut 51 - fn into_foreign(self) -> *mut crate::ffi::c_void; 41 + fn into_foreign(self) -> *mut Self::PointedTo; 52 42 53 43 /// Converts a foreign-owned object back to a Rust-owned one. 54 44 /// ··· 60 46 /// must not be passed to `from_foreign` more than once. 61 47 /// 62 48 /// [`into_foreign`]: Self::into_foreign 63 - unsafe fn from_foreign(ptr: *mut crate::ffi::c_void) -> Self; 49 + unsafe fn from_foreign(ptr: *mut Self::PointedTo) -> Self; 64 50 65 51 /// Tries to convert a foreign-owned object back to a Rust-owned one. 66 52 /// ··· 72 58 /// `ptr` must either be null or satisfy the safety requirements for [`from_foreign`]. 73 59 /// 74 60 /// [`from_foreign`]: Self::from_foreign 75 - unsafe fn try_from_foreign(ptr: *mut crate::ffi::c_void) -> Option<Self> { 61 + unsafe fn try_from_foreign(ptr: *mut Self::PointedTo) -> Option<Self> { 76 62 if ptr.is_null() { 77 63 None 78 64 } else { ··· 95 81 /// 96 82 /// [`into_foreign`]: Self::into_foreign 97 83 /// [`from_foreign`]: Self::from_foreign 98 - unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> Self::Borrowed<'a>; 84 + unsafe fn borrow<'a>(ptr: *mut Self::PointedTo) -> Self::Borrowed<'a>; 99 85 100 86 /// Borrows a foreign-owned object mutably. 101 87 /// ··· 123 109 /// [`from_foreign`]: Self::from_foreign 124 110 /// [`borrow`]: Self::borrow 125 111 /// [`Arc`]: crate::sync::Arc 126 - unsafe fn borrow_mut<'a>(ptr: *mut crate::ffi::c_void) -> Self::BorrowedMut<'a>; 112 + unsafe fn borrow_mut<'a>(ptr: *mut Self::PointedTo) -> Self::BorrowedMut<'a>; 127 113 } 128 114 129 - impl ForeignOwnable for () { 115 + // SAFETY: The `into_foreign` function returns a pointer that is dangling, but well-aligned. 116 + unsafe impl ForeignOwnable for () { 117 + type PointedTo = (); 130 118 type Borrowed<'a> = (); 131 119 type BorrowedMut<'a> = (); 132 120 133 - fn into_foreign(self) -> *mut crate::ffi::c_void { 121 + fn into_foreign(self) -> *mut Self::PointedTo { 134 122 core::ptr::NonNull::dangling().as_ptr() 135 123 } 136 124 137 - unsafe fn from_foreign(_: *mut crate::ffi::c_void) -> Self {} 125 + unsafe fn from_foreign(_: *mut Self::PointedTo) -> Self {} 138 126 139 - unsafe fn borrow<'a>(_: *mut crate::ffi::c_void) -> Self::Borrowed<'a> {} 140 - unsafe fn borrow_mut<'a>(_: *mut crate::ffi::c_void) -> Self::BorrowedMut<'a> {} 127 + unsafe fn borrow<'a>(_: *mut Self::PointedTo) -> Self::Borrowed<'a> {} 128 + unsafe fn borrow_mut<'a>(_: *mut Self::PointedTo) -> Self::BorrowedMut<'a> {} 141 129 } 142 130 143 131 /// Runs a cleanup function/closure when dropped.
+275
rust/kernel/xarray.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! XArray abstraction. 4 + //! 5 + //! C header: [`include/linux/xarray.h`](srctree/include/linux/xarray.h) 6 + 7 + use crate::{ 8 + alloc, bindings, build_assert, 9 + error::{Error, Result}, 10 + types::{ForeignOwnable, NotThreadSafe, Opaque}, 11 + }; 12 + use core::{iter, marker::PhantomData, mem, pin::Pin, ptr::NonNull}; 13 + use pin_init::{pin_data, pin_init, pinned_drop, PinInit}; 14 + 15 + /// An array which efficiently maps sparse integer indices to owned objects. 16 + /// 17 + /// This is similar to a [`crate::alloc::kvec::Vec<Option<T>>`], but more efficient when there are 18 + /// holes in the index space, and can be efficiently grown. 19 + /// 20 + /// # Invariants 21 + /// 22 + /// `self.xa` is always an initialized and valid [`bindings::xarray`] whose entries are either 23 + /// `XA_ZERO_ENTRY` or came from `T::into_foreign`. 24 + /// 25 + /// # Examples 26 + /// 27 + /// ```rust 28 + /// use kernel::alloc::KBox; 29 + /// use kernel::xarray::{AllocKind, XArray}; 30 + /// 31 + /// let xa = KBox::pin_init(XArray::new(AllocKind::Alloc1), GFP_KERNEL)?; 32 + /// 33 + /// let dead = KBox::new(0xdead, GFP_KERNEL)?; 34 + /// let beef = KBox::new(0xbeef, GFP_KERNEL)?; 35 + /// 36 + /// let mut guard = xa.lock(); 37 + /// 38 + /// assert_eq!(guard.get(0), None); 39 + /// 40 + /// assert_eq!(guard.store(0, dead, GFP_KERNEL)?.as_deref(), None); 41 + /// assert_eq!(guard.get(0).copied(), Some(0xdead)); 42 + /// 43 + /// *guard.get_mut(0).unwrap() = 0xffff; 44 + /// assert_eq!(guard.get(0).copied(), Some(0xffff)); 45 + /// 46 + /// assert_eq!(guard.store(0, beef, GFP_KERNEL)?.as_deref().copied(), Some(0xffff)); 47 + /// assert_eq!(guard.get(0).copied(), Some(0xbeef)); 48 + /// 49 + /// guard.remove(0); 50 + /// assert_eq!(guard.get(0), None); 51 + /// 52 + /// # Ok::<(), Error>(()) 53 + /// ``` 54 + #[pin_data(PinnedDrop)] 55 + pub struct XArray<T: ForeignOwnable> { 56 + #[pin] 57 + xa: Opaque<bindings::xarray>, 58 + _p: PhantomData<T>, 59 + } 60 + 61 + #[pinned_drop] 62 + impl<T: ForeignOwnable> PinnedDrop for XArray<T> { 63 + fn drop(self: Pin<&mut Self>) { 64 + self.iter().for_each(|ptr| { 65 + let ptr = ptr.as_ptr(); 66 + // SAFETY: `ptr` came from `T::into_foreign`. 67 + // 68 + // INVARIANT: we own the only reference to the array which is being dropped so the 69 + // broken invariant is not observable on function exit. 70 + drop(unsafe { T::from_foreign(ptr) }) 71 + }); 72 + 73 + // SAFETY: `self.xa` is always valid by the type invariant. 74 + unsafe { bindings::xa_destroy(self.xa.get()) }; 75 + } 76 + } 77 + 78 + /// Flags passed to [`XArray::new`] to configure the array's allocation tracking behavior. 79 + pub enum AllocKind { 80 + /// Consider the first element to be at index 0. 81 + Alloc, 82 + /// Consider the first element to be at index 1. 83 + Alloc1, 84 + } 85 + 86 + impl<T: ForeignOwnable> XArray<T> { 87 + /// Creates a new initializer for this type. 88 + pub fn new(kind: AllocKind) -> impl PinInit<Self> { 89 + let flags = match kind { 90 + AllocKind::Alloc => bindings::XA_FLAGS_ALLOC, 91 + AllocKind::Alloc1 => bindings::XA_FLAGS_ALLOC1, 92 + }; 93 + pin_init!(Self { 94 + // SAFETY: `xa` is valid while the closure is called. 95 + // 96 + // INVARIANT: `xa` is initialized here to an empty, valid [`bindings::xarray`]. 97 + xa <- Opaque::ffi_init(|xa| unsafe { 98 + bindings::xa_init_flags(xa, flags) 99 + }), 100 + _p: PhantomData, 101 + }) 102 + } 103 + 104 + fn iter(&self) -> impl Iterator<Item = NonNull<T::PointedTo>> + '_ { 105 + let mut index = 0; 106 + 107 + // SAFETY: `self.xa` is always valid by the type invariant. 108 + iter::once(unsafe { 109 + bindings::xa_find(self.xa.get(), &mut index, usize::MAX, bindings::XA_PRESENT) 110 + }) 111 + .chain(iter::from_fn(move || { 112 + // SAFETY: `self.xa` is always valid by the type invariant. 113 + Some(unsafe { 114 + bindings::xa_find_after(self.xa.get(), &mut index, usize::MAX, bindings::XA_PRESENT) 115 + }) 116 + })) 117 + .map_while(|ptr| NonNull::new(ptr.cast())) 118 + } 119 + 120 + /// Attempts to lock the [`XArray`] for exclusive access. 121 + pub fn try_lock(&self) -> Option<Guard<'_, T>> { 122 + // SAFETY: `self.xa` is always valid by the type invariant. 123 + if (unsafe { bindings::xa_trylock(self.xa.get()) } != 0) { 124 + Some(Guard { 125 + xa: self, 126 + _not_send: NotThreadSafe, 127 + }) 128 + } else { 129 + None 130 + } 131 + } 132 + 133 + /// Locks the [`XArray`] for exclusive access. 134 + pub fn lock(&self) -> Guard<'_, T> { 135 + // SAFETY: `self.xa` is always valid by the type invariant. 136 + unsafe { bindings::xa_lock(self.xa.get()) }; 137 + 138 + Guard { 139 + xa: self, 140 + _not_send: NotThreadSafe, 141 + } 142 + } 143 + } 144 + 145 + /// A lock guard. 146 + /// 147 + /// The lock is unlocked when the guard goes out of scope. 148 + #[must_use = "the lock unlocks immediately when the guard is unused"] 149 + pub struct Guard<'a, T: ForeignOwnable> { 150 + xa: &'a XArray<T>, 151 + _not_send: NotThreadSafe, 152 + } 153 + 154 + impl<T: ForeignOwnable> Drop for Guard<'_, T> { 155 + fn drop(&mut self) { 156 + // SAFETY: 157 + // - `self.xa.xa` is always valid by the type invariant. 158 + // - The caller holds the lock, so it is safe to unlock it. 159 + unsafe { bindings::xa_unlock(self.xa.xa.get()) }; 160 + } 161 + } 162 + 163 + /// The error returned by [`store`](Guard::store). 164 + /// 165 + /// Contains the underlying error and the value that was not stored. 166 + pub struct StoreError<T> { 167 + /// The error that occurred. 168 + pub error: Error, 169 + /// The value that was not stored. 170 + pub value: T, 171 + } 172 + 173 + impl<T> From<StoreError<T>> for Error { 174 + fn from(value: StoreError<T>) -> Self { 175 + value.error 176 + } 177 + } 178 + 179 + impl<'a, T: ForeignOwnable> Guard<'a, T> { 180 + fn load<F, U>(&self, index: usize, f: F) -> Option<U> 181 + where 182 + F: FnOnce(NonNull<T::PointedTo>) -> U, 183 + { 184 + // SAFETY: `self.xa.xa` is always valid by the type invariant. 185 + let ptr = unsafe { bindings::xa_load(self.xa.xa.get(), index) }; 186 + let ptr = NonNull::new(ptr.cast())?; 187 + Some(f(ptr)) 188 + } 189 + 190 + /// Provides a reference to the element at the given index. 191 + pub fn get(&self, index: usize) -> Option<T::Borrowed<'_>> { 192 + self.load(index, |ptr| { 193 + // SAFETY: `ptr` came from `T::into_foreign`. 194 + unsafe { T::borrow(ptr.as_ptr()) } 195 + }) 196 + } 197 + 198 + /// Provides a mutable reference to the element at the given index. 199 + pub fn get_mut(&mut self, index: usize) -> Option<T::BorrowedMut<'_>> { 200 + self.load(index, |ptr| { 201 + // SAFETY: `ptr` came from `T::into_foreign`. 202 + unsafe { T::borrow_mut(ptr.as_ptr()) } 203 + }) 204 + } 205 + 206 + /// Removes and returns the element at the given index. 207 + pub fn remove(&mut self, index: usize) -> Option<T> { 208 + // SAFETY: 209 + // - `self.xa.xa` is always valid by the type invariant. 210 + // - The caller holds the lock. 211 + let ptr = unsafe { bindings::__xa_erase(self.xa.xa.get(), index) }.cast(); 212 + // SAFETY: 213 + // - `ptr` is either NULL or came from `T::into_foreign`. 214 + // - `&mut self` guarantees that the lifetimes of [`T::Borrowed`] and [`T::BorrowedMut`] 215 + // borrowed from `self` have ended. 216 + unsafe { T::try_from_foreign(ptr) } 217 + } 218 + 219 + /// Stores an element at the given index. 220 + /// 221 + /// May drop the lock if needed to allocate memory, and then reacquire it afterwards. 222 + /// 223 + /// On success, returns the element which was previously at the given index. 224 + /// 225 + /// On failure, returns the element which was attempted to be stored. 226 + pub fn store( 227 + &mut self, 228 + index: usize, 229 + value: T, 230 + gfp: alloc::Flags, 231 + ) -> Result<Option<T>, StoreError<T>> { 232 + build_assert!( 233 + mem::align_of::<T::PointedTo>() >= 4, 234 + "pointers stored in XArray must be 4-byte aligned" 235 + ); 236 + let new = value.into_foreign(); 237 + 238 + let old = { 239 + let new = new.cast(); 240 + // SAFETY: 241 + // - `self.xa.xa` is always valid by the type invariant. 242 + // - The caller holds the lock. 243 + // 244 + // INVARIANT: `new` came from `T::into_foreign`. 245 + unsafe { bindings::__xa_store(self.xa.xa.get(), index, new, gfp.as_raw()) } 246 + }; 247 + 248 + // SAFETY: `__xa_store` returns the old entry at this index on success or `xa_err` if an 249 + // error happened. 250 + let errno = unsafe { bindings::xa_err(old) }; 251 + if errno != 0 { 252 + // SAFETY: `new` came from `T::into_foreign` and `__xa_store` does not take 253 + // ownership of the value on error. 254 + let value = unsafe { T::from_foreign(new) }; 255 + Err(StoreError { 256 + value, 257 + error: Error::from_errno(errno), 258 + }) 259 + } else { 260 + let old = old.cast(); 261 + // SAFETY: `ptr` is either NULL or came from `T::into_foreign`. 262 + // 263 + // NB: `XA_ZERO_ENTRY` is never returned by functions belonging to the Normal XArray 264 + // API; such entries present as `NULL`. 265 + Ok(unsafe { T::try_from_foreign(old) }) 266 + } 267 + } 268 + } 269 + 270 + // SAFETY: `XArray<T>` has no shared mutable state so it is `Send` iff `T` is `Send`. 271 + unsafe impl<T: ForeignOwnable + Send> Send for XArray<T> {} 272 + 273 + // SAFETY: `XArray<T>` serialises the interior mutability it provides so it is `Sync` iff `T` is 274 + // `Send`. 275 + unsafe impl<T: ForeignOwnable + Send> Sync for XArray<T> {}