16a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner/*
26a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * QEMU System Emulator
36a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner *
46a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * Copyright (c) 2003-2008 Fabrice Bellard
56a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner *
66a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * Permission is hereby granted, free of charge, to any person obtaining a copy
76a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * of this software and associated documentation files (the "Software"), to deal
86a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * in the Software without restriction, including without limitation the rights
96a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
106a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * copies of the Software, and to permit persons to whom the Software is
116a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * furnished to do so, subject to the following conditions:
126a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner *
136a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * The above copyright notice and this permission notice shall be included in
146a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * all copies or substantial portions of the Software.
156a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner *
166a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
176a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
186a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
196a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
206a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
216a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
226a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner * THE SOFTWARE.
236a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner */
246a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
2534c48ff1e3ad5cd2084ca40188754d45f423750bDavid 'Digit' Turner#include "sysemu/sysemu.h"
266af6765e2f3bc930d0dce21d752bea570a1b1362David 'Digit' Turner#include "monitor/monitor.h"
271c31e3e43ce4cca85a707dfff631e5e102fdecedDavid 'Digit' Turner#include "ui/console.h"
286a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
296a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner#include "hw/hw.h"
306a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
31dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#include "qemu/thread.h"
32dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#include "qemu/timer.h"
33dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#ifdef CONFIG_POSIX
34dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#include <pthread.h>
356a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner#endif
366a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
37dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#ifdef CONFIG_PPOLL
38dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#include <poll.h>
39dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#endif
40dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
41dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
42dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#include <sys/prctl.h>
43dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#endif
446a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
456a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner/***********************************************************/
466a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner/* timers */
476a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
48dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnertypedef struct QEMUClock {
49dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    /* We rely on BQL to protect the timerlists */
50dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QLIST_HEAD(, QEMUTimerList) timerlists;
51317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner
52dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    NotifierList reset_notifiers;
53dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    int64_t last;
546a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
55dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUClockType type;
56dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    bool enabled;
57dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner} QEMUClock;
58dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
59dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' TurnerQEMUTimerListGroup main_loop_tlg;
60dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' TurnerQEMUClock qemu_clocks[QEMU_CLOCK_MAX];
61f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
62dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner/* A QEMUTimerList is a list of timers attached to a clock. More
63dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * than one QEMUTimerList can be attached to each clock, for instance
64dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * used by different AioContexts / threads. Each clock also has
65dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * a list of the QEMUTimerLists associated with it, in order that
66dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * reenabling the clock can call all the notifiers.
67dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner */
68dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
69dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerstruct QEMUTimerList {
706a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    QEMUClock *clock;
71dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QemuMutex active_timers_lock;
72dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUTimer *active_timers;
73dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QLIST_ENTRY(QEMUTimerList) list;
74dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUTimerListNotifyCB *notify_cb;
75dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    void *notify_opaque;
76dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
77dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    /* lightweight method to mark the end of timerlist's running */
78dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QemuEvent timers_done_ev;
796a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner};
806a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
81dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner/**
82dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * qemu_clock_ptr:
83dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * @type: type of clock
84dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner *
85dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * Translate a clock type into a pointer to QEMUClock object.
86dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner *
87dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * Returns: a pointer to the QEMUClock object
88dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner */
89dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerstatic inline QEMUClock *qemu_clock_ptr(QEMUClockType type)
90dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
91dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return &qemu_clocks[type];
92dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
93dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
94dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerstatic bool timer_expired_ns(QEMUTimer *timer_head, int64_t current_time)
95317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner{
96317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner    return timer_head && (timer_head->expire_time <= current_time);
97317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner}
98317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner
99dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' TurnerQEMUTimerList *timerlist_new(QEMUClockType type,
100dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner                             QEMUTimerListNotifyCB *cb,
101dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner                             void *opaque)
102dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
103dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUTimerList *timer_list;
104dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUClock *clock = qemu_clock_ptr(type);
105dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
106dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    timer_list = g_malloc0(sizeof(QEMUTimerList));
107dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    qemu_event_init(&timer_list->timers_done_ev, false);
108dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    timer_list->clock = clock;
109dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    timer_list->notify_cb = cb;
110dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    timer_list->notify_opaque = opaque;
111dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    qemu_mutex_init(&timer_list->active_timers_lock);
112dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QLIST_INSERT_HEAD(&clock->timerlists, timer_list, list);
113dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return timer_list;
114dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
1156a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
116dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid timerlist_free(QEMUTimerList *timer_list)
117dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
118dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    assert(!timerlist_has_timers(timer_list));
119dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (timer_list->clock) {
120dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        QLIST_REMOVE(timer_list, list);
121dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
122dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    qemu_mutex_destroy(&timer_list->active_timers_lock);
123dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    g_free(timer_list);
124dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
1256a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
126dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerstatic void qemu_clock_init(QEMUClockType type)
1276a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
128dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUClock *clock = qemu_clock_ptr(type);
129dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
1306a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    clock->type = type;
131dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    clock->enabled = true;
132dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    clock->last = INT64_MIN;
133dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QLIST_INIT(&clock->timerlists);
134dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    notifier_list_init(&clock->reset_notifiers);
135dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    main_loop_tlg.tl[type] = timerlist_new(type, NULL, NULL);
136dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
137dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
138dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerbool qemu_clock_use_for_deadline(QEMUClockType type)
139dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
140dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return !(use_icount && (type == QEMU_CLOCK_VIRTUAL));
1416a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
1426a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
143dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid qemu_clock_notify(QEMUClockType type)
1446a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
145dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUTimerList *timer_list;
146dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUClock *clock = qemu_clock_ptr(type);
147dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QLIST_FOREACH(timer_list, &clock->timerlists, list) {
148dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timerlist_notify(timer_list);
149dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
150dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
151dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
152dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner/* Disabling the clock will wait for related timerlists to stop
153dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * executing qemu_run_timers.  Thus, this functions should not
154dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * be used from the callback of a timer that is based on @clock.
155dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * Doing so would cause a deadlock.
156dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner *
157dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * Caller should hold BQL.
158dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner */
159dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid qemu_clock_enable(QEMUClockType type, bool enabled)
160dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
161dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUClock *clock = qemu_clock_ptr(type);
162dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUTimerList *tl;
163dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    bool old = clock->enabled;
1646a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    clock->enabled = enabled;
165dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (enabled && !old) {
166dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        qemu_clock_notify(type);
167dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    } else if (!enabled && old) {
168dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        QLIST_FOREACH(tl, &clock->timerlists, list) {
169dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner            qemu_event_wait(&tl->timers_done_ev);
170dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        }
171dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
172dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
173dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
174dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerbool timerlist_has_timers(QEMUTimerList *timer_list)
175dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
176dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return !!timer_list->active_timers;
177dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
178dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
179dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerbool qemu_clock_has_timers(QEMUClockType type)
180dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
181dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return timerlist_has_timers(
182dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        main_loop_tlg.tl[type]);
183dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
184dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
185dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerbool timerlist_expired(QEMUTimerList *timer_list)
186dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
187dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    int64_t expire_time;
188dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
189dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    qemu_mutex_lock(&timer_list->active_timers_lock);
190dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (!timer_list->active_timers) {
191dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        qemu_mutex_unlock(&timer_list->active_timers_lock);
192dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        return false;
193dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
194dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    expire_time = timer_list->active_timers->expire_time;
195dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    qemu_mutex_unlock(&timer_list->active_timers_lock);
196dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
197dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return expire_time < qemu_clock_get_ns(timer_list->clock->type);
1986a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
1996a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
200dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerbool qemu_clock_expired(QEMUClockType type)
201dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
202dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return timerlist_expired(
203dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        main_loop_tlg.tl[type]);
204317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner}
205317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner
206dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner/*
207dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * As above, but return -1 for no deadline, and do not cap to 2^32
208dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * as we know the result is always positive.
209dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner */
210dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
211dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerint64_t timerlist_deadline_ns(QEMUTimerList *timer_list)
212dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
213dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    int64_t delta;
214dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    int64_t expire_time;
215dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
216dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (!timer_list->clock->enabled) {
217dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        return -1;
218dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
219317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner
220dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    /* The active timers list may be modified before the caller uses our return
221dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner     * value but ->notify_cb() is called when the deadline changes.  Therefore
222dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner     * the caller should notice the change and there is no race condition.
223dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner     */
224dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    qemu_mutex_lock(&timer_list->active_timers_lock);
225dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (!timer_list->active_timers) {
226dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        qemu_mutex_unlock(&timer_list->active_timers_lock);
227dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        return -1;
228317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner    }
229dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    expire_time = timer_list->active_timers->expire_time;
230dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    qemu_mutex_unlock(&timer_list->active_timers_lock);
231dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
232dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    delta = expire_time - qemu_clock_get_ns(timer_list->clock->type);
233317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner
234dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (delta <= 0) {
235dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        return 0;
236dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
237317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner
238f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return delta;
239317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner}
240317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner
241dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner/* Calculate the soonest deadline across all timerlists attached
242dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * to the clock. This is used for the icount timeout so we
243dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * ignore whether or not the clock should be used in deadline
244dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * calculations.
245dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner */
246dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerint64_t qemu_clock_deadline_ns_all(QEMUClockType type)
2476a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
248dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    int64_t deadline = -1;
249dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUTimerList *timer_list;
250dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUClock *clock = qemu_clock_ptr(type);
251dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QLIST_FOREACH(timer_list, &clock->timerlists, list) {
252dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        deadline = qemu_soonest_timeout(deadline,
253dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner                                        timerlist_deadline_ns(timer_list));
254dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
255dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return deadline;
256dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
2576a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
258dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' TurnerQEMUClockType timerlist_get_clock(QEMUTimerList *timer_list)
259dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
260dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return timer_list->clock->type;
261dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
262dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
263dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' TurnerQEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClockType type)
264dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
265dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return main_loop_tlg.tl[type];
266dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
267dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
268dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid timerlist_notify(QEMUTimerList *timer_list)
269dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
270dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (timer_list->notify_cb) {
271dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timer_list->notify_cb(timer_list->notify_opaque);
272dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    } else {
273dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        qemu_notify_event();
274dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
275dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
276dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
277dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner/* Transition function to convert a nanosecond timeout to ms
278dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * This is used where a system does not support ppoll
279dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner */
280dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerint qemu_timeout_ns_to_ms(int64_t ns)
281dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
282dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    int64_t ms;
283dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (ns < 0) {
284dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        return -1;
285dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
286dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
287dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (!ns) {
288dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        return 0;
289dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
290dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
291dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    /* Always round up, because it's better to wait too long than to wait too
292dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner     * little and effectively busy-wait
293dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner     */
294dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    ms = (ns + SCALE_MS - 1) / SCALE_MS;
295dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
296dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    /* To avoid overflow problems, limit this to 2^31, i.e. approx 25 days */
297dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (ms > (int64_t) INT32_MAX) {
298dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        ms = INT32_MAX;
299dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
300dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
301dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return (int) ms;
302dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
303dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
304dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#ifndef CONFIG_ANDROID  // TODO(digit): Implement g_poll()
305dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner/* qemu implementation of g_poll which uses a nanosecond timeout but is
306dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner * otherwise identical to g_poll
307dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner */
308dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerint qemu_poll_ns(GPollFD *fds, guint nfds, int64_t timeout)
309dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
310dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#ifdef CONFIG_PPOLL
311dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (timeout < 0) {
312dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        return ppoll((struct pollfd *)fds, nfds, NULL, NULL);
313dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    } else {
314dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        struct timespec ts;
315dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        ts.tv_sec = timeout / 1000000000LL;
316dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        ts.tv_nsec = timeout % 1000000000LL;
317dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        return ppoll((struct pollfd *)fds, nfds, &ts, NULL);
318dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
319dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#else
320dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return g_poll(fds, nfds, qemu_timeout_ns_to_ms(timeout));
321dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#endif
322dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
323dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#endif  // !CONFIG_ANDROID
324dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
325dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid timer_init(QEMUTimer *ts,
326dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner                QEMUTimerList *timer_list, int scale,
327dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner                QEMUTimerCB *cb, void *opaque)
328dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
329dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    ts->timer_list = timer_list;
3306a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    ts->cb = cb;
3316a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    ts->opaque = opaque;
332317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner    ts->scale = scale;
333dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    ts->expire_time = -1;
3346a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
3356a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
336dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid timer_free(QEMUTimer *ts)
3376a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
338aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(ts);
3396a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
3406a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
341dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerstatic void timer_del_locked(QEMUTimerList *timer_list, QEMUTimer *ts)
3426a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
3436a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    QEMUTimer **pt, *t;
3446a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
345dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    ts->expire_time = -1;
346dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    pt = &timer_list->active_timers;
3476a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    for(;;) {
3486a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        t = *pt;
3496a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        if (!t)
3506a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            break;
3516a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        if (t == ts) {
3526a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            *pt = t->next;
3536a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            break;
3546a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        }
3556a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        pt = &t->next;
3566a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
3576a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
3586a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
359dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerstatic bool timer_mod_ns_locked(QEMUTimerList *timer_list,
360dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner                                QEMUTimer *ts, int64_t expire_time)
3616a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
3626a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    QEMUTimer **pt, *t;
3636a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
3646a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    /* add the timer in the sorted list */
365dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    pt = &timer_list->active_timers;
366dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    for (;;) {
3676a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        t = *pt;
368dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        if (!timer_expired_ns(t, expire_time)) {
3696a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            break;
370317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner        }
3716a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        pt = &t->next;
3726a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
373dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    ts->expire_time = MAX(expire_time, 0);
3746a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    ts->next = *pt;
3756a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    *pt = ts;
3766a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
377dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return pt == &timer_list->active_timers;
378dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
379dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
380dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerstatic void timerlist_rearm(QEMUTimerList *timer_list)
381dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
382dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    /* Interrupt execution to force deadline recalculation.  */
383dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    qemu_clock_warp(timer_list->clock->type);
384dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    timerlist_notify(timer_list);
385dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
386dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
387dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner/* stop a timer, but do not dealloc it */
388dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid timer_del(QEMUTimer *ts)
389dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
390dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUTimerList *timer_list = ts->timer_list;
391dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
392dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    qemu_mutex_lock(&timer_list->active_timers_lock);
393dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    timer_del_locked(timer_list, ts);
394dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    qemu_mutex_unlock(&timer_list->active_timers_lock);
395317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner}
396317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner
397317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner/* modify the current timer so that it will be fired when current_time
398317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner   >= expire_time. The corresponding callback will be called. */
399dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid timer_mod_ns(QEMUTimer *ts, int64_t expire_time)
400317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner{
401dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUTimerList *timer_list = ts->timer_list;
402dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    bool rearm;
403dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
404dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    qemu_mutex_lock(&timer_list->active_timers_lock);
405dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    timer_del_locked(timer_list, ts);
406dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    rearm = timer_mod_ns_locked(timer_list, ts, expire_time);
407dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    qemu_mutex_unlock(&timer_list->active_timers_lock);
408dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
409dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (rearm) {
410dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timerlist_rearm(timer_list);
411dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
4126a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
4136a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
414dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner/* modify the current timer so that it will be fired when current_time
415dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner   >= expire_time or the current deadline, whichever comes earlier.
416dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner   The corresponding callback will be called. */
417dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid timer_mod_anticipate_ns(QEMUTimer *ts, int64_t expire_time)
4186a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
419dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUTimerList *timer_list = ts->timer_list;
420dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    bool rearm;
421dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
422dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    qemu_mutex_lock(&timer_list->active_timers_lock);
423dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (ts->expire_time == -1 || ts->expire_time > expire_time) {
424dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        if (ts->expire_time != -1) {
425dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner            timer_del_locked(timer_list, ts);
426dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        }
427dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        rearm = timer_mod_ns_locked(timer_list, ts, expire_time);
428dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    } else {
429dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        rearm = false;
430dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
431dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    qemu_mutex_unlock(&timer_list->active_timers_lock);
432dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
433dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (rearm) {
434dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timerlist_rearm(timer_list);
4356a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
4366a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
4376a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
438dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid timer_mod(QEMUTimer *ts, int64_t expire_time)
4396a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
440dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    timer_mod_ns(ts, expire_time * ts->scale);
4416a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
4426a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
443dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid timer_mod_anticipate(QEMUTimer *ts, int64_t expire_time)
4446a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
445dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    timer_mod_anticipate_ns(ts, expire_time * ts->scale);
446dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
447dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
448dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerbool timer_pending(QEMUTimer *ts)
449dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
450dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return ts->expire_time >= 0;
451dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
452dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
453dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerbool timer_expired(QEMUTimer *timer_head, int64_t current_time)
454dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
455dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return timer_expired_ns(timer_head, current_time * timer_head->scale);
456dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
457dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
458dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerbool timerlist_run_timers(QEMUTimerList *timer_list)
459dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
460dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUTimer *ts;
4616a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    int64_t current_time;
462dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    bool progress = false;
463dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUTimerCB *cb;
464dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    void *opaque;
4656b512811e01d7c81348bfa9c29c21f788ccc0a8eDavid 'Digit' Turner
466dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    qemu_event_reset(&timer_list->timers_done_ev);
467dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (!timer_list->clock->enabled) {
468dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        goto out;
469dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
4706a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
471dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    current_time = qemu_clock_get_ns(timer_list->clock->type);
4726a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    for(;;) {
473dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        qemu_mutex_lock(&timer_list->active_timers_lock);
474dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        ts = timer_list->active_timers;
475dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        if (!timer_expired_ns(ts, current_time)) {
476dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner            qemu_mutex_unlock(&timer_list->active_timers_lock);
4776a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            break;
478317c9d54284844615b33a25834a63248bf1bfa73David 'Digit' Turner        }
479dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
4806a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        /* remove timer from the list before calling the callback */
481dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timer_list->active_timers = ts->next;
4826a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        ts->next = NULL;
483dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        ts->expire_time = -1;
484dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        cb = ts->cb;
485dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        opaque = ts->opaque;
486dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        qemu_mutex_unlock(&timer_list->active_timers_lock);
4876a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
4886a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        /* run the callback (the timer list can be modified) */
489dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        cb(opaque);
490dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        progress = true;
4916a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
492dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
493dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerout:
494dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    qemu_event_set(&timer_list->timers_done_ev);
495dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return progress;
4966a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
4976a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
498dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerbool qemu_clock_run_timers(QEMUClockType type)
4996a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
500dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return timerlist_run_timers(main_loop_tlg.tl[type]);
501dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
502dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
503dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid timerlistgroup_init(QEMUTimerListGroup *tlg,
504dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner                         QEMUTimerListNotifyCB *cb, void *opaque)
505dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
506dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUClockType type;
507dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
508dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        tlg->tl[type] = timerlist_new(type, cb, opaque);
509dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
510dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
511dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
512dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid timerlistgroup_deinit(QEMUTimerListGroup *tlg)
513dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
514dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUClockType type;
515dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
516dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timerlist_free(tlg->tl[type]);
517dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
518dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
519dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
520dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerbool timerlistgroup_run_timers(QEMUTimerListGroup *tlg)
521dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
522dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUClockType type;
523dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    bool progress = false;
524dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
525dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        progress |= timerlist_run_timers(tlg->tl[type]);
526dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
527dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return progress;
528dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
529dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
530dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerint64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg)
531dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
532dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    int64_t deadline = -1;
533dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUClockType type;
534dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
535dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        if (qemu_clock_use_for_deadline(tlg->tl[type]->clock->type)) {
536dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner            deadline = qemu_soonest_timeout(deadline,
537dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner                                            timerlist_deadline_ns(
538dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner                                                tlg->tl[type]));
5396a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        }
5406a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
541dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return deadline;
5426a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
5436a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
544dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerint64_t qemu_clock_get_ns(QEMUClockType type)
5456a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
546dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    int64_t now, last;
547dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUClock *clock = qemu_clock_ptr(type);
548dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
549dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    switch (type) {
5506a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    case QEMU_CLOCK_REALTIME:
5516a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        return get_clock();
5526a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    default:
5536a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    case QEMU_CLOCK_VIRTUAL:
5546a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        if (use_icount) {
5556a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            return cpu_get_icount();
5566a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        } else {
5576a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner            return cpu_get_clock();
5586a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner        }
5596a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    case QEMU_CLOCK_HOST:
560dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        now = get_clock_realtime();
561dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        last = clock->last;
562dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        clock->last = now;
563dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        if (now < last) {
564dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner            notifier_list_notify(&clock->reset_notifiers, &now);
565dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        }
566dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        return now;
5676a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
5686a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
5696a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
570dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid qemu_clock_register_reset_notifier(QEMUClockType type,
571dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner                                        Notifier *notifier)
5726a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
573dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUClock *clock = qemu_clock_ptr(type);
574dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    notifier_list_add(&clock->reset_notifiers, notifier);
5756a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
5766a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
577dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid qemu_clock_unregister_reset_notifier(QEMUClockType type,
578dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner                                          Notifier *notifier)
5796a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
580dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    notifier_remove(notifier);
581dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
5826a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
583dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid init_clocks(void)
584dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
585dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUClockType type;
586dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
587dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        qemu_clock_init(type);
5886a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
589dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
590dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
591dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0);
592dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#endif
5936a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
5946a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
595dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turneruint64_t timer_expire_time_ns(QEMUTimer *ts)
5966a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner{
597dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return timer_pending(ts) ? ts->expire_time : -1;
5986a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner}
5996a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner
600dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerbool qemu_clock_run_all_timers(void)
601dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
602dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    bool progress = false;
603dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    QEMUClockType type;
604dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
605dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    for (type = 0; type < QEMU_CLOCK_MAX; type++) {
606dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        progress |= qemu_clock_run_timers(type);
6076a9ef1773bf874dea493ff3861782a1e577b67ddDavid Turner    }
608dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
609dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return progress;
610dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
611