Skip to content

Instantly share code, notes, and snippets.

@ellcs
Created May 30, 2024 20:00
Show Gist options
  • Save ellcs/cf19804bed1e1c709bc02accd9c1230e to your computer and use it in GitHub Desktop.
Save ellcs/cf19804bed1e1c709bc02accd9c1230e to your computer and use it in GitHub Desktop.
commit d15c08793a46e2776b4fbc0d01545a1035d024b2
Author: idc <idc>
Date: Tue May 28 14:11:48 2024 -0700
Add associated type for pinnedresult
diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs
index 424257284..9eb78b7f3 100644
--- a/rust/kernel/init.rs
+++ b/rust/kernel/init.rs
@@ -202,24 +202,25 @@
//! [stack]: crate::stack_pin_init
//! [`Arc<T>`]: crate::sync::Arc
//! [`impl PinInit<Foo>`]: PinInit
//! [`impl PinInit<T, E>`]: PinInit
//! [`impl Init<T, E>`]: Init
//! [`Opaque`]: kernel::types::Opaque
//! [`Opaque::ffi_init`]: kernel::types::Opaque::ffi_init
//! [`pin_data`]: ::macros::pin_data
//! [`pin_init!`]: crate::pin_init!
use crate::{
error::{self, Error},
+ sync::Arc,
sync::UniqueArc,
types::{Opaque, ScopeGuard},
};
use alloc::boxed::Box;
use core::{
alloc::AllocError,
cell::UnsafeCell,
convert::Infallible,
marker::PhantomData,
mem::MaybeUninit,
num::*,
pin::Pin,
@@ -1102,37 +1103,41 @@ unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
}
}
// SAFETY: Every type can be initialized by-value. `__pinned_init` calls `__init`.
unsafe impl<T, E> PinInit<T, E> for T {
unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
unsafe { self.__init(slot) }
}
}
/// Smart pointer that can initialize memory in-place.
pub trait InPlaceInit<T>: Sized {
+ /// A type might be pinned implicitly. An addtional `Pin<ImplicitlyPinned>` is useless. In
+ /// doubt, the type can just be set to `Pin<Self>`.
+ type PinnedResult;
+
/// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
/// 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>) -> Result<Self::PinnedResult, E>
where
E: From<AllocError>;
/// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
/// 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>) -> error::Result<Self::PinnedResult>
where
Error: From<E>,
{
// SAFETY: We delegate to `init` and only change the error type.
let init = unsafe {
pin_init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))
};
Self::try_pin_init(init)
}
/// Use the given initializer to in-place initialize a `T`.
fn try_init<E>(init: impl Init<T, E>) -> Result<Self, E>
@@ -1143,27 +1148,55 @@ fn try_init<E>(init: impl Init<T, E>) -> Result<Self, E>
fn init<E>(init: impl Init<T, E>) -> error::Result<Self>
where
Error: From<E>,
{
// SAFETY: We delegate to `init` and only change the error type.
let init = unsafe {
init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))
};
Self::try_init(init)
}
}
+// ```
+// # use kernel::sync::{new_mutex, Arc, Mutex};
+// let mtx: Result<Arc<Mutex<usize>>> = Arc::pin_init(new_mutex!(42, "example::mtx"));
+// ```
+impl<T> InPlaceInit<T> for Arc<T> {
+ type PinnedResult = Self;
+
+ #[inline]
+ fn try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Self::PinnedResult, E>
+ where
+ E: From<AllocError>,
+ {
+ UniqueArc::try_pin_init(init).map(|u| u.into())
+ }
+
+
+ #[inline]
+ fn try_init<E>(init: impl Init<T, E>) -> Result<Self, E>
+ where
+ E: From<AllocError>,
+ {
+ //kernel::sync::Arc::init(init).map_err(|e| e.into())
+ UniqueArc::try_init(init).map(|u| u.into())
+ }
+}
+
impl<T> InPlaceInit<T> for Box<T> {
+ type PinnedResult = Pin<Self>;
+
#[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>) -> Result<Self::PinnedResult, E>
where
E: From<AllocError>,
{
let mut this = Box::try_new_uninit()?;
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.
unsafe { init.__pinned_init(slot)? };
// SAFETY: All fields have been initialized.
Ok(unsafe { this.assume_init() }.into())
}
@@ -1174,26 +1207,28 @@ fn try_init<E>(init: impl Init<T, E>) -> Result<Self, E>
{
let mut this = Box::try_new_uninit()?;
let slot = this.as_mut_ptr();
// SAFETY: When init errors/panics, slot will get deallocated but not dropped,
// slot is valid.
unsafe { init.__init(slot)? };
// SAFETY: All fields have been initialized.
Ok(unsafe { this.assume_init() })
}
}
impl<T> InPlaceInit<T> for UniqueArc<T> {
+ type PinnedResult = Pin<Self>;
+
#[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>) -> Result<Self::PinnedResult, E>
where
E: From<AllocError>,
{
let mut this = UniqueArc::try_new_uninit()?;
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.
unsafe { init.__pinned_init(slot)? };
// SAFETY: All fields have been initialized.
Ok(unsafe { this.assume_init() }.into())
}
diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
index 7d4c4bf58..fd0e87115 100644
--- a/rust/kernel/sync/arc.rs
+++ b/rust/kernel/sync/arc.rs
@@ -3,30 +3,30 @@
//! A reference-counted pointer.
//!
//! This module implements a way for users to create reference-counted objects and pointers to
//! them. Such a pointer automatically increments and decrements the count, and drops the
//! underlying object when it reaches zero. It is also safe to use concurrently from multiple
//! threads.
//!
//! It is different from the standard library's [`Arc`] in a few ways:
//! 1. It is backed by the kernel's `refcount_t` type.
//! 2. It does not support weak references, which allows it to be half the size.
//! 3. It saturates the reference count instead of aborting when it goes over a threshold.
//! 4. It does not provide a `get_mut` method, so the ref counted object is pinned.
+//! 5. The object in [`Arc`] is pinned implicitly.
//!
//! [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html
use crate::{
bindings,
- error::{self, Error},
init::{self, InPlaceInit, Init, PinInit},
try_init,
types::{ForeignOwnable, Opaque},
};
use alloc::boxed::Box;
use core::{
alloc::{AllocError, Layout},
fmt,
marker::{PhantomData, Unsize},
mem::{ManuallyDrop, MaybeUninit},
ops::{Deref, DerefMut},
pin::Pin,
@@ -168,45 +168,45 @@ pub fn try_new(contents: T) -> Result<Self, AllocError> {
// SAFETY: There are no safety requirements for this FFI call.
refcount: Opaque::new(unsafe { bindings::REFCOUNT_INIT(1) }),
data: contents,
};
let inner = Box::try_new(value)?;
// SAFETY: We just created `inner` with a reference count of 1, which is owned by the new
// `Arc` object.
Ok(unsafe { Self::from_inner(Box::leak(inner).into()) })
}
- /// Use the given initializer to in-place initialize a `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>
- where
- Error: From<E>,
- {
- UniqueArc::pin_init(init).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>
- where
- Error: From<E>,
- {
- UniqueArc::init(init).map(|u| u.into())
- }
+ ///// Use the given initializer to in-place initialize a `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>
+ //where
+ // Error: From<E>,
+ //{
+ // UniqueArc::pin_init(init).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>
+ //where
+ // Error: From<E>,
+ //{
+ // UniqueArc::init(init).map(|u| u.into())
+ //}
}
impl<T: ?Sized> Arc<T> {
/// Constructs a new [`Arc`] from an existing [`ArcInner`].
///
/// # Safety
///
/// The caller must ensure that `inner` points to a valid location and has a non-zero reference
/// count, one of which will be owned by the new [`Arc`] instance.
unsafe fn from_inner(inner: NonNull<ArcInner<T>>) -> Self {
// INVARIANT: By the safety requirements, the invariants hold.
Arc {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment