8
8
//! threads.
9
9
//!
10
10
//! It is different from the standard library's [`Arc`] in a few ways:
11
- //! 1. It is backed by the kernel's `refcount_t` type.
11
+ //! 1. It is backed by the kernel's [`Refcount`] type.
12
12
//! 2. It does not support weak references, which allows it to be half the size.
13
13
//! 3. It saturates the reference count instead of aborting when it goes over a threshold.
14
14
//! 4. It does not provide a `get_mut` method, so the ref counted object is pinned.
18
18
19
19
use crate :: {
20
20
alloc:: { AllocError , Flags , KBox } ,
21
- bindings,
22
21
init:: { self , InPlaceInit , Init , PinInit } ,
22
+ sync:: Refcount ,
23
23
try_init,
24
- types:: { ForeignOwnable , Opaque } ,
24
+ types:: ForeignOwnable ,
25
25
} ;
26
26
use core:: {
27
27
alloc:: Layout ,
@@ -144,7 +144,7 @@ pub struct Arc<T: ?Sized> {
144
144
#[ pin_data]
145
145
#[ repr( C ) ]
146
146
struct ArcInner < T : ?Sized > {
147
- refcount : Opaque < bindings :: refcount_t > ,
147
+ refcount : Refcount ,
148
148
data : T ,
149
149
}
150
150
@@ -156,7 +156,7 @@ impl<T: ?Sized> ArcInner<T> {
156
156
/// `ptr` must have been returned by a previous call to [`Arc::into_raw`], and the `Arc` must
157
157
/// not yet have been destroyed.
158
158
unsafe fn container_of ( ptr : * const T ) -> NonNull < ArcInner < T > > {
159
- let refcount_layout = Layout :: new :: < bindings :: refcount_t > ( ) ;
159
+ let refcount_layout = Layout :: new :: < Refcount > ( ) ;
160
160
// SAFETY: The caller guarantees that the pointer is valid.
161
161
let val_layout = Layout :: for_value ( unsafe { & * ptr } ) ;
162
162
// SAFETY: We're computing the layout of a real struct that existed when compiling this
@@ -208,8 +208,7 @@ impl<T> Arc<T> {
208
208
pub fn new ( contents : T , flags : Flags ) -> Result < Self , AllocError > {
209
209
// INVARIANT: The refcount is initialised to a non-zero value.
210
210
let value = ArcInner {
211
- // SAFETY: There are no safety requirements for this FFI call.
212
- refcount : Opaque :: new ( unsafe { bindings:: REFCOUNT_INIT ( 1 ) } ) ,
211
+ refcount : Refcount :: new ( 1 ) ,
213
212
data : contents,
214
213
} ;
215
214
@@ -300,7 +299,7 @@ impl<T: ?Sized> Arc<T> {
300
299
/// use kernel::sync::{Arc, UniqueArc};
301
300
///
302
301
/// let arc = Arc::new(42, GFP_KERNEL)?;
303
- /// let unique_arc = arc. into_unique_or_drop();
302
+ /// let unique_arc = Arc:: into_unique_or_drop(arc );
304
303
///
305
304
/// // The above conversion should succeed since refcount of `arc` is 1.
306
305
/// assert!(unique_arc.is_some());
@@ -316,35 +315,30 @@ impl<T: ?Sized> Arc<T> {
316
315
/// let arc = Arc::new(42, GFP_KERNEL)?;
317
316
/// let another = arc.clone();
318
317
///
319
- /// let unique_arc = arc. into_unique_or_drop();
318
+ /// let unique_arc = Arc:: into_unique_or_drop(arc );
320
319
///
321
320
/// // The above conversion should fail since refcount of `arc` is >1.
322
321
/// assert!(unique_arc.is_none());
323
322
///
324
323
/// # Ok::<(), Error>(())
325
324
/// ```
326
- pub fn into_unique_or_drop ( self ) -> Option < Pin < UniqueArc < T > > > {
325
+ pub fn into_unique_or_drop ( this : Self ) -> Option < Pin < UniqueArc < T > > > {
327
326
// We will manually manage the refcount in this method, so we disable the destructor.
328
- let me = ManuallyDrop :: new ( self ) ;
327
+ let this = ManuallyDrop :: new ( this ) ;
329
328
// SAFETY: We own a refcount, so the pointer is still valid.
330
- let refcount = unsafe { me . ptr . as_ref ( ) } . refcount . get ( ) ;
329
+ let refcount = unsafe { & this . ptr . as_ref ( ) . refcount } ;
331
330
332
331
// If the refcount reaches a non-zero value, then we have destroyed this `Arc` and will
333
332
// return without further touching the `Arc`. If the refcount reaches zero, then there are
334
333
// no other arcs, and we can create a `UniqueArc`.
335
- //
336
- // SAFETY: We own a refcount, so the pointer is not dangling.
337
- let is_zero = unsafe { bindings:: refcount_dec_and_test ( refcount) } ;
338
- if is_zero {
339
- // SAFETY: We have exclusive access to the arc, so we can perform unsynchronized
340
- // accesses to the refcount.
341
- unsafe { core:: ptr:: write ( refcount, bindings:: REFCOUNT_INIT ( 1 ) ) } ;
334
+ if refcount. dec_and_test ( ) {
335
+ refcount. set ( 1 ) ;
342
336
343
- // INVARIANT: We own the only refcount to this arc, so we may create a `UniqueArc`. We
344
- // must pin the `UniqueArc` because the values was previously in an `Arc`, and they pin
345
- // their values.
337
+ // INVARIANT: If the refcount failed to decrement because it is 1, then we have the
338
+ // exclusive ownership, so we may create a `UniqueArc`. We must pin the `UniqueArc`
339
+ // because the values was previously in an `Arc`, and they pin their values.
346
340
Some ( Pin :: from ( UniqueArc {
347
- inner : ManuallyDrop :: into_inner ( me ) ,
341
+ inner : ManuallyDrop :: into_inner ( this ) ,
348
342
} ) )
349
343
} else {
350
344
None
@@ -419,14 +413,10 @@ impl<T: ?Sized> AsRef<T> for Arc<T> {
419
413
420
414
impl < T : ?Sized > Clone for Arc < T > {
421
415
fn clone ( & self ) -> Self {
422
- // SAFETY: By the type invariant, there is necessarily a reference to the object, so it is
423
- // safe to dereference it.
424
- let refcount = unsafe { self . ptr . as_ref ( ) } . refcount . get ( ) ;
425
-
426
- // INVARIANT: C `refcount_inc` saturates the refcount, so it cannot overflow to zero.
416
+ // INVARIANT: `Refcount` saturates the refcount, so it cannot overflow to zero.
427
417
// SAFETY: By the type invariant, there is necessarily a reference to the object, so it is
428
418
// safe to increment the refcount.
429
- unsafe { bindings :: refcount_inc ( refcount) } ;
419
+ unsafe { self . ptr . as_ref ( ) . refcount . inc ( ) } ;
430
420
431
421
// SAFETY: We just incremented the refcount. This increment is now owned by the new `Arc`.
432
422
unsafe { Self :: from_inner ( self . ptr ) }
@@ -435,16 +425,14 @@ impl<T: ?Sized> Clone for Arc<T> {
435
425
436
426
impl < T : ?Sized > Drop for Arc < T > {
437
427
fn drop ( & mut self ) {
438
- // SAFETY: By the type invariant, there is necessarily a reference to the object. We cannot
439
- // touch `refcount` after it's decremented to a non-zero value because another thread/CPU
440
- // may concurrently decrement it to zero and free it. It is ok to have a raw pointer to
441
- // freed/invalid memory as long as it is never dereferenced.
442
- let refcount = unsafe { self . ptr . as_ref ( ) } . refcount . get ( ) ;
443
-
444
428
// INVARIANT: If the refcount reaches zero, there are no other instances of `Arc`, and
445
429
// this instance is being dropped, so the broken invariant is not observable.
446
- // SAFETY: Also by the type invariant, we are allowed to decrement the refcount.
447
- let is_zero = unsafe { bindings:: refcount_dec_and_test ( refcount) } ;
430
+ // SAFETY: By the type invariant, there is necessarily a reference to the object.
431
+ // NOTE: we cannot touch `refcount` after it's decremented to a non-zero value because
432
+ // another thread/CPU may concurrently decrement it to zero and free it. However it is okay
433
+ // to have a transient reference to decrement the refcount, see
434
+ // https://github.com/rust-lang/rust/issues/55005.
435
+ let is_zero = unsafe { self . ptr . as_ref ( ) . refcount . dec_and_test ( ) } ;
448
436
if is_zero {
449
437
// The count reached zero, we must free the memory.
450
438
//
@@ -696,8 +684,7 @@ impl<T> UniqueArc<T> {
696
684
// INVARIANT: The refcount is initialised to a non-zero value.
697
685
let inner = KBox :: try_init :: < AllocError > (
698
686
try_init ! ( ArcInner {
699
- // SAFETY: There are no safety requirements for this FFI call.
700
- refcount: Opaque :: new( unsafe { bindings:: REFCOUNT_INIT ( 1 ) } ) ,
687
+ refcount: Refcount :: new( 1 ) ,
701
688
data <- init:: uninit:: <T , AllocError >( ) ,
702
689
} ? AllocError ) ,
703
690
flags,
0 commit comments