mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:04:41 +01:00
rust: time: Implement basic arithmetic operations for Delta
While rvkms is only going to be using a few of these, since Deltas are basically the same as i64 it's easy enough to just implement all of the basic arithmetic operations for Delta types. Keep in mind there's one quirk here - the kernel has no support for i64 % i64 on 32 bit platforms, the closest we have is i64 % i32 through div_s64_rem(). So, instead of implementing ops::Rem or ops::RemAssign we simply provide Delta::rem_nanos(). Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com> Reviewed-by: FUJITA Tomonori <fujita.tomonori@gmail.com> Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org> Link: https://lore.kernel.org/r/20250820203704.731588-3-lyude@redhat.com Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
This commit is contained in:
parent
22b65a4057
commit
4521438fb0
1 changed files with 98 additions and 0 deletions
|
|
@ -287,6 +287,78 @@ pub struct Delta {
|
|||
nanos: i64,
|
||||
}
|
||||
|
||||
impl ops::Add for Delta {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
Self {
|
||||
nanos: self.nanos + rhs.nanos,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::AddAssign for Delta {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
self.nanos += rhs.nanos;
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Sub for Delta {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
Self {
|
||||
nanos: self.nanos - rhs.nanos,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::SubAssign for Delta {
|
||||
#[inline]
|
||||
fn sub_assign(&mut self, rhs: Self) {
|
||||
self.nanos -= rhs.nanos;
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Mul<i64> for Delta {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, rhs: i64) -> Self::Output {
|
||||
Self {
|
||||
nanos: self.nanos * rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::MulAssign<i64> for Delta {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, rhs: i64) {
|
||||
self.nanos *= rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Div for Delta {
|
||||
type Output = i64;
|
||||
|
||||
#[inline]
|
||||
fn div(self, rhs: Self) -> Self::Output {
|
||||
#[cfg(CONFIG_64BIT)]
|
||||
{
|
||||
self.nanos / rhs.nanos
|
||||
}
|
||||
|
||||
#[cfg(not(CONFIG_64BIT))]
|
||||
{
|
||||
// SAFETY: This function is always safe to call regardless of the input values
|
||||
unsafe { bindings::div64_s64(self.nanos, rhs.nanos) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Delta {
|
||||
/// A span of time equal to zero.
|
||||
pub const ZERO: Self = Self { nanos: 0 };
|
||||
|
|
@ -375,4 +447,30 @@ impl Delta {
|
|||
bindings::ktime_to_ms(self.as_nanos())
|
||||
}
|
||||
}
|
||||
|
||||
/// Return `self % dividend` where `dividend` is in nanoseconds.
|
||||
///
|
||||
/// The kernel doesn't have any emulation for `s64 % s64` on 32 bit platforms, so this is
|
||||
/// limited to 32 bit dividends.
|
||||
#[inline]
|
||||
pub fn rem_nanos(self, dividend: i32) -> Self {
|
||||
#[cfg(CONFIG_64BIT)]
|
||||
{
|
||||
Self {
|
||||
nanos: self.as_nanos() % i64::from(dividend),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(CONFIG_64BIT))]
|
||||
{
|
||||
let mut rem = 0;
|
||||
|
||||
// SAFETY: `rem` is in the stack, so we can always provide a valid pointer to it.
|
||||
unsafe { bindings::div_s64_rem(self.as_nanos(), dividend, &mut rem) };
|
||||
|
||||
Self {
|
||||
nanos: i64::from(rem),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue