Commit 754d6a54 authored by Alex Bligh's avatar Alex Bligh Committed by Stefan Hajnoczi
Browse files

aio / timers: Add QEMUTimerListGroup and helper functions



Add QEMUTimerListGroup and helper functions, to represent
a QEMUTimerList associated with each clock. Add a default
QEMUTimerListGroup representing the default timer lists
which are not associated with any other object (e.g.
an AioContext as added by future patches).

Signed-off-by: default avatarAlex Bligh <alex@alex.org.uk>
Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
parent 6a1751b7
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -53,6 +53,11 @@ typedef enum {

typedef struct QEMUClock QEMUClock;
typedef struct QEMUTimerList QEMUTimerList;

struct QEMUTimerListGroup {
    QEMUTimerList *tl[QEMU_CLOCK_MAX];
};

typedef void QEMUTimerCB(void *opaque);

struct QEMUTimer {
@@ -64,6 +69,7 @@ struct QEMUTimer {
    int scale;
};

extern QEMUTimerListGroup main_loop_tlg;
extern QEMUClock *qemu_clocks[QEMU_CLOCK_MAX];

/**
@@ -217,6 +223,49 @@ QEMUClock *timerlist_get_clock(QEMUTimerList *timer_list);
 */
bool timerlist_run_timers(QEMUTimerList *timer_list);

/**
 * timerlistgroup_init:
 * @tlg: the timer list group
 *
 * Initialise a timer list group. This must already be
 * allocated in memory and zeroed.
 */
void timerlistgroup_init(QEMUTimerListGroup *tlg);

/**
 * timerlistgroup_deinit:
 * @tlg: the timer list group
 *
 * Deinitialise a timer list group. This must already be
 * initialised. Note the memory is not freed.
 */
void timerlistgroup_deinit(QEMUTimerListGroup *tlg);

/**
 * timerlistgroup_run_timers:
 * @tlg: the timer list group
 *
 * Run the timers associated with a timer list group.
 * This will run timers on multiple clocks.
 *
 * Returns: true if any timer callback ran
 */
bool timerlistgroup_run_timers(QEMUTimerListGroup *tlg);

/**
 * timerlistgroup_deadline_ns
 * @tlg: the timer list group
 *
 * Determine the deadline of the soonest timer to
 * expire associated with any timer list linked to
 * the timer list group. Only clocks suitable for
 * deadline calculation are included.
 *
 * Returns: the deadline in nanoseconds or -1 if no
 * timers are to expire.
 */
int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg);

/**
 * qemu_timeout_ns_to_ms:
 * @ns: nanosecond timeout value
+1 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
/* A load of opaque types so that device init declarations don't have to
   pull in all the real definitions.  */
typedef struct QEMUTimer QEMUTimer;
typedef struct QEMUTimerListGroup QEMUTimerListGroup;
typedef struct QEMUFile QEMUFile;
typedef struct QEMUBH QEMUBH;

+42 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ struct QEMUClock {
    bool enabled;
};

QEMUTimerListGroup main_loop_tlg;
QEMUClock *qemu_clocks[QEMU_CLOCK_MAX];

/* A QEMUTimerList is a list of timers attached to a clock. More
@@ -564,6 +565,46 @@ bool qemu_run_timers(QEMUClock *clock)
    return timerlist_run_timers(clock->main_loop_timerlist);
}

void timerlistgroup_init(QEMUTimerListGroup *tlg)
{
    QEMUClockType type;
    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
        tlg->tl[type] = timerlist_new(type);
    }
}

void timerlistgroup_deinit(QEMUTimerListGroup *tlg)
{
    QEMUClockType type;
    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
        timerlist_free(tlg->tl[type]);
    }
}

bool timerlistgroup_run_timers(QEMUTimerListGroup *tlg)
{
    QEMUClockType type;
    bool progress = false;
    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
        progress |= timerlist_run_timers(tlg->tl[type]);
    }
    return progress;
}

int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg)
{
    int64_t deadline = -1;
    QEMUClockType type;
    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
        if (qemu_clock_use_for_deadline(tlg->tl[type]->clock)) {
            deadline = qemu_soonest_timeout(deadline,
                                            timerlist_deadline_ns(
                                                tlg->tl[type]));
        }
    }
    return deadline;
}

int64_t qemu_get_clock_ns(QEMUClock *clock)
{
    int64_t now, last;
@@ -605,6 +646,7 @@ void init_clocks(void)
    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
        if (!qemu_clocks[type]) {
            qemu_clocks[type] = qemu_clock_new(type);
            main_loop_tlg.tl[type] = qemu_clocks[type]->main_loop_timerlist;
        }
    }