Commit 02a03a9f authored by Alex Bligh's avatar Alex Bligh Committed by Stefan Hajnoczi
Browse files

aio / timers: add qemu-timer.c utility functions



Add utility functions to qemu-timer.c for nanosecond timing.

Add qemu_clock_deadline_ns to calculate deadlines to
nanosecond accuracy.

Add utility function qemu_soonest_timeout to calculate soonest deadline.

Add qemu_timeout_ns_to_ms to convert a timeout in nanoseconds back to
milliseconds for when ppoll is not used.

Signed-off-by: default avatarAlex Bligh <alex@alex.org.uk>
Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
parent 58ac56b9
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
@@ -40,6 +40,29 @@ int64_t qemu_get_clock_ns(QEMUClock *clock);
int64_t qemu_clock_has_timers(QEMUClock *clock);
int64_t qemu_clock_expired(QEMUClock *clock);
int64_t qemu_clock_deadline(QEMUClock *clock);

/**
 * qemu_clock_deadline_ns:
 * @clock: the clock to operate on
 *
 * Calculate the timeout of the earliest expiring timer
 * in nanoseconds, or -1 if no timer is set to expire.
 *
 * Returns: time until expiry in nanoseconds or -1
 */
int64_t qemu_clock_deadline_ns(QEMUClock *clock);

/**
 * qemu_timeout_ns_to_ms:
 * @ns: nanosecond timeout value
 *
 * Convert a nanosecond timeout value (or -1) to
 * a millisecond value (or -1), always rounding up.
 *
 * Returns: millisecond timeout value
 */
int qemu_timeout_ns_to_ms(int64_t ns);

void qemu_clock_enable(QEMUClock *clock, bool enabled);
void qemu_clock_warp(QEMUClock *clock);

@@ -67,6 +90,25 @@ int64_t cpu_get_ticks(void);
void cpu_enable_ticks(void);
void cpu_disable_ticks(void);

/**
 * qemu_soonest_timeout:
 * @timeout1: first timeout in nanoseconds (or -1 for infinite)
 * @timeout2: second timeout in nanoseconds (or -1 for infinite)
 *
 * Calculates the soonest of two timeout values. -1 means infinite, which
 * is later than any other value.
 *
 * Returns: soonest timeout value in nanoseconds (or -1 for infinite)
 */
static inline int64_t qemu_soonest_timeout(int64_t timeout1, int64_t timeout2)
{
    /* we can abuse the fact that -1 (which means infinite) is a maximal
     * value when cast to unsigned. As this is disgusting, it's kept in
     * one inline function.
     */
    return ((uint64_t) timeout1 < (uint64_t) timeout2) ? timeout1 : timeout2;
}

static inline QEMUTimer *qemu_new_timer_ns(QEMUClock *clock, QEMUTimerCB *cb,
                                           void *opaque)
{
+50 −0
Original line number Diff line number Diff line
@@ -273,6 +273,56 @@ int64_t qemu_clock_deadline(QEMUClock *clock)
    return delta;
}

/*
 * As above, but return -1 for no deadline, and do not cap to 2^32
 * as we know the result is always positive.
 */

int64_t qemu_clock_deadline_ns(QEMUClock *clock)
{
    int64_t delta;

    if (!clock->enabled || !clock->active_timers) {
        return -1;
    }

    delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock);

    if (delta <= 0) {
        return 0;
    }

    return delta;
}

/* Transition function to convert a nanosecond timeout to ms
 * This is used where a system does not support ppoll
 */
int qemu_timeout_ns_to_ms(int64_t ns)
{
    int64_t ms;
    if (ns < 0) {
        return -1;
    }

    if (!ns) {
        return 0;
    }

    /* Always round up, because it's better to wait too long than to wait too
     * little and effectively busy-wait
     */
    ms = (ns + SCALE_MS - 1) / SCALE_MS;

    /* To avoid overflow problems, limit this to 2^31, i.e. approx 25 days */
    if (ms > (int64_t) INT32_MAX) {
        ms = INT32_MAX;
    }

    return (int) ms;
}


QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
                          QEMUTimerCB *cb, void *opaque)
{