[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [RFC 3/4] clock: Add clock_ns_to_ticks() function
From: |
Luc Michel |
Subject: |
Re: [RFC 3/4] clock: Add clock_ns_to_ticks() function |
Date: |
Wed, 3 Feb 2021 21:51:14 +0100 |
On 12:30 Mon 01 Feb , Peter Maydell wrote:
> Add a clock_ns_to_ticks() function which does the opposite of
> clock_ticks_to_ns(): given a duration in nanoseconds, it returns the
> number of clock ticks that would happen in that time. This is useful
> for devices that have a free running counter register whose value can
> be calculated when it is read.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
> I have made the overflow behaviour here be "wrap", with justification
> as per the comment; but I'm not 100% set on this.
I thought about this, but I can't see a scenario where the upper 64 bits
would be needed. So I guess wrapping is fine.
> ---
> docs/devel/clocks.rst | 12 ++++++++++++
> include/hw/clock.h | 41 +++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 53 insertions(+)
>
> diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
> index dea63742fb0..84fb45bbe5f 100644
> --- a/docs/devel/clocks.rst
> +++ b/docs/devel/clocks.rst
> @@ -355,6 +355,18 @@ rather than simply passing it to a QEMUTimer function
> like
> ``timer_mod_ns()`` then you should be careful to avoid overflow
> in those calculations, of course.)
>
> +Obtaining tick counts
> +---------------------
> +
> +For calculations where you need to know the number of ticks in
> +a given duration, use ``clock_ns_to_ticks()``. This function handles
> +possible non-whole-number-of-nanoseconds periods and avoids
> +potential rounding errors. It will return '0' if the clock is stopped
> +(i.e. it has period zero). If the inputs imply a tick count that
> +overflows a 64-bit value (a very long duration for a clock with a
> +very short period) the output value is truncated, so effectively
> +the 64-bit output wraps around.
> +
> Changing a clock period
> -----------------------
>
> diff --git a/include/hw/clock.h b/include/hw/clock.h
> index 7d0eb286faa..e3545eda439 100644
> --- a/include/hw/clock.h
> +++ b/include/hw/clock.h
> @@ -277,6 +277,47 @@ static inline uint64_t clock_ticks_to_ns(const Clock
> *clk, uint64_t ticks)
> return ns_low >> 32 | ns_high << 32;
> }
>
> +/**
> + * clock_ns_to_ticks:
> + * @clk: the clock to query
> + * @ns: duration in nanoseconds
> + *
> + * Returns the number of ticks this clock would make in the given
> + * number of nanoseconds. Because a clock can have a period which
> + * is not a whole number of nanoseconds, it is important to use this
> + * function rather than attempting to obtain a "period in nanoseconds"
> + * value and then dividing the duration by that value.
> + *
> + * If the clock is stopped (ie it has period zero), returns 0.
> + *
> + * For some inputs the result could overflow a 64-bit value (because
> + * the clock's period is short and the duration is long). In these
> + * cases we truncate the result to a 64-bit value. This is on the
> + * assumption that generally the result is going to be used to report
> + * a 32-bit or 64-bit guest register value, so wrapping either cannot
> + * happen or is the desired behaviour.
> + */
> +static inline uint64_t clock_ns_to_ticks(const Clock *clk, uint64_t ns)
> +{
> + /*
> + * ticks = duration_in_ns / period_in_ns
> + * = ns / (period / 2^32)
> + * = (ns * 2^32) / period
> + * The hi, lo inputs to divu128() are (ns << 32) as a 128 bit value.
> + */
> + uint64_t lo = ns << 32;
> + uint64_t hi = ns >> 32;
> + if (clk->period == 0) {
> + return 0;
> + }
> + /*
> + * Ignore divu128() return value as we've caught div-by-zero and don't
> + * need different behaviour for overflow.
> + */
> + divu128(&lo, &hi, clk->period);
> + return lo;
> +}
> +
> /**
> * clock_is_enabled:
> * @clk: a clock
> --
> 2.20.1
>
--
- [RFC 0/4] New APIs for the Clock framework, Peter Maydell, 2021/02/01
- [RFC 1/4] clock: Add ClockEvent parameter to callbacks, Peter Maydell, 2021/02/01
- [RFC 3/4] clock: Add clock_ns_to_ticks() function, Peter Maydell, 2021/02/01
- Re: [RFC 3/4] clock: Add clock_ns_to_ticks() function,
Luc Michel <=
- [RFC 2/4] clock: Add ClockPreUpdate callback event type, Peter Maydell, 2021/02/01
- [RFC 4/4] hw/timer/npcm7xx_timer: Use new clock_ns_to_ticks(), Peter Maydell, 2021/02/01
- Re: [RFC 0/4] New APIs for the Clock framework, Luc Michel, 2021/02/03