Commit 31089765 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'rust-6.4' of https://github.com/Rust-for-Linux/linux

Pull rust updates from Miguel Ojeda
 "More additions to the Rust core. Importantly, this adds the pin-init
  API, which will be used by other abstractions, such as the
  synchronization ones added here too:

   - pin-init API: a solution for the safe pinned initialization
     problem.

     This allows to reduce the need for 'unsafe' code in the kernel when
     dealing with data structures that require a stable address. Commit
     90e53c5e ("rust: add pin-init API core") contains a nice
     introduction -- here is an example of how it looks like:

        #[pin_data]
        struct Example {
            #[pin]
            value: Mutex<u32>,

            #[pin]
            value_changed: CondVar,
        }

        impl Example {
            fn new() -> impl PinInit<Self> {
                pin_init!(Self {
                    value <- new_mutex!(0),
                    value_changed <- new_condvar!(),
                })
            }
        }

        // In a `Box`.
        let b = Box::pin_init(Example::new())?;

        // In the stack.
        stack_pin_init!(let s = Example::new());

   - 'sync' module:

     New types 'LockClassKey' ('struct lock_class_key'), 'Lock',
     'Guard', 'Mutex' ('struct mutex'), 'SpinLock' ('spinlock_t'),
     'LockedBy' and 'CondVar' (uses 'wait_queue_head_t'), plus macros
     such as 'static_lock_class!' and 'new_spinlock!'.

     In particular, 'Lock' and 'Guard' are generic implementations that
     contain code that is common to all locks. Then, different backends
     (the new 'Backend' trait) are implemented and used to define types
     like 'Mutex':

        type Mutex<T> = Lock<T, MutexBackend>;

     In addition, new methods 'assume_init()', 'init_with()' and
     'pin_init_with()' for 'UniqueArc<MaybeUninit<T>>' and 'downcast()'
     for 'Arc<dyn Any + Send + Sync>'; as well as 'Debug' and 'Display'
     implementations for 'Arc' and 'UniqueArc'. Reduced stack usage of
     'UniqueArc::try_new_uninit()', too.

   - 'types' module:

     New trait 'AlwaysRefCounted' and new type 'ARef' (an owned
     reference to an always-reference-counted object, meant to be used
     in wrappers for C types that have their own ref counting
     functions).

     Moreover, new associated functions 'raw_get()' and 'ffi_init()' for
     'Opaque'.

   - New 'task' module with a new type 'Task' ('struct task_struct'),
     and a new macro 'current!' to safely get a reference to the current
     one.

   - New 'ioctl' module with new '_IOC*' const functions (equivalent to
     the C macros).

   - New 'uapi' crate, intended to be accessible by drivers directly.

   - 'macros' crate: new 'quote!' macro (similar to the one provided in
     userspace by the 'quote' crate); and the 'module!' macro now allows
     specifying multiple module aliases.

   - 'error' module:

     New associated functions for the 'Error' type, such as
     'from_errno()' and new functions such as 'to_result()'.

   - 'alloc' crate:

     More fallible 'Vec' methods: 'try_resize` and
     'try_extend_from_slice' and the infrastructure (imported from the
     Rust standard library) they need"

* tag 'rust-6.4' of https://github.com/Rust-for-Linux/linux: (44 commits)
  rust: ioctl: Add ioctl number manipulation functions
  rust: uapi: Add UAPI crate
  rust: sync: introduce `CondVar`
  rust: lock: add `Guard::do_unlocked`
  rust: sync: introduce `LockedBy`
  rust: introduce `current`
  rust: add basic `Task`
  rust: introduce `ARef`
  rust: lock: introduce `SpinLock`
  rust: lock: introduce `Mutex`
  rust: sync: introduce `Lock` and `Guard`
  rust: sync: introduce `LockClassKey`
  MAINTAINERS: add Benno Lossin as Rust reviewer
  rust: init: broaden the blanket impl of `Init`
  rust: sync: add functions for initializing `UniqueArc<MaybeUninit<T>>`
  rust: sync: reduce stack usage of `UniqueArc::try_new_uninit`
  rust: types: add `Opaque::ffi_init`
  rust: prelude: add `pin-init` API items to prelude
  rust: init: add `Zeroable` trait and `init::zeroed` function
  rust: init: add `stack_pin_init!` macro
  ...
parents 825a0714 ea76e08f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -18346,6 +18346,7 @@ M: Wedson Almeida Filho <wedsonaf@gmail.com>
R:	Boqun Feng <boqun.feng@gmail.com>
R:	Gary Guo <gary@garyguo.net>
R:	Björn Roy Baron <bjorn3_gh@protonmail.com>
R:	Benno Lossin <benno.lossin@proton.me>
L:	rust-for-linux@vger.kernel.org
S:	Supported
W:	https://github.com/Rust-for-Linux/linux
+1 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@

bindings_generated.rs
bindings_helpers_generated.rs
uapi_generated.rs
exports_*_generated.h
doc/
test/
+23 −5
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@ obj-$(CONFIG_RUST) += alloc.o bindings.o kernel.o
always-$(CONFIG_RUST) += exports_alloc_generated.h exports_bindings_generated.h \
    exports_kernel_generated.h

always-$(CONFIG_RUST) += uapi/uapi_generated.rs
obj-$(CONFIG_RUST) += uapi.o

ifdef CONFIG_RUST_BUILD_ASSERT_ALLOW
obj-$(CONFIG_RUST) += build_error.o
else
@@ -113,7 +116,7 @@ rustdoc-alloc: $(src)/alloc/lib.rs rustdoc-core rustdoc-compiler_builtins FORCE

rustdoc-kernel: private rustc_target_flags = --extern alloc \
    --extern build_error --extern macros=$(objtree)/$(obj)/libmacros.so \
    --extern bindings
    --extern bindings --extern uapi
rustdoc-kernel: $(src)/kernel/lib.rs rustdoc-core rustdoc-macros \
    rustdoc-compiler_builtins rustdoc-alloc $(obj)/libmacros.so \
    $(obj)/bindings.o FORCE
@@ -141,6 +144,9 @@ rusttestlib-macros: $(src)/macros/lib.rs rusttest-prepare FORCE
rusttestlib-bindings: $(src)/bindings/lib.rs rusttest-prepare FORCE
	$(call if_changed,rustc_test_library)

rusttestlib-uapi: $(src)/uapi/lib.rs rusttest-prepare FORCE
	$(call if_changed,rustc_test_library)

quiet_cmd_rustdoc_test = RUSTDOC T $<
      cmd_rustdoc_test = \
	OBJTREE=$(abspath $(objtree)) \
@@ -223,9 +229,10 @@ rusttest-macros: $(src)/macros/lib.rs rusttest-prepare FORCE
	$(call if_changed,rustdoc_test)

rusttest-kernel: private rustc_target_flags = --extern alloc \
    --extern build_error --extern macros --extern bindings
    --extern build_error --extern macros --extern bindings --extern uapi
rusttest-kernel: $(src)/kernel/lib.rs rusttest-prepare \
    rusttestlib-build_error rusttestlib-macros rusttestlib-bindings FORCE
    rusttestlib-build_error rusttestlib-macros rusttestlib-bindings \
    rusttestlib-uapi FORCE
	$(call if_changed,rustc_test)
	$(call if_changed,rustc_test_library)

@@ -302,6 +309,12 @@ $(obj)/bindings/bindings_generated.rs: $(src)/bindings/bindings_helper.h \
    $(src)/bindgen_parameters FORCE
	$(call if_changed_dep,bindgen)

$(obj)/uapi/uapi_generated.rs: private bindgen_target_flags = \
    $(shell grep -v '^#\|^$$' $(srctree)/$(src)/bindgen_parameters)
$(obj)/uapi/uapi_generated.rs: $(src)/uapi/uapi_helper.h \
    $(src)/bindgen_parameters FORCE
	$(call if_changed_dep,bindgen)

# See `CFLAGS_REMOVE_helpers.o` above. In addition, Clang on C does not warn
# with `-Wmissing-declarations` (unlike GCC), so it is not strictly needed here
# given it is `libclang`; but for consistency, future Clang changes and/or
@@ -402,10 +415,15 @@ $(obj)/bindings.o: $(src)/bindings/lib.rs \
    $(obj)/bindings/bindings_helpers_generated.rs FORCE
	$(call if_changed_dep,rustc_library)

$(obj)/uapi.o: $(src)/uapi/lib.rs \
    $(obj)/compiler_builtins.o \
    $(obj)/uapi/uapi_generated.rs FORCE
	$(call if_changed_dep,rustc_library)

$(obj)/kernel.o: private rustc_target_flags = --extern alloc \
    --extern build_error --extern macros --extern bindings
    --extern build_error --extern macros --extern bindings --extern uapi
$(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/alloc.o $(obj)/build_error.o \
    $(obj)/libmacros.so $(obj)/bindings.o FORCE
    $(obj)/libmacros.so $(obj)/bindings.o $(obj)/uapi.o FORCE
	$(call if_changed_dep,rustc_library)

endif # CONFIG_RUST
+134 −3
Original line number Diff line number Diff line
@@ -122,10 +122,8 @@ use self::spec_from_elem::SpecFromElem;
#[cfg(not(no_global_oom_handling))]
mod spec_from_elem;

#[cfg(not(no_global_oom_handling))]
use self::set_len_on_drop::SetLenOnDrop;

#[cfg(not(no_global_oom_handling))]
mod set_len_on_drop;

#[cfg(not(no_global_oom_handling))]
@@ -149,7 +147,8 @@ mod spec_from_iter;
#[cfg(not(no_global_oom_handling))]
use self::spec_extend::SpecExtend;

#[cfg(not(no_global_oom_handling))]
use self::spec_extend::TrySpecExtend;

mod spec_extend;

/// A contiguous growable array type, written as `Vec<T>`, short for 'vector'.
@@ -1919,6 +1918,17 @@ impl<T, A: Allocator> Vec<T, A> {
        self.len += count;
    }

    /// Tries to append elements to `self` from other buffer.
    #[inline]
    unsafe fn try_append_elements(&mut self, other: *const [T]) -> Result<(), TryReserveError> {
        let count = unsafe { (*other).len() };
        self.try_reserve(count)?;
        let len = self.len();
        unsafe { ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count) };
        self.len += count;
        Ok(())
    }

    /// Removes the specified range from the vector in bulk, returning all
    /// removed elements as an iterator. If the iterator is dropped before
    /// being fully consumed, it drops the remaining removed elements.
@@ -2340,6 +2350,45 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
        }
    }

    /// Tries to resize the `Vec` in-place so that `len` is equal to `new_len`.
    ///
    /// If `new_len` is greater than `len`, the `Vec` is extended by the
    /// difference, with each additional slot filled with `value`.
    /// If `new_len` is less than `len`, the `Vec` is simply truncated.
    ///
    /// This method requires `T` to implement [`Clone`],
    /// in order to be able to clone the passed value.
    /// If you need more flexibility (or want to rely on [`Default`] instead of
    /// [`Clone`]), use [`Vec::resize_with`].
    /// If you only need to resize to a smaller size, use [`Vec::truncate`].
    ///
    /// # Examples
    ///
    /// ```
    /// let mut vec = vec!["hello"];
    /// vec.try_resize(3, "world").unwrap();
    /// assert_eq!(vec, ["hello", "world", "world"]);
    ///
    /// let mut vec = vec![1, 2, 3, 4];
    /// vec.try_resize(2, 0).unwrap();
    /// assert_eq!(vec, [1, 2]);
    ///
    /// let mut vec = vec![42];
    /// let result = vec.try_resize(usize::MAX, 0);
    /// assert!(result.is_err());
    /// ```
    #[stable(feature = "kernel", since = "1.0.0")]
    pub fn try_resize(&mut self, new_len: usize, value: T) -> Result<(), TryReserveError> {
        let len = self.len();

        if new_len > len {
            self.try_extend_with(new_len - len, ExtendElement(value))
        } else {
            self.truncate(new_len);
            Ok(())
        }
    }

    /// Clones and appends all elements in a slice to the `Vec`.
    ///
    /// Iterates over the slice `other`, clones each element, and then appends
@@ -2365,6 +2414,30 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
        self.spec_extend(other.iter())
    }

    /// Tries to clone and append all elements in a slice to the `Vec`.
    ///
    /// Iterates over the slice `other`, clones each element, and then appends
    /// it to this `Vec`. The `other` slice is traversed in-order.
    ///
    /// Note that this function is same as [`extend`] except that it is
    /// specialized to work with slices instead. If and when Rust gets
    /// specialization this function will likely be deprecated (but still
    /// available).
    ///
    /// # Examples
    ///
    /// ```
    /// let mut vec = vec![1];
    /// vec.try_extend_from_slice(&[2, 3, 4]).unwrap();
    /// assert_eq!(vec, [1, 2, 3, 4]);
    /// ```
    ///
    /// [`extend`]: Vec::extend
    #[stable(feature = "kernel", since = "1.0.0")]
    pub fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), TryReserveError> {
        self.try_spec_extend(other.iter())
    }

    /// Copies elements from `src` range to the end of the vector.
    ///
    /// # Panics
@@ -2504,6 +2577,36 @@ impl<T, A: Allocator> Vec<T, A> {
            // len set by scope guard
        }
    }

    /// Try to extend the vector by `n` values, using the given generator.
    fn try_extend_with<E: ExtendWith<T>>(&mut self, n: usize, mut value: E) -> Result<(), TryReserveError> {
        self.try_reserve(n)?;

        unsafe {
            let mut ptr = self.as_mut_ptr().add(self.len());
            // Use SetLenOnDrop to work around bug where compiler
            // might not realize the store through `ptr` through self.set_len()
            // don't alias.
            let mut local_len = SetLenOnDrop::new(&mut self.len);

            // Write all elements except the last one
            for _ in 1..n {
                ptr::write(ptr, value.next());
                ptr = ptr.offset(1);
                // Increment the length in every step in case next() panics
                local_len.increment_len(1);
            }

            if n > 0 {
                // We can write the last element directly without cloning needlessly
                ptr::write(ptr, value.last());
                local_len.increment_len(1);
            }

            // len set by scope guard
            Ok(())
        }
    }
}

impl<T: PartialEq, A: Allocator> Vec<T, A> {
@@ -2838,6 +2941,34 @@ impl<T, A: Allocator> Vec<T, A> {
        }
    }

    // leaf method to which various SpecFrom/SpecExtend implementations delegate when
    // they have no further optimizations to apply
    fn try_extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) -> Result<(), TryReserveError> {
        // This is the case for a general iterator.
        //
        // This function should be the moral equivalent of:
        //
        //      for item in iterator {
        //          self.push(item);
        //      }
        while let Some(element) = iterator.next() {
            let len = self.len();
            if len == self.capacity() {
                let (lower, _) = iterator.size_hint();
                self.try_reserve(lower.saturating_add(1))?;
            }
            unsafe {
                ptr::write(self.as_mut_ptr().add(len), element);
                // Since next() executes user code which can panic we have to bump the length
                // after each step.
                // NB can't overflow since we would have had to alloc the address space
                self.set_len(len + 1);
            }
        }

        Ok(())
    }

    /// Creates a splicing iterator that replaces the specified range in the vector
    /// with the given `replace_with` iterator and yields the removed items.
    /// `replace_with` does not need to be the same length as `range`.
+30 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: Apache-2.0 OR MIT

// Set the length of the vec when the `SetLenOnDrop` value goes out of scope.
//
// The idea is: The length field in SetLenOnDrop is a local variable
// that the optimizer will see does not alias with any stores through the Vec's data
// pointer. This is a workaround for alias analysis issue #32155
pub(super) struct SetLenOnDrop<'a> {
    len: &'a mut usize,
    local_len: usize,
}

impl<'a> SetLenOnDrop<'a> {
    #[inline]
    pub(super) fn new(len: &'a mut usize) -> Self {
        SetLenOnDrop { local_len: *len, len }
    }

    #[inline]
    pub(super) fn increment_len(&mut self, increment: usize) {
        self.local_len += increment;
    }
}

impl Drop for SetLenOnDrop<'_> {
    #[inline]
    fn drop(&mut self) {
        *self.len = self.local_len;
    }
}
Loading