diff options
Diffstat (limited to 'rust/kernel/sync/arc.rs')
| -rw-r--r-- | rust/kernel/sync/arc.rs | 65 | 
1 files changed, 48 insertions, 17 deletions
| diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs index fa4509406ee9..3cefda7a4372 100644 --- a/rust/kernel/sync/arc.rs +++ b/rust/kernel/sync/arc.rs @@ -26,7 +26,7 @@ use crate::{  use core::{      alloc::Layout,      fmt, -    marker::{PhantomData, Unsize}, +    marker::PhantomData,      mem::{ManuallyDrop, MaybeUninit},      ops::{Deref, DerefMut},      pin::Pin, @@ -125,8 +125,18 @@ mod std_vendor;  /// let coerced: Arc<dyn MyTrait> = obj;  /// # Ok::<(), Error>(())  /// ``` +#[repr(transparent)] +#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))]  pub struct Arc<T: ?Sized> {      ptr: NonNull<ArcInner<T>>, +    // NB: this informs dropck that objects of type `ArcInner<T>` may be used in `<Arc<T> as +    // Drop>::drop`. Note that dropck already assumes that objects of type `T` may be used in +    // `<Arc<T> as Drop>::drop` and the distinction between `T` and `ArcInner<T>` is not presently +    // meaningful with respect to dropck - but this may change in the future so this is left here +    // out of an abundance of caution. +    // +    // See https://doc.rust-lang.org/nomicon/phantom-data.html#generic-parameters-and-drop-checking +    // for more detail on the semantics of dropck in the presence of `PhantomData`.      _p: PhantomData<ArcInner<T>>,  } @@ -172,10 +182,12 @@ impl<T: ?Sized> ArcInner<T> {  // This is to allow coercion from `Arc<T>` to `Arc<U>` if `T` can be converted to the  // dynamically-sized type (DST) `U`. -impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::CoerceUnsized<Arc<U>> for Arc<T> {} +#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))] +impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::CoerceUnsized<Arc<U>> for Arc<T> {}  // This is to allow `Arc<U>` to be dispatched on when `Arc<T>` can be coerced into `Arc<U>`. -impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<Arc<U>> for Arc<T> {} +#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))] +impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<Arc<U>> for Arc<T> {}  // SAFETY: It is safe to send `Arc<T>` to another thread when the underlying `T` is `Sync` because  // it effectively means sharing `&T` (which is safe because `T` is `Sync`); additionally, it needs @@ -201,10 +213,11 @@ impl<T> Arc<T> {          };          let inner = KBox::new(value, flags)?; +        let inner = KBox::leak(inner).into();          // SAFETY: We just created `inner` with a reference count of 1, which is owned by the new          // `Arc` object. -        Ok(unsafe { Self::from_inner(KBox::leak(inner).into()) }) +        Ok(unsafe { Self::from_inner(inner) })      }  } @@ -331,26 +344,37 @@ impl<T: ?Sized> Arc<T> {  impl<T: 'static> ForeignOwnable for Arc<T> {      type Borrowed<'a> = ArcBorrow<'a, T>; +    type BorrowedMut<'a> = Self::Borrowed<'a>; -    fn into_foreign(self) -> *const crate::ffi::c_void { -        ManuallyDrop::new(self).ptr.as_ptr() as _ +    fn into_foreign(self) -> *mut crate::ffi::c_void { +        ManuallyDrop::new(self).ptr.as_ptr().cast()      } -    unsafe fn borrow<'a>(ptr: *const crate::ffi::c_void) -> ArcBorrow<'a, T> { -        // By the safety requirement of this function, we know that `ptr` came from -        // a previous call to `Arc::into_foreign`. -        let inner = NonNull::new(ptr as *mut ArcInner<T>).unwrap(); +    unsafe fn from_foreign(ptr: *mut crate::ffi::c_void) -> Self { +        // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous +        // call to `Self::into_foreign`. +        let inner = unsafe { NonNull::new_unchecked(ptr.cast::<ArcInner<T>>()) }; + +        // SAFETY: By the safety requirement of this function, we know that `ptr` came from +        // a previous call to `Arc::into_foreign`, which guarantees that `ptr` is valid and +        // holds a reference count increment that is transferrable to us. +        unsafe { Self::from_inner(inner) } +    } + +    unsafe fn borrow<'a>(ptr: *mut crate::ffi::c_void) -> ArcBorrow<'a, T> { +        // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous +        // call to `Self::into_foreign`. +        let inner = unsafe { NonNull::new_unchecked(ptr.cast::<ArcInner<T>>()) };          // SAFETY: The safety requirements of `from_foreign` ensure that the object remains alive          // for the lifetime of the returned value.          unsafe { ArcBorrow::new(inner) }      } -    unsafe fn from_foreign(ptr: *const crate::ffi::c_void) -> Self { -        // SAFETY: By the safety requirement of this function, we know that `ptr` came from -        // a previous call to `Arc::into_foreign`, which guarantees that `ptr` is valid and -        // holds a reference count increment that is transferrable to us. -        unsafe { Self::from_inner(NonNull::new(ptr as _).unwrap()) } +    unsafe fn borrow_mut<'a>(ptr: *mut crate::ffi::c_void) -> ArcBorrow<'a, T> { +        // SAFETY: The safety requirements for `borrow_mut` are a superset of the safety +        // requirements for `borrow`. +        unsafe { Self::borrow(ptr) }      }  } @@ -372,10 +396,14 @@ impl<T: ?Sized> AsRef<T> for Arc<T> {  impl<T: ?Sized> Clone for Arc<T> {      fn clone(&self) -> Self { +        // SAFETY: By the type invariant, there is necessarily a reference to the object, so it is +        // safe to dereference it. +        let refcount = unsafe { self.ptr.as_ref() }.refcount.get(); +          // INVARIANT: C `refcount_inc` saturates the refcount, so it cannot overflow to zero.          // SAFETY: By the type invariant, there is necessarily a reference to the object, so it is          // safe to increment the refcount. -        unsafe { bindings::refcount_inc(self.ptr.as_ref().refcount.get()) }; +        unsafe { bindings::refcount_inc(refcount) };          // SAFETY: We just incremented the refcount. This increment is now owned by the new `Arc`.          unsafe { Self::from_inner(self.ptr) } @@ -471,6 +499,8 @@ impl<T: ?Sized> From<Pin<UniqueArc<T>>> for Arc<T> {  /// obj.as_arc_borrow().use_reference();  /// # Ok::<(), Error>(())  /// ``` +#[repr(transparent)] +#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))]  pub struct ArcBorrow<'a, T: ?Sized + 'a> {      inner: NonNull<ArcInner<T>>,      _p: PhantomData<&'a ()>, @@ -478,7 +508,8 @@ pub struct ArcBorrow<'a, T: ?Sized + 'a> {  // This is to allow `ArcBorrow<U>` to be dispatched on when `ArcBorrow<T>` can be coerced into  // `ArcBorrow<U>`. -impl<T: ?Sized + Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<ArcBorrow<'_, U>> +#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))] +impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::DispatchFromDyn<ArcBorrow<'_, U>>      for ArcBorrow<'_, T>  {  } | 
