From: Andreas Hindborg <a.hindborg@kernel.org>
To: "Frederic Weisbecker" <frederic@kernel.org>
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
"Anna-Maria Behnsen" <anna-maria@linutronix.de>,
"Thomas Gleixner" <tglx@linutronix.de>,
"Danilo Krummrich" <dakr@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <benno.lossin@proton.me>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"Lyude Paul" <lyude@redhat.com>,
"Guangbo Cui" <2407018371@qq.com>,
"Dirk Behme" <dirk.behme@gmail.com>,
"Daniel Almeida" <daniel.almeida@collabora.com>,
rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v5 02/14] rust: hrtimer: introduce hrtimer support
Date: Wed, 18 Dec 2024 10:53:21 +0100 [thread overview]
Message-ID: <8734ilmi5q.fsf@kernel.org> (raw)
In-Reply-To: <Z2GfRgwIA0-zQmXc@localhost.localdomain> (Frederic Weisbecker's message of "Tue, 17 Dec 2024 16:56:54 +0100")
"Frederic Weisbecker" <frederic@kernel.org> writes:
> Le Tue, Dec 17, 2024 at 04:17:33PM +0100, Andreas Hindborg a écrit :
>> This patch adds support for intrusive use of the hrtimer system. For now,
>> only one timer can be embedded in a Rust struct.
>>
>> The hrtimer Rust API is based on the intrusive style pattern introduced by
>> the Rust workqueue API.
>>
>> Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
>> ---
>> rust/kernel/time.rs | 2 +
>> rust/kernel/time/hrtimer.rs | 296 ++++++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 298 insertions(+)
>>
>> diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
>> index f59e0fea79d3acfddd922f601f569353609aeec1..51c3532eee0184495ed5b7d717860c9980ff2a43 100644
>> --- a/rust/kernel/time.rs
>> +++ b/rust/kernel/time.rs
>> @@ -10,6 +10,8 @@
>>
>> use core::convert::Into;
>>
>> +pub mod hrtimer;
>> +
>> /// The number of nanoseconds per millisecond.
>> pub const NSEC_PER_MSEC: i64 = bindings::NSEC_PER_MSEC as i64;
>>
>> diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..b09bdb8bc2037bf116a9a87b16271f4045f53aa9
>> --- /dev/null
>> +++ b/rust/kernel/time/hrtimer.rs
>> @@ -0,0 +1,296 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +//! Intrusive high resolution timers.
>> +//!
>> +//! Allows running timer callbacks without doing allocations at the time of
>> +//! starting the timer. For now, only one timer per type is allowed.
>> +//!
>> +//! # Vocabulary
>> +//!
>> +//! A timer is initialized in the **stopped** state. A stopped timer can be
>> +//! **started** with an **expiry** time. After the timer is started, it is
>> +//! **running**. When the timer **expires**, the timer handler is executed.
>> +//! After the handler has executed, the timer may be **restarted** or
>> +//! **stopped**. A running timer can be **cancelled** before it's handler is
>> +//! executed. A timer that is cancelled enters the **stopped** state.
>> +//!
>> +//! States:
>> +//!
>> +//! * Stopped
>> +//! * Running
>> +//!
>> +//! Operations:
>> +//!
>> +//! * Start
>> +//! * Cancel
>> +//! * Stop
>> +//! * Restart
>> +//!
>> +//! Events:
>> +//!
>> +//! * Expire
>> +
>> +use crate::{init::PinInit, prelude::*, time::Ktime, types::Opaque};
>> +use core::marker::PhantomData;
>> +
>> +/// A timer backed by a C `struct hrtimer`.
>> +///
>> +/// # Invariants
>> +///
>> +/// * `self.timer` is initialized by `bindings::hrtimer_setup`.
>> +#[pin_data]
>> +#[repr(C)]
>> +pub struct Timer<U> {
>
> I seem to remember we had a debate on that. Why not call that Hrtimer?
> Timer is a bit too generic for a name. I suspect you'll need to introduce
> jiffies based timer bindings in the future as well and then some confusion
> may arise.
Yes, let's rename it. Good call.
>
>> + #[pin]
>> + timer: Opaque<bindings::hrtimer>,
>> + _t: PhantomData<U>,
>> +}
>> +
>> +// SAFETY: A `Timer` can be moved to other threads and used/dropped from there.
>> +unsafe impl<U> Send for Timer<U> {}
>> +
>> +// SAFETY: Timer operations are locked on C side, so it is safe to operate on a
>> +// timer from multiple threads
>> +unsafe impl<U> Sync for Timer<U> {}
>> +
>> +impl<T> Timer<T> {
>> + /// Return an initializer for a new timer instance.
>> + pub fn new() -> impl PinInit<Self>
>> + where
>> + T: TimerCallback,
>> + {
>> + pin_init!(Self {
>> + // INVARIANTS: We initialize `timer` with `hrtimer_setup` below.
>> + timer <- Opaque::ffi_init(move |place: *mut bindings::hrtimer| {
>> + // SAFETY: By design of `pin_init!`, `place` is a pointer live
>> + // allocation. hrtimer_setup will initialize `place` and does
>> + // not require `place` to be initialized prior to the call.
>> + unsafe {
>> + bindings::hrtimer_setup(
>> + place,
>> + Some(T::CallbackTarget::run),
>> + bindings::CLOCK_MONOTONIC as i32,
>> + bindings::hrtimer_mode_HRTIMER_MODE_REL,
>
> Always relative?
`TimerMode` is introduced in patch 12.
>
>> + );
>> + }
>> + }),
>> + _t: PhantomData,
>> + })
>> + }
>> +
>> + /// Get a pointer to the contained `bindings::hrtimer`.
>> + ///
>> + /// # Safety
>> + ///
>> + /// `ptr` must point to a live allocation of at least the size of `Self`.
>> + unsafe fn raw_get(ptr: *const Self) -> *mut bindings::hrtimer {
>> + // SAFETY: The field projection to `timer` does not go out of bounds,
>> + // because the caller of this function promises that `ptr` points to an
>> + // allocation of at least the size of `Self`.
>> + unsafe { Opaque::raw_get(core::ptr::addr_of!((*ptr).timer)) }
>> + }
>> +
>> + /// Cancel an initialized and potentially running timer.
>> + ///
>> + /// If the timer handler is running, this will block until the handler is
>> + /// finished.
>> + ///
>> + /// # Safety
>> + ///
>> + /// `self_ptr` must point to a valid `Self`.
>> + #[allow(dead_code)]
>> + pub(crate) unsafe fn raw_cancel(self_ptr: *const Self) -> bool {
>> + // SAFETY: timer_ptr points to an allocation of at least `Timer` size.
>> + let c_timer_ptr = unsafe { Timer::raw_get(self_ptr) };
>> +
>> + // If handler is running, this will wait for handler to finish before
>> + // returning.
>> + // SAFETY: `c_timer_ptr` is initialized and valid. Synchronization is
>> + // handled on C side.
>> + unsafe { bindings::hrtimer_cancel(c_timer_ptr) != 0 }
>> + }
>> +}
>> +
>> +/// Implemented by pointer types that point to structs that embed a [`Timer`].
>> +///
>> +/// Typical implementers would be [`Box<T>`], [`Arc<T>`], [`ARef<T>`] where `T`
>> +/// has a field of type `Timer`.
>> +///
>> +/// Target must be [`Sync`] because timer callbacks happen in another thread of
>> +/// execution (hard or soft interrupt context).
>> +///
>> +/// Starting a timer returns a [`TimerHandle`] that can be used to manipulate
>> +/// the timer. Note that it is OK to call the start function repeatedly, and
>> +/// that more than one [`TimerHandle`] associated with a `TimerPointer` may
>> +/// exist. A timer can be manipulated through any of the handles, and a handle
>> +/// may represent a cancelled timer.
>> +///
>> +/// [`Box<T>`]: Box
>> +/// [`Arc<T>`]: crate::sync::Arc
>> +/// [`ARef<T>`]: crate::types::ARef
>> +pub trait TimerPointer: Sync + Sized {
>> + /// A handle representing a running timer.
>> + ///
>> + /// If the timer is running or if the timer callback is executing when the
>> + /// handle is dropped, the drop method of `TimerHandle` should not return
>> + /// until the timer is stopped and the callback has completed.
>> + ///
>> + /// Note: It must be safe to leak the handle.
>> + type TimerHandle: TimerHandle;
>> +
>> + /// Start the timer with expiry after `expires` time units. If the timer was
>> + /// already running, it is restarted with the new expiry time.
>> + fn start(self, expires: Ktime) -> Self::TimerHandle;
>> +}
>> +
>> +/// Implemented by [`TimerPointer`] implementers to give the C timer callback a
>> +/// function to call.
>> +// This is split from `TimerPointer` to make it easier to specify trait bounds.
>> +pub trait RawTimerCallback {
>
> RawHrtimerCallback ?
Yes!
>
>> + /// Callback to be called from C when timer fires.
>> + ///
>> + /// # Safety
>> + ///
>> + /// Only to be called by C code in `hrtimer` subsystem. `ptr` must point to
>> + /// the `bindings::hrtimer` structure that was used to start the timer.
>> + unsafe extern "C" fn run(ptr: *mut bindings::hrtimer) -> bindings::hrtimer_restart;
>> +}
>> +
>> +/// Implemented by structs that can the target of a timer callback.
>> +pub trait TimerCallback {
>
> HrtimerCallback ? etc...
Will do a rename pass.
Best regards,
Andreas Hindborg
next prev parent reply other threads:[~2024-12-18 9:53 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-17 15:17 [PATCH v5 00/14] hrtimer Rust API Andreas Hindborg
2024-12-17 15:17 ` [PATCH v5 01/14] rust: time: Add Ktime::from_ns() Andreas Hindborg
2024-12-17 15:17 ` [PATCH v5 02/14] rust: hrtimer: introduce hrtimer support Andreas Hindborg
2024-12-17 15:56 ` Frederic Weisbecker
2024-12-18 9:53 ` Andreas Hindborg [this message]
2024-12-17 15:17 ` [PATCH v5 03/14] rust: sync: add `Arc::as_ptr` Andreas Hindborg
2024-12-17 15:17 ` [PATCH v5 04/14] rust: hrtimer: implement `TimerPointer` for `Arc` Andreas Hindborg
2024-12-17 15:17 ` [PATCH v5 05/14] rust: hrtimer: allow timer restart from timer handler Andreas Hindborg
[not found] ` <H7fH3H6SrsqtETrWgmThmdGUchRyUZh6hQzk4lVMjEOiY_VfUAHbzIGuWZda0aPObsMSxSfyDxhAC9QSTmiPBw==@protonmail.internalid>
[not found] ` <tencent_74DA73ADC948EF2F933592E880CC09D35B09@qq.com>
2025-01-09 13:20 ` Andreas Hindborg
2024-12-17 15:17 ` [PATCH v5 06/14] rust: hrtimer: add `UnsafeTimerPointer` Andreas Hindborg
2024-12-17 15:17 ` [PATCH v5 07/14] rust: hrtimer: add `hrtimer::ScopedTimerPointer` Andreas Hindborg
2024-12-17 15:17 ` [PATCH v5 08/14] rust: hrtimer: implement `UnsafeTimerPointer` for `Pin<&T>` Andreas Hindborg
2024-12-17 15:17 ` [PATCH v5 09/14] rust: hrtimer: implement `UnsafeTimerPointer` for `Pin<&mut T>` Andreas Hindborg
2024-12-17 15:17 ` [PATCH v5 10/14] rust: alloc: add `Box::into_pin` Andreas Hindborg
2024-12-17 15:17 ` [PATCH v5 11/14] rust: hrtimer: implement `TimerPointer` for `Pin<Box<T>>` Andreas Hindborg
2024-12-17 15:17 ` [PATCH v5 12/14] rust: hrtimer: add `TimerMode` Andreas Hindborg
2024-12-17 15:17 ` [PATCH v5 13/14] rust: hrtimer: add clocksource selection through `ClockSource` Andreas Hindborg
2024-12-17 15:17 ` [PATCH v5 14/14] rust: hrtimer: add maintainer entry Andreas Hindborg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=8734ilmi5q.fsf@kernel.org \
--to=a.hindborg@kernel.org \
--cc=2407018371@qq.com \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=anna-maria@linutronix.de \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=dirk.behme@gmail.com \
--cc=frederic@kernel.org \
--cc=gary@garyguo.net \
--cc=linux-kernel@vger.kernel.org \
--cc=lyude@redhat.com \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tglx@linutronix.de \
--cc=tmgross@umich.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.