Commit b6964fe2 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 5bad4908 711cbfc7
......@@ -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 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
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 unsafe fn __rdl_oom(size: usize, _align: usize) -> ! {
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 @@ pub fn join<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Outp
/// ```
#[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 @@ pub fn into_boxed_slice(mut self) -> Box<[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 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
/// 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 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
/// }
/// ```
///
/// 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 @@ pub fn as_ptr(&self) -> *const T {
/// 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 @@ pub fn as_ptr(&self) -> *const T {
/// }
/// 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 @@ fn from(s: &mut [T]) -> 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 @@ pub(crate) fn from_result<T, F>(f: F) -> T
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 @@ fn try_from(cstr: &'a CStr) -> Result<CString, AllocError> {
}
}
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,28 +120,28 @@ fn wait_internal<T: ?Sized, B: Backend>(&self, wait_state: u32, guard: &mut Guar
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.
/// [`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 interruptible mode.
///
/// 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 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 {
#[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()
}
/// Releases the lock and waits for a notification in uninterruptible 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)
}
/// Calls the kernel function to notify the appropriate number of threads with the given flags.
fn notify(&self, count: i32, flags: u32) {
// SAFETY: `wait_list` points to valid memory.
......
......@@ -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 @@
/// 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.
///
/// 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 attribute is not needed if all methods are required.
/// 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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment