Rust changes for v6.8
Another routine one in terms of features. In terms of lines, this time the 'alloc' version upgrade is less prominent, given that it was fairly small (and we did not have two upgrades). Toolchain and infrastructure: - Upgrade to Rust 1.74.1. The patch release includes a fix for an ICE that the Apple AGX GPU driver was hitting. - Support 'srctree'-relative links in Rust code documentation. - Automate part of the manual constants handling (i.e. the ones not recognised by 'bindgen'). - Suppress searching builtin sysroot to avoid confusion with installed sysroots, needed for the to-be-merged arm64 support which uses a builtin target. - Ignore '__preserve_most' functions for 'bindgen'. - Reduce header inclusion bloat in exports. 'kernel' crate: - Implement 'Debug' for 'CString'. - Make 'CondVar::wait()' an uninterruptible wait. 'macros' crate: - Update 'paste!' to accept string literals. - Improve '#[vtable]' documentation. Documentation: - Add testing section (KUnit and 'rusttest' target). - Remove 'CC=clang' mentions. - Clarify that 'rustup override' applies to build directory. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEPjU5OPd5QIZ9jqqOGXyLc2htIW0FAmWbS68ACgkQGXyLc2ht IW1V4w//ToMxdyHTnoqFyzI5X4mzxaV8vhEViGs5eXG87d0E8WwSRCA4weEGTbER 06huyUI1tTbYgpsOEyuUSEDd/0GiA+sGseaqS4kJ7+aA6fSof7E6nA4d2SURBb2O 0F1c3DucGbeDzZz0GZDWSnoF3RwQWRz1hPR9scMcQi4d69r5mT+HdD1UryXaGkXQ 9gDeWhmqO4EzEjFR/gd0fYxd/z7OgXsaUQJk4fpDGDJ+/USPzrE99iGoHINB6VRA mWsq5g0Po6aPwmlPDcW6bgRrLEWpzHftCNAZjQbjfT4mKjYJg4GJaqShCfM+wkZN 3NVLxueJ0ZzLXmHxpMjx9WdHM1j/MM31W/n0/Opgnalv0lETZdNKy/Ep1Fj+AOTP kKwU2bQT66We78cjY6Fh2noCNv3td9g59/q8TfKAFxsy16BqL/RLqQ21Ft0hyLO+ ebvOOO0o2ul/7onaOFhrXMRdVvaAXeK1c64kiGRUr16X5D5UcvR+ZkJ/LVf2ozvS mDtzXB561WCyVSfTFz0buGdudO4NWE+7Dh7msXhE6W6faFN+7MA6pfWZro64k+az gEmcCcwjUMpV0IrvCWH0dW1NG6XGqGQ/PkGTYdIyZ+1GajEhwNILuIPKuM8VXwLZ zmu+y4xdpPd7hMjncopCsb8G3DidAN7zeYea5tnAGILCmOZMOX4= =w+n8 -----END PGP SIGNATURE----- Merge tag 'rust-6.8' of https://github.com/Rust-for-Linux/linux Pull Rust updates from Miguel Ojeda: "Another routine one in terms of features. In terms of lines, this time the 'alloc' version upgrade is less prominent, given that it was fairly small (and we did not have two upgrades) Toolchain and infrastructure: - Upgrade to Rust 1.74.1 The patch release includes a fix for an ICE that the Apple AGX GPU driver was hitting - Support 'srctree'-relative links in Rust code documentation - Automate part of the manual constants handling (i.e. the ones not recognised by 'bindgen') - Suppress searching builtin sysroot to avoid confusion with installed sysroots, needed for the to-be-merged arm64 support which uses a builtin target - Ignore '__preserve_most' functions for 'bindgen' - Reduce header inclusion bloat in exports 'kernel' crate: - Implement 'Debug' for 'CString' - Make 'CondVar::wait()' an uninterruptible wait 'macros' crate: - Update 'paste!' to accept string literals - Improve '#[vtable]' documentation Documentation: - Add testing section (KUnit and 'rusttest' target) - Remove 'CC=clang' mentions - Clarify that 'rustup override' applies to build directory" * tag 'rust-6.8' of https://github.com/Rust-for-Linux/linux: docs: rust: Clarify that 'rustup override' applies to build directory docs: rust: Add rusttest info docs: rust: remove `CC=clang` mentions rust: support `srctree`-relative links rust: sync: Makes `CondVar::wait()` an uninterruptible wait rust: upgrade to Rust 1.74.1 rust: Suppress searching builtin sysroot rust: macros: improve `#[vtable]` documentation rust: macros: update 'paste!' macro to accept string literals rust: bindings: rename const binding using sed rust: Ignore preserve-most functions rust: replace <linux/module.h> with <linux/export.h> in rust/exports.c rust: kernel: str: Implement Debug for CString
This commit is contained in:
commit
b6964fe239
Documentation
rust
Makefile
alloc
bindgen_parametersbindings
exports.ckernel
macros
scripts
|
@ -31,7 +31,7 @@ you probably needn't concern yourself with pcmciautils.
|
|||
====================== =============== ========================================
|
||||
GNU C 5.1 gcc --version
|
||||
Clang/LLVM (optional) 11.0.0 clang --version
|
||||
Rust (optional) 1.73.0 rustc --version
|
||||
Rust (optional) 1.74.1 rustc --version
|
||||
bindgen (optional) 0.65.1 bindgen --version
|
||||
GNU make 3.82 make --version
|
||||
bash 4.2 bash --version
|
||||
|
|
|
@ -177,6 +177,19 @@ please take a look at the ``rustdoc`` book at:
|
|||
|
||||
https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html
|
||||
|
||||
In addition, the kernel supports creating links relative to the source tree by
|
||||
prefixing the link destination with ``srctree/``. For instance:
|
||||
|
||||
.. code-block:: rust
|
||||
|
||||
//! C header: [`include/linux/printk.h`](srctree/include/linux/printk.h)
|
||||
|
||||
or:
|
||||
|
||||
.. code-block:: rust
|
||||
|
||||
/// [`struct mutex`]: srctree/include/linux/mutex.h
|
||||
|
||||
|
||||
Naming
|
||||
------
|
||||
|
|
|
@ -77,3 +77,27 @@ configuration:
|
|||
#[cfg(CONFIG_X="y")] // Enabled as a built-in (`y`)
|
||||
#[cfg(CONFIG_X="m")] // Enabled as a module (`m`)
|
||||
#[cfg(not(CONFIG_X))] // Disabled
|
||||
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
There are the tests that come from the examples in the Rust documentation
|
||||
and get transformed into KUnit tests. These can be run via KUnit. For example
|
||||
via ``kunit_tool`` (``kunit.py``) on the command line::
|
||||
|
||||
./tools/testing/kunit/kunit.py run --make_options LLVM=1 --arch x86_64 --kconfig_add CONFIG_RUST=y
|
||||
|
||||
Alternatively, KUnit can run them as kernel built-in at boot. Refer to
|
||||
Documentation/dev-tools/kunit/index.rst for the general KUnit documentation
|
||||
and Documentation/dev-tools/kunit/architecture.rst for the details of kernel
|
||||
built-in vs. command line testing.
|
||||
|
||||
Additionally, there are the ``#[test]`` tests. These can be run using
|
||||
the ``rusttest`` Make target::
|
||||
|
||||
make LLVM=1 rusttest
|
||||
|
||||
This requires the kernel ``.config`` and downloads external repositories.
|
||||
It runs the ``#[test]`` tests on the host (currently) and thus is fairly
|
||||
limited in what these tests can test.
|
||||
|
|
|
@ -33,14 +33,18 @@ A particular version of the Rust compiler is required. Newer versions may or
|
|||
may not work because, for the moment, the kernel depends on some unstable
|
||||
Rust features.
|
||||
|
||||
If ``rustup`` is being used, enter the checked out source code directory
|
||||
and run::
|
||||
If ``rustup`` is being used, enter the kernel build directory (or use
|
||||
``--path=<build-dir>`` argument to the ``set`` sub-command) and run::
|
||||
|
||||
rustup override set $(scripts/min-tool-version.sh rustc)
|
||||
|
||||
This will configure your working directory to use the correct version of
|
||||
``rustc`` without affecting your default toolchain. If you are not using
|
||||
``rustup``, fetch a standalone installer from:
|
||||
``rustc`` without affecting your default toolchain.
|
||||
|
||||
Note that the override applies to the current working directory (and its
|
||||
sub-directories).
|
||||
|
||||
If you are not using ``rustup``, fetch a standalone installer from:
|
||||
|
||||
https://forge.rust-lang.org/infra/other-installation-methods.html#standalone
|
||||
|
||||
|
@ -76,7 +80,7 @@ libclang
|
|||
|
||||
``libclang`` (part of LLVM) is used by ``bindgen`` to understand the C code
|
||||
in the kernel, which means LLVM needs to be installed; like when the kernel
|
||||
is compiled with ``CC=clang`` or ``LLVM=1``.
|
||||
is compiled with ``LLVM=1``.
|
||||
|
||||
Linux distributions are likely to have a suitable one available, so it is
|
||||
best to check that first.
|
||||
|
@ -229,10 +233,6 @@ at the moment. That is::
|
|||
|
||||
make LLVM=1
|
||||
|
||||
For architectures that do not support a full LLVM toolchain, use::
|
||||
|
||||
make CC=clang
|
||||
|
||||
Using GCC also works for some configurations, but it is very experimental at
|
||||
the moment.
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $<
|
|||
$(rustc_target_flags) -L$(objtree)/$(obj) \
|
||||
--output $(rustdoc_output) \
|
||||
--crate-name $(subst rustdoc-,,$@) \
|
||||
$(if $(rustdoc_host),,--sysroot=/dev/null) \
|
||||
@$(objtree)/include/generated/rustc_cfg $<
|
||||
|
||||
# The `html_logo_url` and `html_favicon_url` forms of the `doc` attribute
|
||||
|
@ -98,7 +99,8 @@ rustdoc: rustdoc-core rustdoc-macros rustdoc-compiler_builtins \
|
|||
$(Q)find $(rustdoc_output) -name '*.html' -type f -print0 | xargs -0 sed -Ei \
|
||||
-e 's:rust-logo-[0-9a-f]+\.svg:logo.svg:g' \
|
||||
-e 's:favicon-[0-9a-f]+\.svg:logo.svg:g' \
|
||||
-e 's:<link rel="alternate icon" type="image/png" href="[/.]+/static\.files/favicon-(16x16|32x32)-[0-9a-f]+\.png">::g'
|
||||
-e 's:<link rel="alternate icon" type="image/png" href="[/.]+/static\.files/favicon-(16x16|32x32)-[0-9a-f]+\.png">::g' \
|
||||
-e 's:<a href="srctree/([^"]+)">:<a href="$(abs_srctree)/\1">:g'
|
||||
$(Q)for f in $(rustdoc_output)/static.files/rustdoc-*.css; do \
|
||||
echo ".logo-container > img { object-fit: contain; }" >> $$f; done
|
||||
|
||||
|
@ -178,6 +180,7 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $<
|
|||
--extern build_error --extern macros \
|
||||
--extern bindings --extern uapi \
|
||||
--no-run --crate-name kernel -Zunstable-options \
|
||||
--sysroot=/dev/null \
|
||||
--test-builder $(objtree)/scripts/rustdoc_test_builder \
|
||||
$< $(rustdoc_test_kernel_quiet); \
|
||||
$(objtree)/scripts/rustdoc_test_gen
|
||||
|
@ -337,6 +340,8 @@ quiet_cmd_bindgen = BINDGEN $@
|
|||
|
||||
$(obj)/bindings/bindings_generated.rs: private bindgen_target_flags = \
|
||||
$(shell grep -Ev '^#|^$$' $(srctree)/$(src)/bindgen_parameters)
|
||||
$(obj)/bindings/bindings_generated.rs: private bindgen_target_extra = ; \
|
||||
sed -Ei 's/pub const RUST_CONST_HELPER_([a-zA-Z0-9_]*)/pub const \1/g' $@
|
||||
$(obj)/bindings/bindings_generated.rs: $(src)/bindings/bindings_helper.h \
|
||||
$(src)/bindgen_parameters FORCE
|
||||
$(call if_changed_dep,bindgen)
|
||||
|
@ -402,6 +407,7 @@ quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L
|
|||
--emit=metadata=$(dir $@)$(patsubst %.o,lib%.rmeta,$(notdir $@)) \
|
||||
--crate-type rlib -L$(objtree)/$(obj) \
|
||||
--crate-name $(patsubst %.o,%,$(notdir $@)) $< \
|
||||
--sysroot=/dev/null \
|
||||
$(if $(rustc_objcopy),;$(OBJCOPY) $(rustc_objcopy) $@)
|
||||
|
||||
rust-analyzer:
|
||||
|
|
|
@ -345,18 +345,31 @@ extern "Rust" {
|
|||
fn __rust_alloc_error_handler(size: usize, align: usize) -> !;
|
||||
}
|
||||
|
||||
/// Abort on memory allocation error or failure.
|
||||
/// Signal a memory allocation error.
|
||||
///
|
||||
/// Callers of memory allocation APIs wishing to abort computation
|
||||
/// Callers of memory allocation APIs wishing to cease execution
|
||||
/// in response to an allocation error are encouraged to call this function,
|
||||
/// rather than directly invoking `panic!` or similar.
|
||||
/// rather than directly invoking [`panic!`] or similar.
|
||||
///
|
||||
/// The default behavior of this function is to print a message to standard error
|
||||
/// and abort the process.
|
||||
/// It can be replaced with [`set_alloc_error_hook`] and [`take_alloc_error_hook`].
|
||||
/// This function is guaranteed to diverge (not return normally with a value), but depending on
|
||||
/// global configuration, it may either panic (resulting in unwinding or aborting as per
|
||||
/// configuration for all panics), or abort the process (with no unwinding).
|
||||
///
|
||||
/// The default behavior is:
|
||||
///
|
||||
/// * If the binary links against `std` (typically the case), then
|
||||
/// print a message to standard error and abort the process.
|
||||
/// This behavior can be replaced with [`set_alloc_error_hook`] and [`take_alloc_error_hook`].
|
||||
/// Future versions of Rust may panic by default instead.
|
||||
///
|
||||
/// * If the binary does not link against `std` (all of its crates are marked
|
||||
/// [`#![no_std]`][no_std]), then call [`panic!`] with a message.
|
||||
/// [The panic handler] applies as to any panic.
|
||||
///
|
||||
/// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html
|
||||
/// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html
|
||||
/// [The panic handler]: https://doc.rust-lang.org/reference/runtime.html#the-panic_handler-attribute
|
||||
/// [no_std]: https://doc.rust-lang.org/reference/names/preludes.html#the-no_std-attribute
|
||||
#[stable(feature = "global_alloc", since = "1.28.0")]
|
||||
#[rustc_const_unstable(feature = "const_alloc_error", issue = "92523")]
|
||||
#[cfg(all(not(no_global_oom_handling), not(test)))]
|
||||
|
@ -397,9 +410,10 @@ pub mod __alloc_error_handler {
|
|||
if unsafe { __rust_alloc_error_handler_should_panic != 0 } {
|
||||
panic!("memory allocation of {size} bytes failed")
|
||||
} else {
|
||||
core::panicking::panic_nounwind_fmt(format_args!(
|
||||
"memory allocation of {size} bytes failed"
|
||||
))
|
||||
core::panicking::panic_nounwind_fmt(
|
||||
format_args!("memory allocation of {size} bytes failed"),
|
||||
/* force_no_backtrace */ false,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,8 +90,8 @@
|
|||
#![warn(missing_docs)]
|
||||
#![allow(explicit_outlives_requirements)]
|
||||
#![warn(multiple_supertrait_upcastable)]
|
||||
#![cfg_attr(not(bootstrap), allow(internal_features))]
|
||||
#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))]
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustdoc::redundant_explicit_links)]
|
||||
//
|
||||
// Library features:
|
||||
// tidy-alphabetical-start
|
||||
|
@ -122,6 +122,7 @@
|
|||
#![feature(const_waker)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(core_panic)]
|
||||
#![feature(deprecated_suggestion)]
|
||||
#![feature(dispatch_from_dyn)]
|
||||
#![feature(error_generic_member_access)]
|
||||
#![feature(error_in_core)]
|
||||
|
@ -145,7 +146,6 @@
|
|||
#![feature(ptr_metadata)]
|
||||
#![feature(ptr_sub_ptr)]
|
||||
#![feature(receiver_trait)]
|
||||
#![feature(saturating_int_impl)]
|
||||
#![feature(set_ptr_value)]
|
||||
#![feature(sized_type_properties)]
|
||||
#![feature(slice_from_ptr_range)]
|
||||
|
|
|
@ -594,7 +594,7 @@ impl<T> [T] {
|
|||
/// ```
|
||||
#[rustc_allow_incoherent_impl]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(since = "1.3.0", note = "renamed to join")]
|
||||
#[deprecated(since = "1.3.0", note = "renamed to join", suggestion = "join")]
|
||||
pub fn connect<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
|
||||
where
|
||||
Self: Join<Separator>,
|
||||
|
|
|
@ -1228,8 +1228,8 @@ impl<T, A: Allocator> Vec<T, A> {
|
|||
/// Shortens the vector, keeping the first `len` elements and dropping
|
||||
/// the rest.
|
||||
///
|
||||
/// If `len` is greater than the vector's current length, this has no
|
||||
/// effect.
|
||||
/// If `len` is greater or equal to the vector's current length, this has
|
||||
/// no effect.
|
||||
///
|
||||
/// The [`drain`] method can emulate `truncate`, but causes the excess
|
||||
/// elements to be returned instead of dropped.
|
||||
|
@ -1336,6 +1336,15 @@ impl<T, A: Allocator> Vec<T, A> {
|
|||
/// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer
|
||||
/// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`].
|
||||
///
|
||||
/// This method guarantees that for the purpose of the aliasing model, this method
|
||||
/// does not materialize a reference to the underlying slice, and thus the returned pointer
|
||||
/// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`].
|
||||
/// Note that calling other methods that materialize mutable references to the slice,
|
||||
/// or mutable references to specific elements you are planning on accessing through this pointer,
|
||||
/// as well as writing to those elements, may still invalidate this pointer.
|
||||
/// See the second example below for how this guarantee can be used.
|
||||
///
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@ -1349,8 +1358,25 @@ impl<T, A: Allocator> Vec<T, A> {
|
|||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Due to the aliasing guarantee, the following code is legal:
|
||||
///
|
||||
/// ```rust
|
||||
/// unsafe {
|
||||
/// let mut v = vec![0, 1, 2];
|
||||
/// let ptr1 = v.as_ptr();
|
||||
/// let _ = ptr1.read();
|
||||
/// let ptr2 = v.as_mut_ptr().offset(2);
|
||||
/// ptr2.write(2);
|
||||
/// // Notably, the write to `ptr2` did *not* invalidate `ptr1`
|
||||
/// // because it mutated a different element:
|
||||
/// let _ = ptr1.read();
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`as_mut_ptr`]: Vec::as_mut_ptr
|
||||
/// [`as_ptr`]: Vec::as_ptr
|
||||
#[stable(feature = "vec_as_ptr", since = "1.37.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
|
||||
#[inline]
|
||||
pub fn as_ptr(&self) -> *const T {
|
||||
// We shadow the slice method of the same name to avoid going through
|
||||
|
@ -1366,6 +1392,15 @@ impl<T, A: Allocator> Vec<T, A> {
|
|||
/// Modifying the vector may cause its buffer to be reallocated,
|
||||
/// which would also make any pointers to it invalid.
|
||||
///
|
||||
/// This method guarantees that for the purpose of the aliasing model, this method
|
||||
/// does not materialize a reference to the underlying slice, and thus the returned pointer
|
||||
/// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`].
|
||||
/// Note that calling other methods that materialize references to the slice,
|
||||
/// or references to specific elements you are planning on accessing through this pointer,
|
||||
/// may still invalidate this pointer.
|
||||
/// See the second example below for how this guarantee can be used.
|
||||
///
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@ -1383,7 +1418,25 @@ impl<T, A: Allocator> Vec<T, A> {
|
|||
/// }
|
||||
/// assert_eq!(&*x, &[0, 1, 2, 3]);
|
||||
/// ```
|
||||
///
|
||||
/// Due to the aliasing guarantee, the following code is legal:
|
||||
///
|
||||
/// ```rust
|
||||
/// unsafe {
|
||||
/// let mut v = vec![0];
|
||||
/// let ptr1 = v.as_mut_ptr();
|
||||
/// ptr1.write(1);
|
||||
/// let ptr2 = v.as_mut_ptr();
|
||||
/// ptr2.write(2);
|
||||
/// // Notably, the write to `ptr2` did *not* invalidate `ptr1`:
|
||||
/// ptr1.write(3);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`as_mut_ptr`]: Vec::as_mut_ptr
|
||||
/// [`as_ptr`]: Vec::as_ptr
|
||||
#[stable(feature = "vec_as_ptr", since = "1.37.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
|
||||
#[inline]
|
||||
pub fn as_mut_ptr(&mut self) -> *mut T {
|
||||
// We shadow the slice method of the same name to avoid going through
|
||||
|
@ -3403,6 +3456,36 @@ impl<T: Clone> From<&mut [T]> for Vec<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "vec_from_array_ref", since = "1.74.0")]
|
||||
impl<T: Clone, const N: usize> From<&[T; N]> for Vec<T> {
|
||||
/// Allocate a `Vec<T>` and fill it by cloning `s`'s items.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// assert_eq!(Vec::from(&[1, 2, 3]), vec![1, 2, 3]);
|
||||
/// ```
|
||||
fn from(s: &[T; N]) -> Vec<T> {
|
||||
Self::from(s.as_slice())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "vec_from_array_ref", since = "1.74.0")]
|
||||
impl<T: Clone, const N: usize> From<&mut [T; N]> for Vec<T> {
|
||||
/// Allocate a `Vec<T>` and fill it by cloning `s`'s items.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]);
|
||||
/// ```
|
||||
fn from(s: &mut [T; N]) -> Vec<T> {
|
||||
Self::from(s.as_mut_slice())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "vec_from_array", since = "1.44.0")]
|
||||
impl<T, const N: usize> From<[T; N]> for Vec<T> {
|
||||
|
|
|
@ -20,3 +20,7 @@
|
|||
|
||||
# `seccomp`'s comment gets understood as a doctest
|
||||
--no-doc-comments
|
||||
|
||||
# These functions use the `__preserve_most` calling convention, which neither bindgen
|
||||
# nor Rust currently understand, and which Clang currently declares to be unstable.
|
||||
--blocklist-function __list_.*_report
|
||||
|
|
|
@ -18,6 +18,6 @@
|
|||
#include <linux/workqueue.h>
|
||||
|
||||
/* `bindgen` gets confused at certain things. */
|
||||
const size_t BINDINGS_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;
|
||||
const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL;
|
||||
const gfp_t BINDINGS___GFP_ZERO = __GFP_ZERO;
|
||||
const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;
|
||||
const gfp_t RUST_CONST_HELPER_GFP_KERNEL = GFP_KERNEL;
|
||||
const gfp_t RUST_CONST_HELPER___GFP_ZERO = __GFP_ZERO;
|
||||
|
|
|
@ -48,6 +48,3 @@ mod bindings_helper {
|
|||
}
|
||||
|
||||
pub use bindings_raw::*;
|
||||
|
||||
pub const GFP_KERNEL: gfp_t = BINDINGS_GFP_KERNEL;
|
||||
pub const __GFP_ZERO: gfp_t = BINDINGS___GFP_ZERO;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
* accidentally exposed.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#define EXPORT_SYMBOL_RUST_GPL(sym) extern int sym; EXPORT_SYMBOL_GPL(sym)
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ unsafe fn krealloc_aligned(ptr: *mut u8, new_layout: Layout, flags: bindings::gf
|
|||
|
||||
let mut size = layout.size();
|
||||
|
||||
if layout.align() > bindings::BINDINGS_ARCH_SLAB_MINALIGN {
|
||||
if layout.align() > bindings::ARCH_SLAB_MINALIGN {
|
||||
// The alignment requirement exceeds the slab guarantee, thus try to enlarge the size
|
||||
// to use the "power-of-two" size/alignment guarantee (see comments in `kmalloc()` for
|
||||
// more information).
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
//! Kernel errors.
|
||||
//!
|
||||
//! C header: [`include/uapi/asm-generic/errno-base.h`](../../../include/uapi/asm-generic/errno-base.h)
|
||||
//! C header: [`include/uapi/asm-generic/errno-base.h`](srctree/include/uapi/asm-generic/errno-base.h)
|
||||
|
||||
use crate::str::CStr;
|
||||
|
||||
|
@ -335,3 +335,7 @@ where
|
|||
Err(e) => T::from(e.to_errno() as i16),
|
||||
}
|
||||
}
|
||||
|
||||
/// Error message for calling a default function of a [`#[vtable]`](macros::vtable) trait.
|
||||
pub const VTABLE_DEFAULT_ERROR: &str =
|
||||
"This function must not be called, see the #[vtable] documentation.";
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
//! ioctl() number definitions
|
||||
//!
|
||||
//! C header: [`include/asm-generic/ioctl.h`](../../../../include/asm-generic/ioctl.h)
|
||||
//! C header: [`include/asm-generic/ioctl.h`](srctree/include/asm-generic/ioctl.h)
|
||||
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
//! KUnit-based macros for Rust unit tests.
|
||||
//!
|
||||
//! C header: [`include/kunit/test.h`](../../../../../include/kunit/test.h)
|
||||
//! C header: [`include/kunit/test.h`](srctree/include/kunit/test.h)
|
||||
//!
|
||||
//! Reference: <https://docs.kernel.org/dev-tools/kunit/index.html>
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
//! Printing facilities.
|
||||
//!
|
||||
//! C header: [`include/linux/printk.h`](../../../../include/linux/printk.h)
|
||||
//! C header: [`include/linux/printk.h`](srctree/include/linux/printk.h)
|
||||
//!
|
||||
//! Reference: <https://www.kernel.org/doc/html/latest/core-api/printk-basics.html>
|
||||
|
||||
|
@ -48,7 +48,7 @@ pub mod format_strings {
|
|||
/// The format string is always the same for a given level, i.e. for a
|
||||
/// given `prefix`, which are the kernel's `KERN_*` constants.
|
||||
///
|
||||
/// [`_printk`]: ../../../../include/linux/printk.h
|
||||
/// [`_printk`]: srctree/include/linux/printk.h
|
||||
const fn generate(is_cont: bool, prefix: &[u8; 3]) -> [u8; LENGTH] {
|
||||
// Ensure the `KERN_*` macros are what we expect.
|
||||
assert!(prefix[0] == b'\x01');
|
||||
|
@ -97,7 +97,7 @@ pub mod format_strings {
|
|||
/// The format string must be one of the ones in [`format_strings`], and
|
||||
/// the module name must be null-terminated.
|
||||
///
|
||||
/// [`_printk`]: ../../../../include/linux/_printk.h
|
||||
/// [`_printk`]: srctree/include/linux/_printk.h
|
||||
#[doc(hidden)]
|
||||
#[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))]
|
||||
pub unsafe fn call_printk(
|
||||
|
@ -120,7 +120,7 @@ pub unsafe fn call_printk(
|
|||
///
|
||||
/// Public but hidden since it should only be used from public macros.
|
||||
///
|
||||
/// [`_printk`]: ../../../../include/linux/printk.h
|
||||
/// [`_printk`]: srctree/include/linux/printk.h
|
||||
#[doc(hidden)]
|
||||
#[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))]
|
||||
pub fn call_printk_cont(args: fmt::Arguments<'_>) {
|
||||
|
|
|
@ -608,6 +608,12 @@ impl<'a> TryFrom<&'a CStr> for CString {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CString {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
/// A convenience alias for [`core::format_args`].
|
||||
#[macro_export]
|
||||
macro_rules! fmt {
|
||||
|
|
|
@ -50,7 +50,7 @@ macro_rules! new_condvar {
|
|||
/// fn wait_for_value(e: &Example, v: u32) {
|
||||
/// let mut guard = e.value.lock();
|
||||
/// while *guard != v {
|
||||
/// e.value_changed.wait_uninterruptible(&mut guard);
|
||||
/// e.value_changed.wait(&mut guard);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
|
@ -69,7 +69,7 @@ macro_rules! new_condvar {
|
|||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`struct wait_queue_head`]: ../../../include/linux/wait.h
|
||||
/// [`struct wait_queue_head`]: srctree/include/linux/wait.h
|
||||
#[pin_data]
|
||||
pub struct CondVar {
|
||||
#[pin]
|
||||
|
@ -120,26 +120,26 @@ impl CondVar {
|
|||
unsafe { bindings::finish_wait(self.wait_list.get(), wait.get()) };
|
||||
}
|
||||
|
||||
/// Releases the lock and waits for a notification in interruptible mode.
|
||||
/// Releases the lock and waits for a notification in uninterruptible mode.
|
||||
///
|
||||
/// Atomically releases the given lock (whose ownership is proven by the guard) and puts the
|
||||
/// thread to sleep, reacquiring the lock on wake up. It wakes up when notified by
|
||||
/// [`CondVar::notify_one`] or [`CondVar::notify_all`], or when the thread receives a signal.
|
||||
/// It may also wake up spuriously.
|
||||
///
|
||||
/// Returns whether there is a signal pending.
|
||||
#[must_use = "wait returns if a signal is pending, so the caller must check the return value"]
|
||||
pub fn wait<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T, B>) -> bool {
|
||||
self.wait_internal(bindings::TASK_INTERRUPTIBLE, guard);
|
||||
crate::current!().signal_pending()
|
||||
/// [`CondVar::notify_one`] or [`CondVar::notify_all`]. Note that it may also wake up
|
||||
/// spuriously.
|
||||
pub fn wait<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T, B>) {
|
||||
self.wait_internal(bindings::TASK_UNINTERRUPTIBLE, guard);
|
||||
}
|
||||
|
||||
/// Releases the lock and waits for a notification in uninterruptible mode.
|
||||
/// Releases the lock and waits for a notification in interruptible mode.
|
||||
///
|
||||
/// Similar to [`CondVar::wait`], except that the wait is not interruptible. That is, the
|
||||
/// thread won't wake up due to signals. It may, however, wake up supirously.
|
||||
pub fn wait_uninterruptible<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T, B>) {
|
||||
self.wait_internal(bindings::TASK_UNINTERRUPTIBLE, guard)
|
||||
/// Similar to [`CondVar::wait`], except that the wait is interruptible. That is, the thread may
|
||||
/// wake up due to signals. It may also wake up spuriously.
|
||||
///
|
||||
/// Returns whether there is a signal pending.
|
||||
#[must_use = "wait_interruptible returns if a signal is pending, so the caller must check the return value"]
|
||||
pub fn wait_interruptible<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T, B>) -> bool {
|
||||
self.wait_internal(bindings::TASK_INTERRUPTIBLE, guard);
|
||||
crate::current!().signal_pending()
|
||||
}
|
||||
|
||||
/// Calls the kernel function to notify the appropriate number of threads with the given flags.
|
||||
|
|
|
@ -84,7 +84,7 @@ macro_rules! new_mutex {
|
|||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`struct mutex`]: ../../../../include/linux/mutex.h
|
||||
/// [`struct mutex`]: srctree/include/linux/mutex.h
|
||||
pub type Mutex<T> = super::Lock<T, MutexBackend>;
|
||||
|
||||
/// A kernel `struct mutex` lock backend.
|
||||
|
|
|
@ -82,7 +82,7 @@ macro_rules! new_spinlock {
|
|||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`spinlock_t`]: ../../../../include/linux/spinlock.h
|
||||
/// [`spinlock_t`]: srctree/include/linux/spinlock.h
|
||||
pub type SpinLock<T> = super::Lock<T, SpinLockBackend>;
|
||||
|
||||
/// A kernel `spinlock_t` lock backend.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
//! Tasks (threads and processes).
|
||||
//!
|
||||
//! C header: [`include/linux/sched.h`](../../../../include/linux/sched.h).
|
||||
//! C header: [`include/linux/sched.h`](srctree/include/linux/sched.h).
|
||||
|
||||
use crate::{bindings, types::Opaque};
|
||||
use core::{marker::PhantomData, ops::Deref, ptr};
|
||||
|
|
|
@ -132,7 +132,7 @@
|
|||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! C header: [`include/linux/workqueue.h`](../../../../include/linux/workqueue.h)
|
||||
//! C header: [`include/linux/workqueue.h`](srctree/include/linux/workqueue.h)
|
||||
|
||||
use crate::{bindings, prelude::*, sync::Arc, sync::LockClassKey, types::Opaque};
|
||||
use alloc::alloc::AllocError;
|
||||
|
|
|
@ -20,7 +20,7 @@ use proc_macro::TokenStream;
|
|||
/// The `type` argument should be a type which implements the [`Module`]
|
||||
/// trait. Also accepts various forms of kernel metadata.
|
||||
///
|
||||
/// C header: [`include/linux/moduleparam.h`](../../../include/linux/moduleparam.h)
|
||||
/// C header: [`include/linux/moduleparam.h`](srctree/include/linux/moduleparam.h)
|
||||
///
|
||||
/// [`Module`]: ../kernel/trait.Module.html
|
||||
///
|
||||
|
@ -87,27 +87,49 @@ pub fn module(ts: TokenStream) -> TokenStream {
|
|||
/// implementation could just return `Error::EINVAL`); Linux typically use C
|
||||
/// `NULL` pointers to represent these functions.
|
||||
///
|
||||
/// This attribute is intended to close the gap. Traits can be declared and
|
||||
/// implemented with the `#[vtable]` attribute, and a `HAS_*` associated constant
|
||||
/// will be generated for each method in the trait, indicating if the implementor
|
||||
/// has overridden a method.
|
||||
/// This attribute closes that gap. A trait can be annotated with the
|
||||
/// `#[vtable]` attribute. Implementers of the trait will then also have to
|
||||
/// annotate the trait with `#[vtable]`. This attribute generates a `HAS_*`
|
||||
/// associated constant bool for each method in the trait that is set to true if
|
||||
/// the implementer has overridden the associated method.
|
||||
///
|
||||
/// This attribute is not needed if all methods are required.
|
||||
/// For a trait method to be optional, it must have a default implementation.
|
||||
/// This is also the case for traits annotated with `#[vtable]`, but in this
|
||||
/// case the default implementation will never be executed. The reason for this
|
||||
/// is that the functions will be called through function pointers installed in
|
||||
/// C side vtables. When an optional method is not implemented on a `#[vtable]`
|
||||
/// trait, a NULL entry is installed in the vtable. Thus the default
|
||||
/// implementation is never called. Since these traits are not designed to be
|
||||
/// used on the Rust side, it should not be possible to call the default
|
||||
/// implementation. This is done to ensure that we call the vtable methods
|
||||
/// through the C vtable, and not through the Rust vtable. Therefore, the
|
||||
/// default implementation should call `kernel::build_error`, which prevents
|
||||
/// calls to this function at compile time:
|
||||
///
|
||||
/// ```compile_fail
|
||||
/// # use kernel::error::VTABLE_DEFAULT_ERROR;
|
||||
/// kernel::build_error(VTABLE_DEFAULT_ERROR)
|
||||
/// ```
|
||||
///
|
||||
/// Note that you might need to import [`kernel::error::VTABLE_DEFAULT_ERROR`].
|
||||
///
|
||||
/// This macro should not be used when all functions are required.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use kernel::error::VTABLE_DEFAULT_ERROR;
|
||||
/// use kernel::prelude::*;
|
||||
///
|
||||
/// // Declares a `#[vtable]` trait
|
||||
/// #[vtable]
|
||||
/// pub trait Operations: Send + Sync + Sized {
|
||||
/// fn foo(&self) -> Result<()> {
|
||||
/// Err(EINVAL)
|
||||
/// kernel::build_error(VTABLE_DEFAULT_ERROR)
|
||||
/// }
|
||||
///
|
||||
/// fn bar(&self) -> Result<()> {
|
||||
/// Err(EINVAL)
|
||||
/// kernel::build_error(VTABLE_DEFAULT_ERROR)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
|
@ -125,6 +147,8 @@ pub fn module(ts: TokenStream) -> TokenStream {
|
|||
/// assert_eq!(<Foo as Operations>::HAS_FOO, true);
|
||||
/// assert_eq!(<Foo as Operations>::HAS_BAR, false);
|
||||
/// ```
|
||||
///
|
||||
/// [`kernel::error::VTABLE_DEFAULT_ERROR`]: ../kernel/error/constant.VTABLE_DEFAULT_ERROR.html
|
||||
#[proc_macro_attribute]
|
||||
pub fn vtable(attr: TokenStream, ts: TokenStream) -> TokenStream {
|
||||
vtable::vtable(attr, ts)
|
||||
|
@ -254,8 +278,8 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||
/// Within the `paste!` macro, identifiers inside `[<` and `>]` are concatenated together to form a
|
||||
/// single identifier.
|
||||
///
|
||||
/// This is similar to the [`paste`] crate, but with pasting feature limited to identifiers
|
||||
/// (literals, lifetimes and documentation strings are not supported). There is a difference in
|
||||
/// This is similar to the [`paste`] crate, but with pasting feature limited to identifiers and
|
||||
/// literals (lifetimes and documentation strings are not supported). There is a difference in
|
||||
/// supported modifiers as well.
|
||||
///
|
||||
/// # Example
|
||||
|
@ -337,6 +361,24 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||
/// assert_eq!(br_ok(), binder_driver_return_protocol_BR_OK);
|
||||
/// ```
|
||||
///
|
||||
/// # Literals
|
||||
///
|
||||
/// Literals can also be concatenated with other identifiers:
|
||||
///
|
||||
/// ```ignore
|
||||
/// macro_rules! create_numbered_fn {
|
||||
/// ($name:literal, $val:literal) => {
|
||||
/// kernel::macros::paste! {
|
||||
/// fn [<some_ $name _fn $val>]() -> u32 { $val }
|
||||
/// }
|
||||
/// };
|
||||
/// }
|
||||
///
|
||||
/// create_numbered_fn!("foo", 100);
|
||||
///
|
||||
/// assert_eq!(some_foo_fn100(), 100)
|
||||
/// ```
|
||||
///
|
||||
/// [`paste`]: https://docs.rs/paste/
|
||||
#[proc_macro]
|
||||
pub fn paste(input: TokenStream) -> TokenStream {
|
||||
|
|
|
@ -9,7 +9,15 @@ fn concat(tokens: &[TokenTree], group_span: Span) -> TokenTree {
|
|||
loop {
|
||||
match tokens.next() {
|
||||
None => break,
|
||||
Some(TokenTree::Literal(lit)) => segments.push((lit.to_string(), lit.span())),
|
||||
Some(TokenTree::Literal(lit)) => {
|
||||
// Allow us to concat string literals by stripping quotes
|
||||
let mut value = lit.to_string();
|
||||
if value.starts_with('"') && value.ends_with('"') {
|
||||
value.remove(0);
|
||||
value.pop();
|
||||
}
|
||||
segments.push((value, lit.span()));
|
||||
}
|
||||
Some(TokenTree::Ident(ident)) => {
|
||||
let mut value = ident.to_string();
|
||||
if value.starts_with("r#") {
|
||||
|
|
|
@ -275,6 +275,7 @@ rust_common_cmd = \
|
|||
--extern alloc --extern kernel \
|
||||
--crate-type rlib -L $(objtree)/rust/ \
|
||||
--crate-name $(basename $(notdir $@)) \
|
||||
--sysroot=/dev/null \
|
||||
--out-dir $(dir $@) --emit=dep-info=$(depfile)
|
||||
|
||||
# `--emit=obj`, `--emit=asm` and `--emit=llvm-ir` imply a single codegen unit
|
||||
|
|
|
@ -31,7 +31,7 @@ llvm)
|
|||
fi
|
||||
;;
|
||||
rustc)
|
||||
echo 1.73.0
|
||||
echo 1.74.1
|
||||
;;
|
||||
bindgen)
|
||||
echo 0.65.1
|
||||
|
|
Loading…
Reference in New Issue