mirror of
https://github.com/torvalds/linux.git
synced 2026-05-26 16:12:59 +02:00
Rust task & schedule changes for v6.17:
- Make Task, CondVar and PollCondVar methods inline to avoid unnecessary function calls - Add might_sleep() support for Rust code: Rust's "#[track_caller]" mechanism is used so that Rust's might_sleep() doesn't need to be defined as a macro -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEj5IosQTPz8XU1wRHSXnow7UH+rgFAmhbLOgACgkQSXnow7UH +riscwf/e/+KmJTox5/JOqs6yxxQdCHMaGnMK62E5AII7NsiUI8+XB9z6efzCMmy kS2W7aCmBZX67Y1B/xRL/ArHMBAJBi/CrCedZJcmzfB9aMa4Lj4mgiPkbUXkxE6Q F5CDQK21ftu+0Q7Hhlq92ec17ZWodOvNxCFBBmjtQqUvBzj0dY45jcG7brs+N+1Z t9UO3YokzukNqpIXTpG0HFP+XNafWWCgn9iIQ44lRxIaAoPI44uJjh1OXLTrZ1M9 EMWYIrsY3b71Im78l6pzr+UOzJdJLI+QCBiz7ySLYz3kZ5dEfFdJOsumbc0G8A69 VSGDFPEbJxZYuMxrH0E44XmxH4rJdA== =gD/Y -----END PGP SIGNATURE----- Merge tag 'rust-sched.2025.06.24' of git://git.kernel.org/pub/scm/linux/kernel/git/boqun/linux into sched/core Rust task & schedule changes for v6.17: - Make Task, CondVar and PollCondVar methods inline to avoid unnecessary function calls - Add might_sleep() support for Rust code: Rust's "#[track_caller]" mechanism is used so that Rust's might_sleep() doesn't need to be defined as a macro Signed-off-by: Peter Zijlstra <peterz@infradead.org> # -----BEGIN PGP SIGNATURE----- # # iQEzBAABCAAdFiEEj5IosQTPz8XU1wRHSXnow7UH+rgFAmhbLOgACgkQSXnow7UH # +riscwf/e/+KmJTox5/JOqs6yxxQdCHMaGnMK62E5AII7NsiUI8+XB9z6efzCMmy # kS2W7aCmBZX67Y1B/xRL/ArHMBAJBi/CrCedZJcmzfB9aMa4Lj4mgiPkbUXkxE6Q # F5CDQK21ftu+0Q7Hhlq92ec17ZWodOvNxCFBBmjtQqUvBzj0dY45jcG7brs+N+1Z # t9UO3YokzukNqpIXTpG0HFP+XNafWWCgn9iIQ44lRxIaAoPI44uJjh1OXLTrZ1M9 # EMWYIrsY3b71Im78l6pzr+UOzJdJLI+QCBiz7ySLYz3kZ5dEfFdJOsumbc0G8A69 # VSGDFPEbJxZYuMxrH0E44XmxH4rJdA== # =gD/Y # -----END PGP SIGNATURE----- # gpg: Signature made Wed 25 Jun 2025 12:55:36 AM CEST # gpg: using RSA key 8F9228B104CFCFC5D4D704474979E8C3B507FAB8 # gpg: Can't check signature: No public key
This commit is contained in:
commit
d398a68e8b
|
|
@ -142,6 +142,9 @@ config RUSTC_HAS_SPAN_FILE
|
|||
config RUSTC_HAS_UNNECESSARY_TRANSMUTES
|
||||
def_bool RUSTC_VERSION >= 108800
|
||||
|
||||
config RUSTC_HAS_FILE_WITH_NUL
|
||||
def_bool RUSTC_VERSION >= 108900
|
||||
|
||||
config PAHOLE_VERSION
|
||||
int
|
||||
default $(shell,$(srctree)/scripts/pahole-version.sh $(PAHOLE))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched/task.h>
|
||||
|
||||
void rust_helper_might_resched(void)
|
||||
{
|
||||
might_resched();
|
||||
}
|
||||
|
||||
struct task_struct *rust_helper_get_current(void)
|
||||
{
|
||||
return current;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@
|
|||
#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(coerce_unsized))]
|
||||
#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(dispatch_from_dyn))]
|
||||
#![cfg_attr(not(CONFIG_RUSTC_HAS_COERCE_POINTEE), feature(unsize))]
|
||||
//
|
||||
// `feature(file_with_nul)` is expected to become stable. Before Rust 1.89.0, it did not exist, so
|
||||
// enable it conditionally.
|
||||
#![cfg_attr(CONFIG_RUSTC_HAS_FILE_WITH_NUL, feature(file_with_nul))]
|
||||
|
||||
// Ensure conditional compilation based on the kernel configuration works;
|
||||
// otherwise we may silently break things like initcall handling.
|
||||
|
|
@ -274,3 +278,47 @@ macro_rules! asm {
|
|||
::core::arch::asm!( $($asm)*, $($rest)* )
|
||||
};
|
||||
}
|
||||
|
||||
/// Gets the C string file name of a [`Location`].
|
||||
///
|
||||
/// If `file_with_nul()` is not available, returns a string that warns about it.
|
||||
///
|
||||
/// [`Location`]: core::panic::Location
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use kernel::file_from_location;
|
||||
///
|
||||
/// #[track_caller]
|
||||
/// fn foo() {
|
||||
/// let caller = core::panic::Location::caller();
|
||||
///
|
||||
/// // Output:
|
||||
/// // - A path like "rust/kernel/example.rs" if file_with_nul() is available.
|
||||
/// // - "<Location::file_with_nul() not supported>" otherwise.
|
||||
/// let caller_file = file_from_location(caller);
|
||||
///
|
||||
/// // Prints out the message with caller's file name.
|
||||
/// pr_info!("foo() called in file {caller_file:?}\n");
|
||||
///
|
||||
/// # if cfg!(CONFIG_RUSTC_HAS_FILE_WITH_NUL) {
|
||||
/// # assert_eq!(Ok(caller.file()), caller_file.to_str());
|
||||
/// # }
|
||||
/// }
|
||||
///
|
||||
/// # foo();
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn file_from_location<'a>(loc: &'a core::panic::Location<'a>) -> &'a core::ffi::CStr {
|
||||
#[cfg(CONFIG_RUSTC_HAS_FILE_WITH_NUL)]
|
||||
{
|
||||
loc.file_with_nul()
|
||||
}
|
||||
|
||||
#[cfg(not(CONFIG_RUSTC_HAS_FILE_WITH_NUL))]
|
||||
{
|
||||
let _ = loc;
|
||||
c"<Location::file_with_nul() not supported>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -216,6 +216,7 @@ fn notify(&self, count: c_int) {
|
|||
/// This method behaves like `notify_one`, except that it hints to the scheduler that the
|
||||
/// current thread is about to go to sleep, so it should schedule the target thread on the same
|
||||
/// CPU.
|
||||
#[inline]
|
||||
pub fn notify_sync(&self) {
|
||||
// SAFETY: `wait_queue_head` points to valid memory.
|
||||
unsafe { bindings::__wake_up_sync(self.wait_queue_head.get(), TASK_NORMAL) };
|
||||
|
|
@ -225,6 +226,7 @@ pub fn notify_sync(&self) {
|
|||
///
|
||||
/// This is not 'sticky' in the sense that if no thread is waiting, the notification is lost
|
||||
/// completely (as opposed to automatically waking up the next waiter).
|
||||
#[inline]
|
||||
pub fn notify_one(&self) {
|
||||
self.notify(1);
|
||||
}
|
||||
|
|
@ -233,6 +235,7 @@ pub fn notify_one(&self) {
|
|||
///
|
||||
/// This is not 'sticky' in the sense that if no thread is waiting, the notification is lost
|
||||
/// completely (as opposed to automatically waking up the next waiter).
|
||||
#[inline]
|
||||
pub fn notify_all(&self) {
|
||||
self.notify(0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ fn deref(&self) -> &CondVar {
|
|||
|
||||
#[pinned_drop]
|
||||
impl PinnedDrop for PollCondVar {
|
||||
#[inline]
|
||||
fn drop(self: Pin<&mut Self>) {
|
||||
// Clear anything registered using `register_wait`.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -173,6 +173,7 @@ pub fn current_raw() -> *mut bindings::task_struct {
|
|||
/// Callers must ensure that the returned object is only used to access a [`CurrentTask`]
|
||||
/// within the task context that was active when this function was called. For more details,
|
||||
/// see the invariants section for [`CurrentTask`].
|
||||
#[inline]
|
||||
pub unsafe fn current() -> impl Deref<Target = CurrentTask> {
|
||||
struct TaskRef {
|
||||
task: *const CurrentTask,
|
||||
|
|
@ -222,24 +223,28 @@ pub fn pid(&self) -> Pid {
|
|||
}
|
||||
|
||||
/// Returns the UID of the given task.
|
||||
#[inline]
|
||||
pub fn uid(&self) -> Kuid {
|
||||
// SAFETY: It's always safe to call `task_uid` on a valid task.
|
||||
Kuid::from_raw(unsafe { bindings::task_uid(self.as_ptr()) })
|
||||
}
|
||||
|
||||
/// Returns the effective UID of the given task.
|
||||
#[inline]
|
||||
pub fn euid(&self) -> Kuid {
|
||||
// SAFETY: It's always safe to call `task_euid` on a valid task.
|
||||
Kuid::from_raw(unsafe { bindings::task_euid(self.as_ptr()) })
|
||||
}
|
||||
|
||||
/// Determines whether the given task has pending signals.
|
||||
#[inline]
|
||||
pub fn signal_pending(&self) -> bool {
|
||||
// SAFETY: It's always safe to call `signal_pending` on a valid task.
|
||||
unsafe { bindings::signal_pending(self.as_ptr()) != 0 }
|
||||
}
|
||||
|
||||
/// Returns task's pid namespace with elevated reference count
|
||||
#[inline]
|
||||
pub fn get_pid_ns(&self) -> Option<ARef<PidNamespace>> {
|
||||
// SAFETY: By the type invariant, we know that `self.0` is valid.
|
||||
let ptr = unsafe { bindings::task_get_pid_ns(self.as_ptr()) };
|
||||
|
|
@ -255,6 +260,7 @@ pub fn get_pid_ns(&self) -> Option<ARef<PidNamespace>> {
|
|||
|
||||
/// Returns the given task's pid in the provided pid namespace.
|
||||
#[doc(alias = "task_tgid_nr_ns")]
|
||||
#[inline]
|
||||
pub fn tgid_nr_ns(&self, pidns: Option<&PidNamespace>) -> Pid {
|
||||
let pidns = match pidns {
|
||||
Some(pidns) => pidns.as_ptr(),
|
||||
|
|
@ -268,6 +274,7 @@ pub fn tgid_nr_ns(&self, pidns: Option<&PidNamespace>) -> Pid {
|
|||
}
|
||||
|
||||
/// Wakes up the task.
|
||||
#[inline]
|
||||
pub fn wake_up(&self) {
|
||||
// SAFETY: It's always safe to call `wake_up_process` on a valid task, even if the task
|
||||
// running.
|
||||
|
|
@ -341,11 +348,13 @@ pub fn active_pid_ns(&self) -> Option<&PidNamespace> {
|
|||
|
||||
// SAFETY: The type invariants guarantee that `Task` is always refcounted.
|
||||
unsafe impl crate::types::AlwaysRefCounted for Task {
|
||||
#[inline]
|
||||
fn inc_ref(&self) {
|
||||
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
|
||||
unsafe { bindings::get_task_struct(self.as_ptr()) };
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
|
||||
// SAFETY: The safety requirements guarantee that the refcount is nonzero.
|
||||
unsafe { bindings::put_task_struct(obj.cast().as_ptr()) }
|
||||
|
|
@ -391,3 +400,27 @@ fn eq(&self, other: &Kuid) -> bool {
|
|||
}
|
||||
|
||||
impl Eq for Kuid {}
|
||||
|
||||
/// Annotation for functions that can sleep.
|
||||
///
|
||||
/// Equivalent to the C side [`might_sleep()`], this function serves as
|
||||
/// a debugging aid and a potential scheduling point.
|
||||
///
|
||||
/// This function can only be used in a nonatomic context.
|
||||
///
|
||||
/// [`might_sleep()`]: https://docs.kernel.org/driver-api/basics.html#c.might_sleep
|
||||
#[track_caller]
|
||||
#[inline]
|
||||
pub fn might_sleep() {
|
||||
#[cfg(CONFIG_DEBUG_ATOMIC_SLEEP)]
|
||||
{
|
||||
let loc = core::panic::Location::caller();
|
||||
let file = kernel::file_from_location(loc);
|
||||
|
||||
// SAFETY: `file.as_ptr()` is valid for reading and guaranteed to be nul-terminated.
|
||||
unsafe { crate::bindings::__might_sleep(file.as_ptr().cast(), loc.line() as i32) }
|
||||
}
|
||||
|
||||
// SAFETY: Always safe to call.
|
||||
unsafe { crate::bindings::might_resched() }
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user