rust: init: update init
module to take allocation flags
This is the last component in the conversion for allocators to take allocation flags as parameters. Reviewed-by: Benno Lossin <benno.lossin@proton.me> Signed-off-by: Wedson Almeida Filho <walmeida@microsoft.com> Link: https://lore.kernel.org/r/20240328013603.206764-10-wedsonaf@gmail.com Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
parent
cc41670e06
commit
c34aa00d1d
@ -68,7 +68,7 @@
|
||||
//! # a <- new_mutex!(42, "Foo::a"),
|
||||
//! # b: 24,
|
||||
//! # });
|
||||
//! let foo: Result<Pin<Box<Foo>>> = Box::pin_init(foo);
|
||||
//! let foo: Result<Pin<Box<Foo>>> = Box::pin_init(foo, GFP_KERNEL);
|
||||
//! ```
|
||||
//!
|
||||
//! For more information see the [`pin_init!`] macro.
|
||||
@ -80,7 +80,8 @@
|
||||
//!
|
||||
//! ```rust
|
||||
//! # use kernel::sync::{new_mutex, Arc, Mutex};
|
||||
//! let mtx: Result<Arc<Mutex<usize>>> = Arc::pin_init(new_mutex!(42, "example::mtx"));
|
||||
//! let mtx: Result<Arc<Mutex<usize>>> =
|
||||
//! Arc::pin_init(new_mutex!(42, "example::mtx"), GFP_KERNEL);
|
||||
//! ```
|
||||
//!
|
||||
//! To declare an init macro/function you just return an [`impl PinInit<T, E>`]:
|
||||
@ -99,7 +100,7 @@
|
||||
//! fn new() -> impl PinInit<Self, Error> {
|
||||
//! try_pin_init!(Self {
|
||||
//! status <- new_mutex!(0, "DriverData::status"),
|
||||
//! buffer: Box::init(kernel::init::zeroed())?,
|
||||
//! buffer: Box::init(kernel::init::zeroed(), GFP_KERNEL)?,
|
||||
//! })
|
||||
//! }
|
||||
//! }
|
||||
@ -210,7 +211,7 @@
|
||||
//! [`pin_init!`]: crate::pin_init!
|
||||
|
||||
use crate::{
|
||||
alloc::{box_ext::BoxExt, flags::*},
|
||||
alloc::{box_ext::BoxExt, Flags},
|
||||
error::{self, Error},
|
||||
sync::UniqueArc,
|
||||
types::{Opaque, ScopeGuard},
|
||||
@ -391,7 +392,7 @@ macro_rules! stack_try_pin_init {
|
||||
/// },
|
||||
/// });
|
||||
/// # initializer }
|
||||
/// # Box::pin_init(demo()).unwrap();
|
||||
/// # Box::pin_init(demo(), GFP_KERNEL).unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// Arbitrary Rust expressions can be used to set the value of a variable.
|
||||
@ -461,7 +462,7 @@ macro_rules! stack_try_pin_init {
|
||||
/// # })
|
||||
/// # }
|
||||
/// # }
|
||||
/// let foo = Box::pin_init(Foo::new());
|
||||
/// let foo = Box::pin_init(Foo::new(), GFP_KERNEL);
|
||||
/// ```
|
||||
///
|
||||
/// They can also easily embed it into their own `struct`s:
|
||||
@ -601,7 +602,7 @@ macro_rules! pin_init {
|
||||
/// impl BigBuf {
|
||||
/// fn new() -> impl PinInit<Self, Error> {
|
||||
/// try_pin_init!(Self {
|
||||
/// big: Box::init(init::zeroed())?,
|
||||
/// big: Box::init(init::zeroed(), GFP_KERNEL)?,
|
||||
/// small: [0; 1024 * 1024],
|
||||
/// ptr: core::ptr::null_mut(),
|
||||
/// }? Error)
|
||||
@ -702,7 +703,7 @@ macro_rules! init {
|
||||
/// impl BigBuf {
|
||||
/// fn new() -> impl Init<Self, Error> {
|
||||
/// try_init!(Self {
|
||||
/// big: Box::init(zeroed())?,
|
||||
/// big: Box::init(zeroed(), GFP_KERNEL)?,
|
||||
/// small: [0; 1024 * 1024],
|
||||
/// }? Error)
|
||||
/// }
|
||||
@ -1014,7 +1015,7 @@ pub fn uninit<T, E>() -> impl Init<MaybeUninit<T>, E> {
|
||||
///
|
||||
/// ```rust
|
||||
/// use kernel::{error::Error, init::init_array_from_fn};
|
||||
/// let array: Box<[usize; 1_000]> = Box::init::<Error>(init_array_from_fn(|i| i)).unwrap();
|
||||
/// let array: Box<[usize; 1_000]> = Box::init::<Error>(init_array_from_fn(|i| i), GFP_KERNEL).unwrap();
|
||||
/// assert_eq!(array.len(), 1_000);
|
||||
/// ```
|
||||
pub fn init_array_from_fn<I, const N: usize, T, E>(
|
||||
@ -1058,7 +1059,7 @@ where
|
||||
/// ```rust
|
||||
/// use kernel::{sync::{Arc, Mutex}, init::pin_init_array_from_fn, new_mutex};
|
||||
/// let array: Arc<[Mutex<usize>; 1_000]> =
|
||||
/// Arc::pin_init(pin_init_array_from_fn(|i| new_mutex!(i))).unwrap();
|
||||
/// Arc::pin_init(pin_init_array_from_fn(|i| new_mutex!(i)), GFP_KERNEL).unwrap();
|
||||
/// assert_eq!(array.len(), 1_000);
|
||||
/// ```
|
||||
pub fn pin_init_array_from_fn<I, const N: usize, T, E>(
|
||||
@ -1116,7 +1117,7 @@ pub trait InPlaceInit<T>: Sized {
|
||||
/// type.
|
||||
///
|
||||
/// If `T: !Unpin` it will not be able to move afterwards.
|
||||
fn try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Pin<Self>, E>
|
||||
fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Pin<Self>, E>
|
||||
where
|
||||
E: From<AllocError>;
|
||||
|
||||
@ -1124,7 +1125,7 @@ pub trait InPlaceInit<T>: Sized {
|
||||
/// type.
|
||||
///
|
||||
/// If `T: !Unpin` it will not be able to move afterwards.
|
||||
fn pin_init<E>(init: impl PinInit<T, E>) -> error::Result<Pin<Self>>
|
||||
fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Pin<Self>>
|
||||
where
|
||||
Error: From<E>,
|
||||
{
|
||||
@ -1132,16 +1133,16 @@ pub trait InPlaceInit<T>: Sized {
|
||||
let init = unsafe {
|
||||
pin_init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))
|
||||
};
|
||||
Self::try_pin_init(init)
|
||||
Self::try_pin_init(init, flags)
|
||||
}
|
||||
|
||||
/// Use the given initializer to in-place initialize a `T`.
|
||||
fn try_init<E>(init: impl Init<T, E>) -> Result<Self, E>
|
||||
fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
|
||||
where
|
||||
E: From<AllocError>;
|
||||
|
||||
/// Use the given initializer to in-place initialize a `T`.
|
||||
fn init<E>(init: impl Init<T, E>) -> error::Result<Self>
|
||||
fn init<E>(init: impl Init<T, E>, flags: Flags) -> error::Result<Self>
|
||||
where
|
||||
Error: From<E>,
|
||||
{
|
||||
@ -1149,17 +1150,17 @@ pub trait InPlaceInit<T>: Sized {
|
||||
let init = unsafe {
|
||||
init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))
|
||||
};
|
||||
Self::try_init(init)
|
||||
Self::try_init(init, flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> InPlaceInit<T> for Box<T> {
|
||||
#[inline]
|
||||
fn try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Pin<Self>, E>
|
||||
fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Pin<Self>, E>
|
||||
where
|
||||
E: From<AllocError>,
|
||||
{
|
||||
let mut this = <Box<_> as BoxExt<_>>::new_uninit(GFP_KERNEL)?;
|
||||
let mut this = <Box<_> as BoxExt<_>>::new_uninit(flags)?;
|
||||
let slot = this.as_mut_ptr();
|
||||
// SAFETY: When init errors/panics, slot will get deallocated but not dropped,
|
||||
// slot is valid and will not be moved, because we pin it later.
|
||||
@ -1169,11 +1170,11 @@ impl<T> InPlaceInit<T> for Box<T> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_init<E>(init: impl Init<T, E>) -> Result<Self, E>
|
||||
fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
|
||||
where
|
||||
E: From<AllocError>,
|
||||
{
|
||||
let mut this = <Box<_> as BoxExt<_>>::new_uninit(GFP_KERNEL)?;
|
||||
let mut this = <Box<_> as BoxExt<_>>::new_uninit(flags)?;
|
||||
let slot = this.as_mut_ptr();
|
||||
// SAFETY: When init errors/panics, slot will get deallocated but not dropped,
|
||||
// slot is valid.
|
||||
@ -1185,11 +1186,11 @@ impl<T> InPlaceInit<T> for Box<T> {
|
||||
|
||||
impl<T> InPlaceInit<T> for UniqueArc<T> {
|
||||
#[inline]
|
||||
fn try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Pin<Self>, E>
|
||||
fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Pin<Self>, E>
|
||||
where
|
||||
E: From<AllocError>,
|
||||
{
|
||||
let mut this = UniqueArc::new_uninit(GFP_KERNEL)?;
|
||||
let mut this = UniqueArc::new_uninit(flags)?;
|
||||
let slot = this.as_mut_ptr();
|
||||
// SAFETY: When init errors/panics, slot will get deallocated but not dropped,
|
||||
// slot is valid and will not be moved, because we pin it later.
|
||||
@ -1199,11 +1200,11 @@ impl<T> InPlaceInit<T> for UniqueArc<T> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_init<E>(init: impl Init<T, E>) -> Result<Self, E>
|
||||
fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
|
||||
where
|
||||
E: From<AllocError>,
|
||||
{
|
||||
let mut this = UniqueArc::new_uninit(GFP_KERNEL)?;
|
||||
let mut this = UniqueArc::new_uninit(flags)?;
|
||||
let slot = this.as_mut_ptr();
|
||||
// SAFETY: When init errors/panics, slot will get deallocated but not dropped,
|
||||
// slot is valid.
|
||||
|
@ -182,22 +182,22 @@ impl<T> Arc<T> {
|
||||
///
|
||||
/// If `T: !Unpin` it will not be able to move afterwards.
|
||||
#[inline]
|
||||
pub fn pin_init<E>(init: impl PinInit<T, E>) -> error::Result<Self>
|
||||
pub fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Self>
|
||||
where
|
||||
Error: From<E>,
|
||||
{
|
||||
UniqueArc::pin_init(init).map(|u| u.into())
|
||||
UniqueArc::pin_init(init, flags).map(|u| u.into())
|
||||
}
|
||||
|
||||
/// Use the given initializer to in-place initialize a `T`.
|
||||
///
|
||||
/// This is equivalent to [`Arc<T>::pin_init`], since an [`Arc`] is always pinned.
|
||||
#[inline]
|
||||
pub fn init<E>(init: impl Init<T, E>) -> error::Result<Self>
|
||||
pub fn init<E>(init: impl Init<T, E>, flags: Flags) -> error::Result<Self>
|
||||
where
|
||||
Error: From<E>,
|
||||
{
|
||||
UniqueArc::init(init).map(|u| u.into())
|
||||
UniqueArc::init(init, flags).map(|u| u.into())
|
||||
}
|
||||
}
|
||||
|
||||
@ -565,13 +565,16 @@ impl<T> UniqueArc<T> {
|
||||
}
|
||||
|
||||
/// Tries to allocate a new [`UniqueArc`] instance whose contents are not initialised yet.
|
||||
pub fn new_uninit(_flags: Flags) -> Result<UniqueArc<MaybeUninit<T>>, AllocError> {
|
||||
pub fn new_uninit(flags: Flags) -> Result<UniqueArc<MaybeUninit<T>>, AllocError> {
|
||||
// INVARIANT: The refcount is initialised to a non-zero value.
|
||||
let inner = Box::try_init::<AllocError>(try_init!(ArcInner {
|
||||
// SAFETY: There are no safety requirements for this FFI call.
|
||||
refcount: Opaque::new(unsafe { bindings::REFCOUNT_INIT(1) }),
|
||||
data <- init::uninit::<T, AllocError>(),
|
||||
}? AllocError))?;
|
||||
let inner = Box::try_init::<AllocError>(
|
||||
try_init!(ArcInner {
|
||||
// SAFETY: There are no safety requirements for this FFI call.
|
||||
refcount: Opaque::new(unsafe { bindings::REFCOUNT_INIT(1) }),
|
||||
data <- init::uninit::<T, AllocError>(),
|
||||
}? AllocError),
|
||||
flags,
|
||||
)?;
|
||||
Ok(UniqueArc {
|
||||
// INVARIANT: The newly-created object has a refcount of 1.
|
||||
// SAFETY: The pointer from the `Box` is valid.
|
||||
|
@ -75,7 +75,7 @@ pub use new_condvar;
|
||||
/// Box::pin_init(pin_init!(Example {
|
||||
/// value <- new_mutex!(0),
|
||||
/// value_changed <- new_condvar!(),
|
||||
/// }))
|
||||
/// }), GFP_KERNEL)
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
|
@ -60,7 +60,7 @@ pub use new_mutex;
|
||||
/// }
|
||||
///
|
||||
/// // Allocate a boxed `Example`.
|
||||
/// let e = Box::pin_init(Example::new())?;
|
||||
/// let e = Box::pin_init(Example::new(), GFP_KERNEL)?;
|
||||
/// assert_eq!(e.c, 10);
|
||||
/// assert_eq!(e.d.lock().a, 20);
|
||||
/// assert_eq!(e.d.lock().b, 30);
|
||||
|
@ -58,7 +58,7 @@ pub use new_spinlock;
|
||||
/// }
|
||||
///
|
||||
/// // Allocate a boxed `Example`.
|
||||
/// let e = Box::pin_init(Example::new())?;
|
||||
/// let e = Box::pin_init(Example::new(), GFP_KERNEL)?;
|
||||
/// assert_eq!(e.c, 10);
|
||||
/// assert_eq!(e.d.lock().a, 20);
|
||||
/// assert_eq!(e.d.lock().b, 30);
|
||||
|
@ -53,7 +53,7 @@
|
||||
//! Arc::pin_init(pin_init!(MyStruct {
|
||||
//! value,
|
||||
//! work <- new_work!("MyStruct::work"),
|
||||
//! }))
|
||||
//! }), GFP_KERNEL)
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
@ -101,7 +101,7 @@
|
||||
//! value_2,
|
||||
//! work_1 <- new_work!("MyStruct::work_1"),
|
||||
//! work_2 <- new_work!("MyStruct::work_2"),
|
||||
//! }))
|
||||
//! }), GFP_KERNEL)
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
@ -132,6 +132,7 @@
|
||||
//!
|
||||
//! C header: [`include/linux/workqueue.h`](srctree/include/linux/workqueue.h)
|
||||
|
||||
use crate::alloc::Flags;
|
||||
use crate::{bindings, prelude::*, sync::Arc, sync::LockClassKey, types::Opaque};
|
||||
use alloc::alloc::AllocError;
|
||||
use alloc::boxed::Box;
|
||||
@ -210,13 +211,17 @@ impl Queue {
|
||||
/// Tries to spawn the given function or closure as a work item.
|
||||
///
|
||||
/// This method can fail because it allocates memory to store the work item.
|
||||
pub fn try_spawn<T: 'static + Send + FnOnce()>(&self, func: T) -> Result<(), AllocError> {
|
||||
pub fn try_spawn<T: 'static + Send + FnOnce()>(
|
||||
&self,
|
||||
flags: Flags,
|
||||
func: T,
|
||||
) -> Result<(), AllocError> {
|
||||
let init = pin_init!(ClosureWork {
|
||||
work <- new_work!("Queue::try_spawn"),
|
||||
func: Some(func),
|
||||
});
|
||||
|
||||
self.enqueue(Box::pin_init(init).map_err(|_| AllocError)?);
|
||||
self.enqueue(Box::pin_init(init, flags).map_err(|_| AllocError)?);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user