Skip to content
Snippets Groups Projects
  1. Jan 13, 2025
  2. Oct 07, 2024
    • Gary Guo's avatar
      rust: enable arbitrary_self_types and remove `Receiver` · c95bbb59
      Gary Guo authored
      The term "receiver" means that a type can be used as the type of `self`,
      and thus enables method call syntax `foo.bar()` instead of
      `Foo::bar(foo)`. Stable Rust as of today (1.81) enables a limited
      selection of types (primitives and types in std, e.g. `Box` and `Arc`)
      to be used as receivers, while custom types cannot.
      
      We want the kernel `Arc` type to have the same functionality as the Rust
      std `Arc`, so we use the `Receiver` trait (gated behind `receiver_trait`
      unstable feature) to gain the functionality.
      
      The `arbitrary_self_types` RFC [1] (tracking issue [2]) is accepted and
      it will allow all types that implement a new `Receiver` trait (different
      from today's unstable trait) to be used as receivers. This trait will be
      automatically implemented for all `Deref` types, which include our `Arc`
      type, so we no longer have to opt-in to be used as receiver. To prepare
      us for the change, remove the `Receiver` implementation and the
      associated feature. To still allow `Arc` and others to be used as method
      receivers, turn on `arbitrary_self_types` feature instead.
      
      This feature gate is introduced in 1.23.0. It used to enable both
      `Deref` types and raw pointer types to be used as receivers, but the
      latter is now split into a different feature gate in Rust 1.83 nightly.
      We do not need receivers on raw pointers so this change would not affect
      us and usage of `arbitrary_self_types` feature would work for all Rust
      versions that we support (>=1.78).
      
      Cc: Adrian Taylor <ade@hohum.me.uk>
      Link: https://github.com/rust-lang/rfcs/pull/3519 [1]
      Link: https://github.com/rust-lang/rust/issues/44874
      
       [2]
      Signed-off-by: default avatarGary Guo <gary@garyguo.net>
      Reviewed-by: default avatarBenno Lossin <benno.lossin@proton.me>
      Reviewed-by: default avatarAlice Ryhl <aliceryhl@google.com>
      Link: https://lore.kernel.org/r/20240915132734.1653004-1-gary@garyguo.net
      
      
      Signed-off-by: default avatarMiguel Ojeda <ojeda@kernel.org>
      c95bbb59
  3. Aug 23, 2024
    • Alice Ryhl's avatar
      rust: list: add List · db841866
      Alice Ryhl authored
      
      Add the actual linked list itself.
      
      The linked list uses the following design: The List type itself just has
      a single pointer to the first element of the list. And the actual list
      items then form a cycle. So the last item is `first->prev`.
      
      This is slightly different from the usual kernel linked list. Matching
      that exactly would amount to giving List two pointers, and having it be
      part of the cycle of items. This alternate design has the advantage that
      the cycle is never completely empty, which can reduce the number of
      branches in some cases. However, it also has the disadvantage that List
      must be pinned, which this design is trying to avoid.
      
      Having the list items form a cycle rather than having null pointers at
      the beginning/end is convenient for several reasons. For one, it lets us
      store only one pointer in List, and it simplifies the implementation of
      several functions.
      
      Unfortunately, the `remove` function that removes an arbitrary element
      from the list has to be unsafe. This is needed because there is no way
      to handle the case where you pass an element from the wrong list. For
      example, if it is the first element of some other list, then that other
      list's `first` pointer would not be updated. Similarly, it could be a
      data race if you try to remove it from two different lists in parallel.
      (There's no problem with passing `remove` an item that's not in any
      list. Additionally, other removal methods such as `pop_front` need not
      be unsafe, as they can't be used to remove items from another list.)
      
      A future patch in this series will introduce support for cursors that
      can be used to remove arbitrary items without unsafe code.
      
      Reviewed-by: default avatarBenno Lossin <benno.lossin@proton.me>
      Signed-off-by: default avatarAlice Ryhl <aliceryhl@google.com>
      Link: https://lore.kernel.org/r/20240814-linked-list-v5-6-f5f5e8075da0@google.com
      
      
      [ Fixed a few typos. - Miguel ]
      Signed-off-by: default avatarMiguel Ojeda <ojeda@kernel.org>
      db841866
    • Alice Ryhl's avatar
      rust: list: add tracking for ListArc · a4802631
      Alice Ryhl authored
      
      Add the ability to track whether a ListArc exists for a given value,
      allowing for the creation of ListArcs without going through UniqueArc.
      
      The `impl_list_arc_safe!` macro is extended with a `tracked_by` strategy
      that defers the tracking of ListArcs to a field of the struct.
      Additionally, the AtomicListArcTracker type is introduced, which can
      track whether a ListArc exists using an atomic. By deferring the
      tracking to a field of type AtomicListArcTracker, structs gain the
      ability to create ListArcs without going through a UniqueArc.
      
      Rust Binder uses this for some objects where we want to be able to
      insert them into a linked list at any time. Using the
      AtomicListArcTracker, we are able to check whether an item is already in
      the list, and if not, we can create a `ListArc` and push it.
      
      The macro has the ability to defer the tracking of ListArcs to a field,
      using whatever strategy that field has. Since we don't add any
      strategies other than AtomicListArcTracker, another similar option would
      be to hard-code that the field should be an AtomicListArcTracker.
      However, Rust Binder has a case where the AtomicListArcTracker is not
      stored directly in the struct, but in a sub-struct. Furthermore, the
      outer struct is generic:
      
      struct Wrapper<T: ?Sized> {
          links: ListLinks,
          inner: T,
      }
      
      Here, the Wrapper struct implements ListArcSafe with `tracked_by inner`,
      and then the various types used with `inner` also uses the macro to
      implement ListArcSafe. Some of them use the untracked strategy, and some
      of them use tracked_by with an AtomicListArcTracker. This way, Wrapper
      just inherits whichever choice `inner` has made.
      
      Reviewed-by: default avatarBenno Lossin <benno.lossin@proton.me>
      Signed-off-by: default avatarAlice Ryhl <aliceryhl@google.com>
      Link: https://lore.kernel.org/r/20240814-linked-list-v5-3-f5f5e8075da0@google.com
      
      
      Signed-off-by: default avatarMiguel Ojeda <ojeda@kernel.org>
      a4802631
    • Alice Ryhl's avatar
      rust: list: add ListArc · 6cd34171
      Alice Ryhl authored
      
      The `ListArc` type can be thought of as a special reference to a
      refcounted object that owns the permission to manipulate the
      `next`/`prev` pointers stored in the refcounted object. By ensuring that
      each object has only one `ListArc` reference, the owner of that
      reference is assured exclusive access to the `next`/`prev` pointers.
      When a `ListArc` is inserted into a `List`, the `List` takes ownership
      of the `ListArc` reference.
      
      There are various strategies for ensuring that a value has only one
      `ListArc` reference. The simplest is to convert a `UniqueArc` into a
      `ListArc`. However, the refcounted object could also keep track of
      whether a `ListArc` exists using a boolean, which could allow for the
      creation of new `ListArc` references from an `Arc` reference. Whatever
      strategy is used, the relevant tracking is referred to as "the tracking
      inside `T`", and the `ListArcSafe` trait (and its subtraits) are used to
      update the tracking when a `ListArc` is created or destroyed.
      
      Note that we allow the case where the tracking inside `T` thinks that a
      `ListArc` exists, but actually, there isn't a `ListArc`. However, we do
      not allow the opposite situation where a `ListArc` exists, but the
      tracking thinks it doesn't. This is because the former can at most
      result in us failing to create a `ListArc` when the operation could
      succeed, whereas the latter can result in the creation of two `ListArc`
      references. Only the latter situation can lead to memory safety issues.
      
      This patch introduces the `impl_list_arc_safe!` macro that allows you to
      implement `ListArcSafe` for types using the strategy where a `ListArc`
      can only be created from a `UniqueArc`. Other strategies are introduced
      in later patches.
      
      This is part of the linked list that Rust Binder will use for many
      different things. The strategy where a `ListArc` can only be created
      from a `UniqueArc` is actually sufficient for most of the objects that
      Rust Binder needs to insert into linked lists. Usually, these are todo
      items that are created and then immediately inserted into a queue.
      
      The const generic ID allows objects to have several prev/next pointer
      pairs so that the same object can be inserted into several different
      lists. You are able to have several `ListArc` references as long as they
      correspond to different pointer pairs. The ID itself is purely a
      compile-time concept and will not be present in the final binary. Both
      the `List` and the `ListArc` will need to agree on the ID for them to
      work together. Rust Binder uses this in a few places (e.g. death
      recipients) where the same object can be inserted into both generic todo
      lists and some other lists for tracking the status of the object.
      
      The ID is a const generic rather than a type parameter because the
      `pair_from_unique` method needs to be able to assert that the two ids
      are different. There's no easy way to assert that when using types
      instead of integers.
      
      Reviewed-by: default avatarBenno Lossin <benno.lossin@proton.me>
      Signed-off-by: default avatarAlice Ryhl <aliceryhl@google.com>
      Link: https://lore.kernel.org/r/20240814-linked-list-v5-2-f5f5e8075da0@google.com
      
      
      Signed-off-by: default avatarMiguel Ojeda <ojeda@kernel.org>
      6cd34171
Loading