@@ -86,8 +86,7 @@ impl<T> Ref<T> {
86
86
87
87
// INVARIANT: The refcount is initialised to a non-zero value.
88
88
let value = RefInner {
89
- // SAFETY: Just an FFI call that returns a `refcount_t` initialised to 1.
90
- refcount : Opaque :: new ( unsafe { bindings:: REFCOUNT_INIT ( 1 ) } ) ,
89
+ refcount : Opaque :: new ( new_refcount ( ) ) ,
91
90
data : contents,
92
91
} ;
93
92
// SAFETY: `inner` is writable and properly aligned.
@@ -501,3 +500,83 @@ impl<T: ?Sized> DerefMut for UniqueRef<T> {
501
500
unsafe { & mut self . inner . ptr . as_mut ( ) . data }
502
501
}
503
502
}
503
+
504
+ /// Allows the creation of "reference-counted" globals.
505
+ ///
506
+ /// This is achieved by biasing the refcount with +1, which ensures that the count never drops back
507
+ /// to zero (unless buggy unsafe code incorrectly decrements without owning an increment) and
508
+ /// therefore also ensures that `drop` is never called.
509
+ ///
510
+ /// # Examples
511
+ ///
512
+ /// ```
513
+ /// use kernel::sync::{Ref, RefBorrow, StaticRef};
514
+ ///
515
+ /// const VALUE: u32 = 10;
516
+ /// static SR: StaticRef<u32> = StaticRef::new(VALUE);
517
+ ///
518
+ /// fn takes_ref_borrow(v: RefBorrow<'_, u32>) {
519
+ /// assert_eq!(*v, VALUE);
520
+ /// }
521
+ ///
522
+ /// fn takes_ref(v: Ref<u32>) {
523
+ /// assert_eq!(*v, VALUE);
524
+ /// }
525
+ ///
526
+ /// takes_ref_borrow(SR.as_ref_borrow());
527
+ /// takes_ref(SR.as_ref_borrow().into());
528
+ /// ```
529
+ pub struct StaticRef < T : ?Sized > {
530
+ inner : RefInner < T > ,
531
+ }
532
+
533
+ // SAFETY: A `StaticRef<T>` is a `Ref<T>` declared statically, so we just use the same criteria for
534
+ // making it `Sync`.
535
+ unsafe impl < T : ?Sized + Sync + Send > Sync for StaticRef < T > { }
536
+
537
+ impl < T > StaticRef < T > {
538
+ /// Creates a new instance of a static "ref-counted" object.
539
+ pub const fn new ( data : T ) -> Self {
540
+ // INVARIANT: The refcount is initialised to a non-zero value.
541
+ Self {
542
+ inner : RefInner {
543
+ refcount : Opaque :: new ( new_refcount ( ) ) ,
544
+ data,
545
+ } ,
546
+ }
547
+ }
548
+ }
549
+
550
+ impl < T : ?Sized > StaticRef < T > {
551
+ /// Creates a [`RefBorrow`] instance from the given static object.
552
+ ///
553
+ /// This requires a `'static` lifetime so that it can guarantee that the underlyling object
554
+ /// remains valid and is effectively pinned.
555
+ pub fn as_ref_borrow ( & ' static self ) -> RefBorrow < ' static , T > {
556
+ // SAFETY: The static lifetime guarantees that the object remains valid. And the shared
557
+ // reference guarantees that no mutable references exist.
558
+ unsafe { RefBorrow :: new ( NonNull :: from ( & self . inner ) ) }
559
+ }
560
+ }
561
+
562
+ /// Creates, from a const context, a new instance of `struct refcount_struct` with a refcount of 1.
563
+ ///
564
+ /// ```
565
+ /// # // The test below is meant to ensure that `new_refcount` (which is const) mimics
566
+ /// # // `REFCOUNT_INIT`, which is written in C and thus can't be used in a const context.
567
+ /// # // TODO: Once `#[test]` is working, move this to a test and make `new_refcount` private.
568
+ /// # use kernel::bindings;
569
+ /// # // SAFETY: Just an FFI call that returns a `refcount_t` initialised to 1.
570
+ /// # let bindings::refcount_struct {
571
+ /// # refs: bindings::atomic_t { counter: a },
572
+ /// # } = unsafe { bindings::REFCOUNT_INIT(1) };
573
+ /// # let bindings::refcount_struct {
574
+ /// # refs: bindings::atomic_t { counter: b },
575
+ /// # } = kernel::sync::new_refcount();
576
+ /// # assert_eq!(a, b);
577
+ /// ```
578
+ pub const fn new_refcount ( ) -> bindings:: refcount_struct {
579
+ bindings:: refcount_struct {
580
+ refs : bindings:: atomic_t { counter : 1 } ,
581
+ }
582
+ }
0 commit comments