Received: by 2002:a05:6358:7058:b0:131:369:b2a3 with SMTP id 24csp8120877rwp; Wed, 19 Jul 2023 05:41:19 -0700 (PDT) X-Google-Smtp-Source: APBJJlEtGT0l6i6Ij6tsVRsdz+sLMRYxjsAr6sgYOdvPnlCRyN02JMOU8QZY/DsAL4KXM3taqhGf X-Received: by 2002:a2e:9643:0:b0:2b6:bb08:91c4 with SMTP id z3-20020a2e9643000000b002b6bb0891c4mr4307008ljh.42.1689770478980; Wed, 19 Jul 2023 05:41:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1689770478; cv=none; d=google.com; s=arc-20160816; b=imnW5V1H1IoOoV26Jqb2yyx3XOG5ZuKfo/MTqEgUTbhfryHzjWSMga/5wVniT3ajnb EG0wFNTuJOlYAiQh5TdZGTkGyDjssjq1dp6VhzxN2jULYmPJl9mpNUje37ZvODZm3yoL ivfRc8FrQ1e7yxZxM7ukeDEzaTF9vi34zfeErIAGkBdS86EMcQjWqRT2M8ml3Txo6mOi CwCdhmaXKDaq4sK1xopilJsMwquIlh3ip+qLeI1jig3fsgQYs5icIUThjDfLlH18Es4h BBv/ze7APNdJNDIFBxLsvWfnmZldXP6WnCqzLQbrDWKywkZf32HfbiA0Aertm24fMtBW rF1w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :feedback-id:references:in-reply-to:message-id:subject:cc:from:to :dkim-signature:date; bh=rEVdWSo+kD3Fdo3WkLbwKFyovtZO71VzepvO8eBT3Tw=; fh=dlK+N+A8YWHrLW/5XZKYi9cUl+GvmfyrYolTEWGxlY0=; b=p0hk9FSeKeRa85+LNPVn81qyiH5ksEQDL9ltOAch7EpWfzHZ4zf3oMHrEPy2H6UB4D xDN1rO7PEuxv5s0qx7CTyLyy3qsIzjq+5Xh65p5d4vN+7KBgFjcJq8qlobQzm0brZt1s Xwd+cX5e8s/YsSNS8nwfEK2O7q5PqTAVlQTyhm13yjKymUs+VMiejl6mxIORr5aq7TVC BKyGtktxvphT4ObUF+RAf94fLsg2vBUJ6n8i1PkqRUDPyDEVT703g6ltAcbHYrY9cjaQ /QX8NyED452bZavKaNoFRQ0KaRYQkeueUJ8Ed/0MVulJl42SayqopURngXnUYi5ZLbhL GrQQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@protonmail.com header.s=protonmail3 header.b=MG9ZHnMY; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=protonmail.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id a24-20020a17090682d800b00987e40fd473si2657203ejy.1019.2023.07.19.05.40.54; Wed, 19 Jul 2023 05:41:18 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@protonmail.com header.s=protonmail3 header.b=MG9ZHnMY; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=protonmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230071AbjGSMRo (ORCPT + 99 others); Wed, 19 Jul 2023 08:17:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42842 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229563AbjGSMRl (ORCPT ); Wed, 19 Jul 2023 08:17:41 -0400 Received: from mail-0201.mail-europe.com (mail-0201.mail-europe.com [51.77.79.158]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EAB6011D for ; Wed, 19 Jul 2023 05:17:39 -0700 (PDT) Date: Wed, 19 Jul 2023 12:17:30 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1689769055; x=1690028255; bh=rEVdWSo+kD3Fdo3WkLbwKFyovtZO71VzepvO8eBT3Tw=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=MG9ZHnMYJyYDWcSS3ZFEB7RPtb4MniCkB/y/nvUHWZmeFFXZe3T5XsCPlBSP3tbgP T4Hlbb4RKMCbnZXgQTEJGyCkEM6Kk9l2MaPHwwU1wqQrWlxEqiwplKdI1AT3eJs/TW TScd4MKltMDHLWAUUT7v+Y3mBGEAFBZfKcqLM1MaEoCAM3KFEksd4X3IrJmqrvDyyU JRc2AX5tegMmSm4uBiVU3SgUjBg1LDOUfddliezsAIr4STJZsWQUUTn2WFQzIFzEMM cU+80Wg0PFZbxsiK9ty9hBDryC9qrfi9ZkgObUbgb37rE7mvUFE7bxH27Sj2fmbuO0 BkEss6k+K+nJA== To: Asahi Lina , Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , =?utf-8?Q?Bj=C3=B6rn_Roy_Baron?= , John Stultz , Thomas Gleixner , Stephen Boyd , Josh Stone , Gaelan Steele From: Heghedus Razvan Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, asahi@lists.linux.dev Subject: Re: [PATCH v2] rust: time: New module for timekeeping functions Message-ID: In-Reply-To: <20230714-rust-time-v2-1-f5aed84218c4@asahilina.net> References: <20230714-rust-time-v2-1-f5aed84218c4@asahilina.net> Feedback-ID: 1233518:user:proton MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri Jul 14, 2023 at 10:55 AM EEST, Asahi Lina wrote: > This module is intended to contain functions related to kernel > timekeeping and time. > > Initially, this implements an abstraction for a time Instant (analogous > to the Rust std::time::Instant) that represents an opaque instant in > time. Unlike the std Instant, this is a generic type that is bound to a > specific clock source, so that only Instants from the same clock source > can be subtracted/compared. > > Then we implement the relevant clocks available to the kernel: > KernelTime (CLOCK_MONOTONIC), BootTime (CLOCK_BOOTTIME), > RealTime (CLOCK_REALTIME), and TaiTime. > > Co-developed-by: Heghedus Razvan > Signed-off-by: Asahi Lina Signed-off-by: Heghedus Razvan > --- > > Based on the feedback to v1, now we have proper type checking for kernel > time. I decided to implement marker traits for monotonic vs. wallclock > time sources, since it's useful to be able to safely implement different > semantics conditional on that, but that left me with a name conflict of > the Monotonic trait with the CLOCK_MONOTONIC / "default ktime" clock > source. I ended up calling it KernelTime since it's the most fundamental > kernel timesource, but suggestions welcome! > > Heghedus: I think I need a signoff on this since this is based on the > playground demo you wrote in the feedback to v1. Can you provide that? I > can fold it into v3 (if there is one, otherwise Miguel can probably just > add it when he applies it). Thanks! > --- > rust/bindings/bindings_helper.h | 2 + > rust/helpers.c | 16 +++++ > rust/kernel/lib.rs | 1 + > rust/kernel/time.rs | 150 ++++++++++++++++++++++++++++++++++= ++++++ > 4 files changed, 169 insertions(+) > > diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_hel= per.h > index 3e601ce2548d..eddfdf887364 100644 > --- a/rust/bindings/bindings_helper.h > +++ b/rust/bindings/bindings_helper.h > @@ -8,9 +8,11 @@ > > #include > #include > +#include > #include > #include > #include > +#include > > /* `bindgen` gets confused at certain things. */ > const gfp_t BINDINGS_GFP_KERNEL =3D GFP_KERNEL; > diff --git a/rust/helpers.c b/rust/helpers.c > index bb594da56137..eff092302e23 100644 > --- a/rust/helpers.c > +++ b/rust/helpers.c > @@ -26,6 +26,7 @@ > #include > #include > #include > +#include > #include > > __noreturn void rust_helper_BUG(void) > @@ -135,6 +136,21 @@ void rust_helper_put_task_struct(struct task_struct = *t) > } > EXPORT_SYMBOL_GPL(rust_helper_put_task_struct); > > +ktime_t rust_helper_ktime_get_real(void) { > +=09return ktime_get_real(); > +} > +EXPORT_SYMBOL_GPL(rust_helper_ktime_get_real); > + > +ktime_t rust_helper_ktime_get_boottime(void) { > +=09return ktime_get_boottime(); > +} > +EXPORT_SYMBOL_GPL(rust_helper_ktime_get_boottime); > + > +ktime_t rust_helper_ktime_get_clocktai(void) { > +=09return ktime_get_clocktai(); > +} > +EXPORT_SYMBOL_GPL(rust_helper_ktime_get_clocktai); > + > /* > * We use `bindgen`'s `--size_t-is-usize` option to bind the C `size_t` = type > * as the Rust `usize` type, so we can use it in contexts where Rust > diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs > index 85b261209977..52c91484c5d8 100644 > --- a/rust/kernel/lib.rs > +++ b/rust/kernel/lib.rs > @@ -42,6 +42,7 @@ > pub mod str; > pub mod sync; > pub mod task; > +pub mod time; > pub mod types; > > #[doc(hidden)] > diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs > new file mode 100644 > index 000000000000..f3bfeed20145 > --- /dev/null > +++ b/rust/kernel/time.rs > @@ -0,0 +1,150 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +//! Timekeeping functions. > +//! > +//! C header: [`include/linux/ktime.h`](../../../../include/linux/ktime.= h) > +//! C header: [`include/linux/timekeeping.h`](../../../../include/linux/= timekeeping.h) > + > +use crate::{bindings, pr_err}; > +use core::marker::PhantomData; > +use core::time::Duration; > + > +/// Represents a clock, that is, a unique time source. > +pub trait Clock: Sized {} > + > +/// A time source that can be queried for the current time. > +pub trait Now: Clock { > + /// Returns the current time for this clock. > + fn now() -> Instant; > +} > + > +/// Marker trait for clock sources that are guaranteed to be monotonic. > +pub trait Monotonic {} > + > +/// Marker trait for clock sources that represent a calendar (wall clock= ) > +/// relative to the UNIX epoch. > +pub trait WallTime {} > + > +/// An instant in time associated with a given clock source. > +#[derive(Debug)] > +pub struct Instant { > + nanoseconds: i64, > + _type: PhantomData, > +} > + > +impl Clone for Instant { > + fn clone(&self) -> Self { > + *self > + } > +} > + > +impl Copy for Instant {} > + > +impl Instant { > + fn new(nanoseconds: i64) -> Self { > + Instant { > + nanoseconds, > + _type: PhantomData, > + } > + } > + > + /// Returns the time elapsed since an earlier Instant, or > + /// None if the argument is a later Instant. > + pub fn since(&self, earlier: Instant) -> Option { > + if earlier.nanoseconds > self.nanoseconds { > + None > + } else { > + // Casting to u64 and subtracting is guaranteed to give the = right > + // result for all inputs, as long as the condition we checke= d above > + // holds. > + Some(Duration::from_nanos( > + self.nanoseconds as u64 - earlier.nanoseconds as u64, > + )) > + } > + } > +} > + > +impl Instant { > + /// Returns the time elapsed since this Instant. > + /// > + /// This is guaranteed to return a positive result, since > + /// it is only implemented for monotonic clocks. > + pub fn elapsed(&self) -> Duration { > + T::now().since(*self).unwrap_or_else(|| { > + pr_err!( > + "Monotonic clock {} went backwards!", > + core::any::type_name::() > + ); > + Duration::ZERO > + }) > + } > +} > + > +/// Contains the various clock source types available to the kernel. > +pub mod clock { > + use super::*; > + > + /// A clock representing the default kernel time source. > + /// > + /// This is `CLOCK_MONOTONIC` (though it is not the only > + /// monotonic clock) and also the default clock used by > + /// `ktime_get()` in the C API. > + /// > + /// This is like `BootTime`, but does not include time > + /// spent sleeping. > + > + pub struct KernelTime; > + > + impl Clock for KernelTime {} > + impl Monotonic for KernelTime {} > + impl Now for KernelTime { > + fn now() -> Instant { > + Instant::::new(unsafe { bindings::ktime_get() }) > + } > + } > + > + /// A clock representing the time elapsed since boot. > + /// > + /// This is `CLOCK_MONOTONIC` (though it is not the only > + /// monotonic clock) and also the default clock used by > + /// `ktime_get()` in the C API. > + /// > + /// This is like `KernelTime`, but does include time > + /// spent sleeping. > + pub struct BootTime; > + > + impl Clock for BootTime {} > + impl Monotonic for BootTime {} > + impl Now for BootTime { > + fn now() -> Instant { > + Instant::::new(unsafe { bindings::ktime_get_boottime()= }) > + } > + } > + > + /// A clock representing TAI time. > + /// > + /// This clock is not monotonic and can be changed from userspace. > + /// However, it is not affected by leap seconds. > + pub struct TaiTime; > + > + impl Clock for TaiTime {} > + impl WallTime for TaiTime {} > + impl Now for TaiTime { > + fn now() -> Instant { > + Instant::::new(unsafe { bindings::ktime_get_clocktai()= }) > + } > + } > + > + /// A clock representing wall clock time. > + /// > + /// This clock is not monotonic and can be changed from userspace. > + pub struct RealTime; > + > + impl Clock for RealTime {} > + impl WallTime for RealTime {} > + impl Now for RealTime { > + fn now() -> Instant { > + Instant::::new(unsafe { bindings::ktime_get_real() }) > + } > + } > +} > > --- > base-commit: 06c2afb862f9da8dc5efa4b6076a0e48c3fbaaa5 > change-id: 20230714-rust-time-10dd9ed25333 > > Thank you, > ~~ Lina