xref: /openbmc/qemu/include/qemu/timer.h (revision e8eed838)
11de7afc9SPaolo Bonzini #ifndef QEMU_TIMER_H
21de7afc9SPaolo Bonzini #define QEMU_TIMER_H
31de7afc9SPaolo Bonzini 
489a603a0SArtem Pisarenko #include "qemu/bitops.h"
51de7afc9SPaolo Bonzini #include "qemu/notify.h"
649caffe0SPeter Maydell #include "qemu/host-utils.h"
71de7afc9SPaolo Bonzini 
813566fe3SStefan Hajnoczi #define NANOSECONDS_PER_SECOND 1000000000LL
9471fae3cSAlberto Garcia 
101de7afc9SPaolo Bonzini /* timers */
111de7afc9SPaolo Bonzini 
121de7afc9SPaolo Bonzini #define SCALE_MS 1000000
131de7afc9SPaolo Bonzini #define SCALE_US 1000
141de7afc9SPaolo Bonzini #define SCALE_NS 1
151de7afc9SPaolo Bonzini 
16ff83c66eSAlex Bligh /**
17ff83c66eSAlex Bligh  * QEMUClockType:
18ff83c66eSAlex Bligh  *
19ff83c66eSAlex Bligh  * The following clock types are available:
20ff83c66eSAlex Bligh  *
21ff83c66eSAlex Bligh  * @QEMU_CLOCK_REALTIME: Real time clock
22ff83c66eSAlex Bligh  *
23ff83c66eSAlex Bligh  * The real time clock should be used only for stuff which does not
24490ab15aSCao jin  * change the virtual machine state, as it runs even if the virtual
25490ab15aSCao jin  * machine is stopped.
26ff83c66eSAlex Bligh  *
27ff83c66eSAlex Bligh  * @QEMU_CLOCK_VIRTUAL: virtual clock
28ff83c66eSAlex Bligh  *
29490ab15aSCao jin  * The virtual clock only runs during the emulation. It stops
30490ab15aSCao jin  * when the virtual machine is stopped.
31ff83c66eSAlex Bligh  *
32ff83c66eSAlex Bligh  * @QEMU_CLOCK_HOST: host clock
33ff83c66eSAlex Bligh  *
34490ab15aSCao jin  * The host clock should be used for device models that emulate accurate
35ff83c66eSAlex Bligh  * real time sources. It will continue to run when the virtual machine
36ff83c66eSAlex Bligh  * is suspended, and it will reflect system time changes the host may
37490ab15aSCao jin  * undergo (e.g. due to NTP).
384e7fa73eSPavel Dovgalyuk  *
394e7fa73eSPavel Dovgalyuk  * @QEMU_CLOCK_VIRTUAL_RT: realtime clock used for icount warp
404e7fa73eSPavel Dovgalyuk  *
414e7fa73eSPavel Dovgalyuk  * Outside icount mode, this clock is the same as @QEMU_CLOCK_VIRTUAL.
424e7fa73eSPavel Dovgalyuk  * In icount mode, this clock counts nanoseconds while the virtual
43bf2a7ddbSPavel Dovgalyuk  * machine is running.  It is used to increase @QEMU_CLOCK_VIRTUAL
44bf2a7ddbSPavel Dovgalyuk  * while the CPUs are sleeping and thus not executing instructions.
45ff83c66eSAlex Bligh  */
46ff83c66eSAlex Bligh 
47ff83c66eSAlex Bligh typedef enum {
48ff83c66eSAlex Bligh     QEMU_CLOCK_REALTIME = 0,
49ff83c66eSAlex Bligh     QEMU_CLOCK_VIRTUAL = 1,
50ff83c66eSAlex Bligh     QEMU_CLOCK_HOST = 2,
514e7fa73eSPavel Dovgalyuk     QEMU_CLOCK_VIRTUAL_RT = 3,
52ff83c66eSAlex Bligh     QEMU_CLOCK_MAX
53ff83c66eSAlex Bligh } QEMUClockType;
5458ac56b9SAlex Bligh 
5589a603a0SArtem Pisarenko /**
5689a603a0SArtem Pisarenko  * QEMU Timer attributes:
5789a603a0SArtem Pisarenko  *
5889a603a0SArtem Pisarenko  * An individual timer may be given one or multiple attributes when initialized.
5989a603a0SArtem Pisarenko  * Each attribute corresponds to one bit. Attributes modify the processing
6089a603a0SArtem Pisarenko  * of timers when they fire.
6189a603a0SArtem Pisarenko  *
62e81f8679SArtem Pisarenko  * The following attributes are available:
63e81f8679SArtem Pisarenko  *
64e81f8679SArtem Pisarenko  * QEMU_TIMER_ATTR_EXTERNAL: drives external subsystem
65dcb15780SPavel Dovgalyuk  * QEMU_TIMER_ATTR_ALL: mask for all existing attributes
66e81f8679SArtem Pisarenko  *
67e81f8679SArtem Pisarenko  * Timers with this attribute do not recorded in rr mode, therefore it could be
68e81f8679SArtem Pisarenko  * used for the subsystems that operate outside the guest core. Applicable only
69e81f8679SArtem Pisarenko  * with virtual clock type.
7089a603a0SArtem Pisarenko  */
7189a603a0SArtem Pisarenko 
72dcb15780SPavel Dovgalyuk #define QEMU_TIMER_ATTR_EXTERNAL ((int)BIT(0))
73dcb15780SPavel Dovgalyuk #define QEMU_TIMER_ATTR_ALL      0xffffffff
74e81f8679SArtem Pisarenko 
75ff83c66eSAlex Bligh typedef struct QEMUTimerList QEMUTimerList;
76754d6a54SAlex Bligh 
77754d6a54SAlex Bligh struct QEMUTimerListGroup {
78754d6a54SAlex Bligh     QEMUTimerList *tl[QEMU_CLOCK_MAX];
79754d6a54SAlex Bligh };
80754d6a54SAlex Bligh 
811de7afc9SPaolo Bonzini typedef void QEMUTimerCB(void *opaque);
823f53bc61SPaolo Bonzini typedef void QEMUTimerListNotifyCB(void *opaque, QEMUClockType type);
831de7afc9SPaolo Bonzini 
84ff83c66eSAlex Bligh struct QEMUTimer {
85ff83c66eSAlex Bligh     int64_t expire_time;        /* in nanoseconds */
86ff83c66eSAlex Bligh     QEMUTimerList *timer_list;
87ff83c66eSAlex Bligh     QEMUTimerCB *cb;
88ff83c66eSAlex Bligh     void *opaque;
89ff83c66eSAlex Bligh     QEMUTimer *next;
9089a603a0SArtem Pisarenko     int attributes;
91ff83c66eSAlex Bligh     int scale;
92ff83c66eSAlex Bligh };
931de7afc9SPaolo Bonzini 
94754d6a54SAlex Bligh extern QEMUTimerListGroup main_loop_tlg;
951de7afc9SPaolo Bonzini 
9640daca54SAlex Bligh /*
9754904d2aSAlex Bligh  * qemu_clock_get_ns;
9854904d2aSAlex Bligh  * @type: the clock type
9954904d2aSAlex Bligh  *
10054904d2aSAlex Bligh  * Get the nanosecond value of a clock with
10154904d2aSAlex Bligh  * type @type
10254904d2aSAlex Bligh  *
10354904d2aSAlex Bligh  * Returns: the clock value in nanoseconds
10454904d2aSAlex Bligh  */
10540daca54SAlex Bligh int64_t qemu_clock_get_ns(QEMUClockType type);
10654904d2aSAlex Bligh 
10754904d2aSAlex Bligh /**
10855a197daSAlex Bligh  * qemu_clock_get_ms;
10955a197daSAlex Bligh  * @type: the clock type
11055a197daSAlex Bligh  *
11155a197daSAlex Bligh  * Get the millisecond value of a clock with
11255a197daSAlex Bligh  * type @type
11355a197daSAlex Bligh  *
11455a197daSAlex Bligh  * Returns: the clock value in milliseconds
11555a197daSAlex Bligh  */
qemu_clock_get_ms(QEMUClockType type)11655a197daSAlex Bligh static inline int64_t qemu_clock_get_ms(QEMUClockType type)
11755a197daSAlex Bligh {
11855a197daSAlex Bligh     return qemu_clock_get_ns(type) / SCALE_MS;
11955a197daSAlex Bligh }
12055a197daSAlex Bligh 
12155a197daSAlex Bligh /**
12255a197daSAlex Bligh  * qemu_clock_get_us;
12355a197daSAlex Bligh  * @type: the clock type
12455a197daSAlex Bligh  *
12555a197daSAlex Bligh  * Get the microsecond value of a clock with
12655a197daSAlex Bligh  * type @type
12755a197daSAlex Bligh  *
12855a197daSAlex Bligh  * Returns: the clock value in microseconds
12955a197daSAlex Bligh  */
qemu_clock_get_us(QEMUClockType type)13055a197daSAlex Bligh static inline int64_t qemu_clock_get_us(QEMUClockType type)
13155a197daSAlex Bligh {
13255a197daSAlex Bligh     return qemu_clock_get_ns(type) / SCALE_US;
13355a197daSAlex Bligh }
13455a197daSAlex Bligh 
13555a197daSAlex Bligh /**
13654904d2aSAlex Bligh  * qemu_clock_has_timers:
13740daca54SAlex Bligh  * @type: the clock type
13854904d2aSAlex Bligh  *
13954904d2aSAlex Bligh  * Determines whether a clock's default timer list
14054904d2aSAlex Bligh  * has timers attached
14154904d2aSAlex Bligh  *
142978f2205SStefan Hajnoczi  * Note that this function should not be used when other threads also access
143978f2205SStefan Hajnoczi  * the timer list.  The return value may be outdated by the time it is acted
144978f2205SStefan Hajnoczi  * upon.
145978f2205SStefan Hajnoczi  *
14654904d2aSAlex Bligh  * Returns: true if the clock's default timer list
14754904d2aSAlex Bligh  * has timers attached
14854904d2aSAlex Bligh  */
14940daca54SAlex Bligh bool qemu_clock_has_timers(QEMUClockType type);
15054904d2aSAlex Bligh 
15154904d2aSAlex Bligh /**
15254904d2aSAlex Bligh  * qemu_clock_expired:
15340daca54SAlex Bligh  * @type: the clock type
15454904d2aSAlex Bligh  *
15554904d2aSAlex Bligh  * Determines whether a clock's default timer list
15645241cf9SYaowei Bai  * has an expired timer.
15754904d2aSAlex Bligh  *
15854904d2aSAlex Bligh  * Returns: true if the clock's default timer list has
15954904d2aSAlex Bligh  * an expired timer
16054904d2aSAlex Bligh  */
16140daca54SAlex Bligh bool qemu_clock_expired(QEMUClockType type);
16202a03a9fSAlex Bligh 
16302a03a9fSAlex Bligh /**
164ff83c66eSAlex Bligh  * qemu_clock_use_for_deadline:
16540daca54SAlex Bligh  * @type: the clock type
166ff83c66eSAlex Bligh  *
167ff83c66eSAlex Bligh  * Determine whether a clock should be used for deadline
168ff83c66eSAlex Bligh  * calculations. Some clocks, for instance vm_clock with
169740b1759SClaudio Fontana  * icount_enabled() set, do not count in nanoseconds.
170740b1759SClaudio Fontana  * Such clocks are not used for deadline calculations, and are presumed
171ff83c66eSAlex Bligh  * to interrupt any poll using qemu_notify/aio_notify
172ff83c66eSAlex Bligh  * etc.
173ff83c66eSAlex Bligh  *
174ff83c66eSAlex Bligh  * Returns: true if the clock runs in nanoseconds and
175ff83c66eSAlex Bligh  * should be used for a deadline.
176ff83c66eSAlex Bligh  */
17740daca54SAlex Bligh bool qemu_clock_use_for_deadline(QEMUClockType type);
178ff83c66eSAlex Bligh 
179ff83c66eSAlex Bligh /**
18040daca54SAlex Bligh  * qemu_clock_deadline_ns_all:
18140daca54SAlex Bligh  * @type: the clock type
182dcb15780SPavel Dovgalyuk  * @attr_mask: mask for the timer attributes that are included
183dcb15780SPavel Dovgalyuk  *             in deadline calculation
184ac70aafcSAlex Bligh  *
185ac70aafcSAlex Bligh  * Calculate the deadline across all timer lists associated
186ac70aafcSAlex Bligh  * with a clock (as opposed to just the default one)
187ac70aafcSAlex Bligh  * in nanoseconds, or -1 if no timer is set to expire.
188ac70aafcSAlex Bligh  *
189ac70aafcSAlex Bligh  * Returns: time until expiry in nanoseconds or -1
190ac70aafcSAlex Bligh  */
191dcb15780SPavel Dovgalyuk int64_t qemu_clock_deadline_ns_all(QEMUClockType type, int attr_mask);
192ac70aafcSAlex Bligh 
193ac70aafcSAlex Bligh /**
194ff83c66eSAlex Bligh  * qemu_clock_get_main_loop_timerlist:
19540daca54SAlex Bligh  * @type: the clock type
196ff83c66eSAlex Bligh  *
197083b96e2SCao jin  * Return the default timer list associated with a clock.
198ff83c66eSAlex Bligh  *
199ff83c66eSAlex Bligh  * Returns: the default timer list
200ff83c66eSAlex Bligh  */
20140daca54SAlex Bligh QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClockType type);
202ff83c66eSAlex Bligh 
203ff83c66eSAlex Bligh /**
204b1bbfe72SAlex Bligh  * qemu_clock_nofify:
20540daca54SAlex Bligh  * @type: the clock type
206b1bbfe72SAlex Bligh  *
207b1bbfe72SAlex Bligh  * Call the notifier callback connected with the default timer
208b1bbfe72SAlex Bligh  * list linked to the clock, or qemu_notify() if none.
209b1bbfe72SAlex Bligh  */
21040daca54SAlex Bligh void qemu_clock_notify(QEMUClockType type);
21140daca54SAlex Bligh 
21240daca54SAlex Bligh /**
21340daca54SAlex Bligh  * qemu_clock_enable:
21440daca54SAlex Bligh  * @type: the clock type
21540daca54SAlex Bligh  * @enabled: true to enable, false to disable
21640daca54SAlex Bligh  *
21740daca54SAlex Bligh  * Enable or disable a clock
2183c053411SLiu Ping Fan  * Disabling the clock will wait for related timerlists to stop
2193c053411SLiu Ping Fan  * executing qemu_run_timers.  Thus, this functions should not
2203c053411SLiu Ping Fan  * be used from the callback of a timer that is based on @clock.
2213c053411SLiu Ping Fan  * Doing so would cause a deadlock.
2223c053411SLiu Ping Fan  *
2233c053411SLiu Ping Fan  * Caller should hold BQL.
22440daca54SAlex Bligh  */
22540daca54SAlex Bligh void qemu_clock_enable(QEMUClockType type, bool enabled);
22640daca54SAlex Bligh 
22740daca54SAlex Bligh /**
22840daca54SAlex Bligh  * qemu_clock_run_timers:
22940daca54SAlex Bligh  * @type: clock on which to operate
23040daca54SAlex Bligh  *
23140daca54SAlex Bligh  * Run all the timers associated with the default timer list
23240daca54SAlex Bligh  * of a clock.
23340daca54SAlex Bligh  *
23440daca54SAlex Bligh  * Returns: true if any timer ran.
23540daca54SAlex Bligh  */
23640daca54SAlex Bligh bool qemu_clock_run_timers(QEMUClockType type);
23740daca54SAlex Bligh 
23840daca54SAlex Bligh /**
23940daca54SAlex Bligh  * qemu_clock_run_all_timers:
24040daca54SAlex Bligh  *
24140daca54SAlex Bligh  * Run all the timers associated with the default timer list
24240daca54SAlex Bligh  * of every clock.
24340daca54SAlex Bligh  *
24440daca54SAlex Bligh  * Returns: true if any timer ran.
24540daca54SAlex Bligh  */
24640daca54SAlex Bligh bool qemu_clock_run_all_timers(void);
24740daca54SAlex Bligh 
2484b930d26SPavel Dovgalyuk 
24940daca54SAlex Bligh /*
25040daca54SAlex Bligh  * QEMUTimerList
25140daca54SAlex Bligh  */
252b1bbfe72SAlex Bligh 
253b1bbfe72SAlex Bligh /**
254ff83c66eSAlex Bligh  * timerlist_new:
255ff83c66eSAlex Bligh  * @type: the clock type to associate with the timerlist
256d5541d86SAlex Bligh  * @cb: the callback to call on notification
257d5541d86SAlex Bligh  * @opaque: the opaque pointer to pass to the callback
258ff83c66eSAlex Bligh  *
259ff83c66eSAlex Bligh  * Create a new timerlist associated with the clock of
260ff83c66eSAlex Bligh  * type @type.
261ff83c66eSAlex Bligh  *
262ff83c66eSAlex Bligh  * Returns: a pointer to the QEMUTimerList created
263ff83c66eSAlex Bligh  */
264d5541d86SAlex Bligh QEMUTimerList *timerlist_new(QEMUClockType type,
265d5541d86SAlex Bligh                              QEMUTimerListNotifyCB *cb, void *opaque);
266ff83c66eSAlex Bligh 
267ff83c66eSAlex Bligh /**
268ff83c66eSAlex Bligh  * timerlist_free:
269ff83c66eSAlex Bligh  * @timer_list: the timer list to free
270ff83c66eSAlex Bligh  *
271ff83c66eSAlex Bligh  * Frees a timer_list. It must have no active timers.
272ff83c66eSAlex Bligh  */
273ff83c66eSAlex Bligh void timerlist_free(QEMUTimerList *timer_list);
274ff83c66eSAlex Bligh 
275ff83c66eSAlex Bligh /**
276ff83c66eSAlex Bligh  * timerlist_has_timers:
277ff83c66eSAlex Bligh  * @timer_list: the timer list to operate on
278ff83c66eSAlex Bligh  *
279ff83c66eSAlex Bligh  * Determine whether a timer list has active timers
280ff83c66eSAlex Bligh  *
281978f2205SStefan Hajnoczi  * Note that this function should not be used when other threads also access
282978f2205SStefan Hajnoczi  * the timer list.  The return value may be outdated by the time it is acted
283978f2205SStefan Hajnoczi  * upon.
284978f2205SStefan Hajnoczi  *
285ff83c66eSAlex Bligh  * Returns: true if the timer list has timers.
286ff83c66eSAlex Bligh  */
287ff83c66eSAlex Bligh bool timerlist_has_timers(QEMUTimerList *timer_list);
288ff83c66eSAlex Bligh 
289ff83c66eSAlex Bligh /**
290ff83c66eSAlex Bligh  * timerlist_expired:
291ff83c66eSAlex Bligh  * @timer_list: the timer list to operate on
292ff83c66eSAlex Bligh  *
293ff83c66eSAlex Bligh  * Determine whether a timer list has any timers which
294ff83c66eSAlex Bligh  * are expired.
295ff83c66eSAlex Bligh  *
296ff83c66eSAlex Bligh  * Returns: true if the timer list has timers which
297ff83c66eSAlex Bligh  * have expired.
298ff83c66eSAlex Bligh  */
299ff83c66eSAlex Bligh bool timerlist_expired(QEMUTimerList *timer_list);
300ff83c66eSAlex Bligh 
301ff83c66eSAlex Bligh /**
302ff83c66eSAlex Bligh  * timerlist_deadline_ns:
303ff83c66eSAlex Bligh  * @timer_list: the timer list to operate on
304ff83c66eSAlex Bligh  *
305ff83c66eSAlex Bligh  * Determine the deadline for a timer_list, i.e.
306ff83c66eSAlex Bligh  * the number of nanoseconds until the first timer
307ff83c66eSAlex Bligh  * expires. Return -1 if there are no timers.
308ff83c66eSAlex Bligh  *
309ff83c66eSAlex Bligh  * Returns: the number of nanoseconds until the earliest
310ff83c66eSAlex Bligh  * timer expires -1 if none
311ff83c66eSAlex Bligh  */
312ff83c66eSAlex Bligh int64_t timerlist_deadline_ns(QEMUTimerList *timer_list);
313ff83c66eSAlex Bligh 
314ff83c66eSAlex Bligh /**
31540daca54SAlex Bligh  * timerlist_get_clock:
316ff83c66eSAlex Bligh  * @timer_list: the timer list to operate on
317ff83c66eSAlex Bligh  *
31840daca54SAlex Bligh  * Determine the clock type associated with a timer list.
319ff83c66eSAlex Bligh  *
32040daca54SAlex Bligh  * Returns: the clock type associated with the
32140daca54SAlex Bligh  * timer list.
322ff83c66eSAlex Bligh  */
32340daca54SAlex Bligh QEMUClockType timerlist_get_clock(QEMUTimerList *timer_list);
324ff83c66eSAlex Bligh 
325ff83c66eSAlex Bligh /**
326ff83c66eSAlex Bligh  * timerlist_run_timers:
327ff83c66eSAlex Bligh  * @timer_list: the timer list to use
328ff83c66eSAlex Bligh  *
329ff83c66eSAlex Bligh  * Call all expired timers associated with the timer list.
330ff83c66eSAlex Bligh  *
331ff83c66eSAlex Bligh  * Returns: true if any timer expired
332ff83c66eSAlex Bligh  */
333ff83c66eSAlex Bligh bool timerlist_run_timers(QEMUTimerList *timer_list);
334ff83c66eSAlex Bligh 
335ff83c66eSAlex Bligh /**
336d5541d86SAlex Bligh  * timerlist_notify:
337d5541d86SAlex Bligh  * @timer_list: the timer list to use
338d5541d86SAlex Bligh  *
339d5541d86SAlex Bligh  * call the notifier callback associated with the timer list.
340d5541d86SAlex Bligh  */
341d5541d86SAlex Bligh void timerlist_notify(QEMUTimerList *timer_list);
342d5541d86SAlex Bligh 
34340daca54SAlex Bligh /*
34440daca54SAlex Bligh  * QEMUTimerListGroup
34540daca54SAlex Bligh  */
34640daca54SAlex Bligh 
347d5541d86SAlex Bligh /**
348754d6a54SAlex Bligh  * timerlistgroup_init:
349754d6a54SAlex Bligh  * @tlg: the timer list group
350d5541d86SAlex Bligh  * @cb: the callback to call when a notify is required
351d5541d86SAlex Bligh  * @opaque: the opaque pointer to be passed to the callback.
352754d6a54SAlex Bligh  *
353754d6a54SAlex Bligh  * Initialise a timer list group. This must already be
354d5541d86SAlex Bligh  * allocated in memory and zeroed. The notifier callback is
355d5541d86SAlex Bligh  * called whenever a clock in the timer list group is
356d5541d86SAlex Bligh  * reenabled or whenever a timer associated with any timer
357d5541d86SAlex Bligh  * list is modified. If @cb is specified as null, qemu_notify()
358d5541d86SAlex Bligh  * is used instead.
359754d6a54SAlex Bligh  */
360d5541d86SAlex Bligh void timerlistgroup_init(QEMUTimerListGroup *tlg,
361d5541d86SAlex Bligh                          QEMUTimerListNotifyCB *cb, void *opaque);
362754d6a54SAlex Bligh 
363754d6a54SAlex Bligh /**
364754d6a54SAlex Bligh  * timerlistgroup_deinit:
365754d6a54SAlex Bligh  * @tlg: the timer list group
366754d6a54SAlex Bligh  *
367754d6a54SAlex Bligh  * Deinitialise a timer list group. This must already be
368754d6a54SAlex Bligh  * initialised. Note the memory is not freed.
369754d6a54SAlex Bligh  */
370754d6a54SAlex Bligh void timerlistgroup_deinit(QEMUTimerListGroup *tlg);
371754d6a54SAlex Bligh 
372754d6a54SAlex Bligh /**
373754d6a54SAlex Bligh  * timerlistgroup_run_timers:
374754d6a54SAlex Bligh  * @tlg: the timer list group
375754d6a54SAlex Bligh  *
376754d6a54SAlex Bligh  * Run the timers associated with a timer list group.
377754d6a54SAlex Bligh  * This will run timers on multiple clocks.
378754d6a54SAlex Bligh  *
379754d6a54SAlex Bligh  * Returns: true if any timer callback ran
380754d6a54SAlex Bligh  */
381754d6a54SAlex Bligh bool timerlistgroup_run_timers(QEMUTimerListGroup *tlg);
382754d6a54SAlex Bligh 
383754d6a54SAlex Bligh /**
38454904d2aSAlex Bligh  * timerlistgroup_deadline_ns:
385754d6a54SAlex Bligh  * @tlg: the timer list group
386754d6a54SAlex Bligh  *
387754d6a54SAlex Bligh  * Determine the deadline of the soonest timer to
388754d6a54SAlex Bligh  * expire associated with any timer list linked to
389754d6a54SAlex Bligh  * the timer list group. Only clocks suitable for
390754d6a54SAlex Bligh  * deadline calculation are included.
391754d6a54SAlex Bligh  *
392754d6a54SAlex Bligh  * Returns: the deadline in nanoseconds or -1 if no
393754d6a54SAlex Bligh  * timers are to expire.
394754d6a54SAlex Bligh  */
395754d6a54SAlex Bligh int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg);
396754d6a54SAlex Bligh 
39740daca54SAlex Bligh /*
39840daca54SAlex Bligh  * QEMUTimer
39902a03a9fSAlex Bligh  */
400ff83c66eSAlex Bligh 
401ff83c66eSAlex Bligh /**
40289a603a0SArtem Pisarenko  * timer_init_full:
403ff83c66eSAlex Bligh  * @ts: the timer to be initialised
40489a603a0SArtem Pisarenko  * @timer_list_group: (optional) the timer list group to attach the timer to
40589a603a0SArtem Pisarenko  * @type: the clock type to use
406dc9fc1caSNamhyung Kim  * @scale: the scale value for the timer
40789a603a0SArtem Pisarenko  * @attributes: 0, or one or more OR'ed QEMU_TIMER_ATTR_<id> values
408ff83c66eSAlex Bligh  * @cb: the callback to be called when the timer expires
409ff83c66eSAlex Bligh  * @opaque: the opaque pointer to be passed to the callback
410ff83c66eSAlex Bligh  *
41189a603a0SArtem Pisarenko  * Initialise a timer with the given scale and attributes,
41289a603a0SArtem Pisarenko  * and associate it with timer list for given clock @type in @timer_list_group
41389a603a0SArtem Pisarenko  * (or default timer list group, if NULL).
414ff83c66eSAlex Bligh  * The caller is responsible for allocating the memory.
415ff83c66eSAlex Bligh  *
416ff83c66eSAlex Bligh  * You need not call an explicit deinit call. Simply make
417ff83c66eSAlex Bligh  * sure it is not on a list with timer_del.
418ff83c66eSAlex Bligh  */
41989a603a0SArtem Pisarenko void timer_init_full(QEMUTimer *ts,
42089a603a0SArtem Pisarenko                      QEMUTimerListGroup *timer_list_group, QEMUClockType type,
42189a603a0SArtem Pisarenko                      int scale, int attributes,
422ff83c66eSAlex Bligh                      QEMUTimerCB *cb, void *opaque);
423ff83c66eSAlex Bligh 
424ff83c66eSAlex Bligh /**
42565a81af8SPaolo Bonzini  * timer_init:
42604ecbb78SCao jin  * @ts: the timer to be initialised
42765a81af8SPaolo Bonzini  * @type: the clock to associate with the timer
42865a81af8SPaolo Bonzini  * @scale: the scale value for the timer
42965a81af8SPaolo Bonzini  * @cb: the callback to call when the timer expires
43065a81af8SPaolo Bonzini  * @opaque: the opaque pointer to pass to the callback
43165a81af8SPaolo Bonzini  *
43265a81af8SPaolo Bonzini  * Initialize a timer with the given scale on the default timer list
43365a81af8SPaolo Bonzini  * associated with the clock.
43489a603a0SArtem Pisarenko  * See timer_init_full for details.
43565a81af8SPaolo Bonzini  */
timer_init(QEMUTimer * ts,QEMUClockType type,int scale,QEMUTimerCB * cb,void * opaque)43665a81af8SPaolo Bonzini static inline void timer_init(QEMUTimer *ts, QEMUClockType type, int scale,
43765a81af8SPaolo Bonzini                               QEMUTimerCB *cb, void *opaque)
43865a81af8SPaolo Bonzini {
43989a603a0SArtem Pisarenko     timer_init_full(ts, NULL, type, scale, 0, cb, opaque);
44065a81af8SPaolo Bonzini }
44165a81af8SPaolo Bonzini 
44265a81af8SPaolo Bonzini /**
44365a81af8SPaolo Bonzini  * timer_init_ns:
44404ecbb78SCao jin  * @ts: the timer to be initialised
44565a81af8SPaolo Bonzini  * @type: the clock to associate with the timer
44665a81af8SPaolo Bonzini  * @cb: the callback to call when the timer expires
44765a81af8SPaolo Bonzini  * @opaque: the opaque pointer to pass to the callback
44865a81af8SPaolo Bonzini  *
44965a81af8SPaolo Bonzini  * Initialize a timer with nanosecond scale on the default timer list
45065a81af8SPaolo Bonzini  * associated with the clock.
45189a603a0SArtem Pisarenko  * See timer_init_full for details.
45265a81af8SPaolo Bonzini  */
timer_init_ns(QEMUTimer * ts,QEMUClockType type,QEMUTimerCB * cb,void * opaque)45365a81af8SPaolo Bonzini static inline void timer_init_ns(QEMUTimer *ts, QEMUClockType type,
45465a81af8SPaolo Bonzini                                  QEMUTimerCB *cb, void *opaque)
45565a81af8SPaolo Bonzini {
45665a81af8SPaolo Bonzini     timer_init(ts, type, SCALE_NS, cb, opaque);
45765a81af8SPaolo Bonzini }
45865a81af8SPaolo Bonzini 
45965a81af8SPaolo Bonzini /**
46065a81af8SPaolo Bonzini  * timer_init_us:
46104ecbb78SCao jin  * @ts: the timer to be initialised
46265a81af8SPaolo Bonzini  * @type: the clock to associate with the timer
46365a81af8SPaolo Bonzini  * @cb: the callback to call when the timer expires
46465a81af8SPaolo Bonzini  * @opaque: the opaque pointer to pass to the callback
46565a81af8SPaolo Bonzini  *
46665a81af8SPaolo Bonzini  * Initialize a timer with microsecond scale on the default timer list
46765a81af8SPaolo Bonzini  * associated with the clock.
46889a603a0SArtem Pisarenko  * See timer_init_full for details.
46965a81af8SPaolo Bonzini  */
timer_init_us(QEMUTimer * ts,QEMUClockType type,QEMUTimerCB * cb,void * opaque)47065a81af8SPaolo Bonzini static inline void timer_init_us(QEMUTimer *ts, QEMUClockType type,
47165a81af8SPaolo Bonzini                                  QEMUTimerCB *cb, void *opaque)
47265a81af8SPaolo Bonzini {
47365a81af8SPaolo Bonzini     timer_init(ts, type, SCALE_US, cb, opaque);
47465a81af8SPaolo Bonzini }
47565a81af8SPaolo Bonzini 
47665a81af8SPaolo Bonzini /**
47765a81af8SPaolo Bonzini  * timer_init_ms:
47804ecbb78SCao jin  * @ts: the timer to be initialised
47965a81af8SPaolo Bonzini  * @type: the clock to associate with the timer
48065a81af8SPaolo Bonzini  * @cb: the callback to call when the timer expires
48165a81af8SPaolo Bonzini  * @opaque: the opaque pointer to pass to the callback
48265a81af8SPaolo Bonzini  *
48365a81af8SPaolo Bonzini  * Initialize a timer with millisecond scale on the default timer list
48465a81af8SPaolo Bonzini  * associated with the clock.
48589a603a0SArtem Pisarenko  * See timer_init_full for details.
48665a81af8SPaolo Bonzini  */
timer_init_ms(QEMUTimer * ts,QEMUClockType type,QEMUTimerCB * cb,void * opaque)48765a81af8SPaolo Bonzini static inline void timer_init_ms(QEMUTimer *ts, QEMUClockType type,
48865a81af8SPaolo Bonzini                                  QEMUTimerCB *cb, void *opaque)
48965a81af8SPaolo Bonzini {
49065a81af8SPaolo Bonzini     timer_init(ts, type, SCALE_MS, cb, opaque);
49165a81af8SPaolo Bonzini }
49265a81af8SPaolo Bonzini 
49365a81af8SPaolo Bonzini /**
49489a603a0SArtem Pisarenko  * timer_new_full:
49589a603a0SArtem Pisarenko  * @timer_list_group: (optional) the timer list group to attach the timer to
49689a603a0SArtem Pisarenko  * @type: the clock type to use
497dc9fc1caSNamhyung Kim  * @scale: the scale value for the timer
49889a603a0SArtem Pisarenko  * @attributes: 0, or one or more OR'ed QEMU_TIMER_ATTR_<id> values
499ff83c66eSAlex Bligh  * @cb: the callback to be called when the timer expires
500ff83c66eSAlex Bligh  * @opaque: the opaque pointer to be passed to the callback
501ff83c66eSAlex Bligh  *
50289a603a0SArtem Pisarenko  * Create a new timer with the given scale and attributes,
50389a603a0SArtem Pisarenko  * and associate it with timer list for given clock @type in @timer_list_group
50489a603a0SArtem Pisarenko  * (or default timer list group, if NULL).
505ff83c66eSAlex Bligh  * The memory is allocated by the function.
506ff83c66eSAlex Bligh  *
507ff83c66eSAlex Bligh  * This is not the preferred interface unless you know you
50889a603a0SArtem Pisarenko  * are going to call timer_free. Use timer_init or timer_init_full instead.
50989a603a0SArtem Pisarenko  *
51089a603a0SArtem Pisarenko  * The default timer list has one special feature: in icount mode,
51189a603a0SArtem Pisarenko  * %QEMU_CLOCK_VIRTUAL timers are run in the vCPU thread.  This is
51289a603a0SArtem Pisarenko  * not true of other timer lists, which are typically associated
51389a603a0SArtem Pisarenko  * with an AioContext---each of them runs its timer callbacks in its own
51489a603a0SArtem Pisarenko  * AioContext thread.
515ff83c66eSAlex Bligh  *
516ff83c66eSAlex Bligh  * Returns: a pointer to the timer
517ff83c66eSAlex Bligh  */
timer_new_full(QEMUTimerListGroup * timer_list_group,QEMUClockType type,int scale,int attributes,QEMUTimerCB * cb,void * opaque)51889a603a0SArtem Pisarenko static inline QEMUTimer *timer_new_full(QEMUTimerListGroup *timer_list_group,
51989a603a0SArtem Pisarenko                                         QEMUClockType type,
52089a603a0SArtem Pisarenko                                         int scale, int attributes,
52189a603a0SArtem Pisarenko                                         QEMUTimerCB *cb, void *opaque)
522ff83c66eSAlex Bligh {
523b21e2380SMarkus Armbruster     QEMUTimer *ts = g_new0(QEMUTimer, 1);
52489a603a0SArtem Pisarenko     timer_init_full(ts, timer_list_group, type, scale, attributes, cb, opaque);
525ff83c66eSAlex Bligh     return ts;
526ff83c66eSAlex Bligh }
527ff83c66eSAlex Bligh 
528a3a726aeSAlex Bligh /**
529a3a726aeSAlex Bligh  * timer_new:
530a3a726aeSAlex Bligh  * @type: the clock type to use
531dc9fc1caSNamhyung Kim  * @scale: the scale value for the timer
532a3a726aeSAlex Bligh  * @cb: the callback to be called when the timer expires
533a3a726aeSAlex Bligh  * @opaque: the opaque pointer to be passed to the callback
534a3a726aeSAlex Bligh  *
53589a603a0SArtem Pisarenko  * Create a new timer with the given scale,
53689a603a0SArtem Pisarenko  * and associate it with the default timer list for the clock type @type.
53789a603a0SArtem Pisarenko  * See timer_new_full for details.
5386b8f0187SPaolo Bonzini  *
539a3a726aeSAlex Bligh  * Returns: a pointer to the timer
540a3a726aeSAlex Bligh  */
timer_new(QEMUClockType type,int scale,QEMUTimerCB * cb,void * opaque)541a3a726aeSAlex Bligh static inline QEMUTimer *timer_new(QEMUClockType type, int scale,
542a3a726aeSAlex Bligh                                    QEMUTimerCB *cb, void *opaque)
543a3a726aeSAlex Bligh {
54489a603a0SArtem Pisarenko     return timer_new_full(NULL, type, scale, 0, cb, opaque);
545a3a726aeSAlex Bligh }
546a3a726aeSAlex Bligh 
54754904d2aSAlex Bligh /**
54840daca54SAlex Bligh  * timer_new_ns:
54904ecbb78SCao jin  * @type: the clock type to associate with the timer
55004ecbb78SCao jin  * @cb: the callback to call when the timer expires
55140daca54SAlex Bligh  * @opaque: the opaque pointer to pass to the callback
55254904d2aSAlex Bligh  *
55340daca54SAlex Bligh  * Create a new timer with nanosecond scale on the default timer list
55440daca54SAlex Bligh  * associated with the clock.
55589a603a0SArtem Pisarenko  * See timer_new_full for details.
5566b8f0187SPaolo Bonzini  *
55740daca54SAlex Bligh  * Returns: a pointer to the newly created timer
55854904d2aSAlex Bligh  */
timer_new_ns(QEMUClockType type,QEMUTimerCB * cb,void * opaque)55940daca54SAlex Bligh static inline QEMUTimer *timer_new_ns(QEMUClockType type, QEMUTimerCB *cb,
56040daca54SAlex Bligh                                       void *opaque)
56140daca54SAlex Bligh {
56240daca54SAlex Bligh     return timer_new(type, SCALE_NS, cb, opaque);
56340daca54SAlex Bligh }
56440daca54SAlex Bligh 
56540daca54SAlex Bligh /**
56640daca54SAlex Bligh  * timer_new_us:
56704ecbb78SCao jin  * @type: the clock type to associate with the timer
56804ecbb78SCao jin  * @cb: the callback to call when the timer expires
56940daca54SAlex Bligh  * @opaque: the opaque pointer to pass to the callback
57040daca54SAlex Bligh  *
57140daca54SAlex Bligh  * Create a new timer with microsecond scale on the default timer list
57240daca54SAlex Bligh  * associated with the clock.
57389a603a0SArtem Pisarenko  * See timer_new_full for details.
57440daca54SAlex Bligh  *
57540daca54SAlex Bligh  * Returns: a pointer to the newly created timer
57640daca54SAlex Bligh  */
timer_new_us(QEMUClockType type,QEMUTimerCB * cb,void * opaque)57740daca54SAlex Bligh static inline QEMUTimer *timer_new_us(QEMUClockType type, QEMUTimerCB *cb,
57840daca54SAlex Bligh                                       void *opaque)
57940daca54SAlex Bligh {
58040daca54SAlex Bligh     return timer_new(type, SCALE_US, cb, opaque);
58140daca54SAlex Bligh }
58240daca54SAlex Bligh 
58340daca54SAlex Bligh /**
58440daca54SAlex Bligh  * timer_new_ms:
58504ecbb78SCao jin  * @type: the clock type to associate with the timer
58604ecbb78SCao jin  * @cb: the callback to call when the timer expires
58740daca54SAlex Bligh  * @opaque: the opaque pointer to pass to the callback
58840daca54SAlex Bligh  *
58940daca54SAlex Bligh  * Create a new timer with millisecond scale on the default timer list
59040daca54SAlex Bligh  * associated with the clock.
59189a603a0SArtem Pisarenko  * See timer_new_full for details.
59240daca54SAlex Bligh  *
59340daca54SAlex Bligh  * Returns: a pointer to the newly created timer
59440daca54SAlex Bligh  */
timer_new_ms(QEMUClockType type,QEMUTimerCB * cb,void * opaque)59540daca54SAlex Bligh static inline QEMUTimer *timer_new_ms(QEMUClockType type, QEMUTimerCB *cb,
59640daca54SAlex Bligh                                       void *opaque)
59740daca54SAlex Bligh {
59840daca54SAlex Bligh     return timer_new(type, SCALE_MS, cb, opaque);
59940daca54SAlex Bligh }
600ff83c66eSAlex Bligh 
601ff83c66eSAlex Bligh /**
602cd1bd53aSPaolo Bonzini  * timer_deinit:
603cd1bd53aSPaolo Bonzini  * @ts: the timer to be de-initialised
604cd1bd53aSPaolo Bonzini  *
605cd1bd53aSPaolo Bonzini  * Deassociate the timer from any timerlist.  You should
606cd1bd53aSPaolo Bonzini  * call timer_del before.  After this call, any further
607cd1bd53aSPaolo Bonzini  * timer_del call cannot cause dangling pointer accesses
608cd1bd53aSPaolo Bonzini  * even if the previously used timerlist is freed.
609cd1bd53aSPaolo Bonzini  */
610cd1bd53aSPaolo Bonzini void timer_deinit(QEMUTimer *ts);
611cd1bd53aSPaolo Bonzini 
612cd1bd53aSPaolo Bonzini /**
61354904d2aSAlex Bligh  * timer_del:
61440daca54SAlex Bligh  * @ts: the timer
61554904d2aSAlex Bligh  *
61640daca54SAlex Bligh  * Delete a timer from the active list.
617978f2205SStefan Hajnoczi  *
618978f2205SStefan Hajnoczi  * This function is thread-safe but the timer and its timer list must not be
619978f2205SStefan Hajnoczi  * freed while this function is running.
620ff83c66eSAlex Bligh  */
62140daca54SAlex Bligh void timer_del(QEMUTimer *ts);
62254904d2aSAlex Bligh 
62354904d2aSAlex Bligh /**
6245f8e93c3SPeter Maydell  * timer_free:
6255f8e93c3SPeter Maydell  * @ts: the timer
6265f8e93c3SPeter Maydell  *
6275f8e93c3SPeter Maydell  * Free a timer. This will call timer_del() for you to remove
6285f8e93c3SPeter Maydell  * the timer from the active list if it was still active.
6295f8e93c3SPeter Maydell  */
timer_free(QEMUTimer * ts)6305f8e93c3SPeter Maydell static inline void timer_free(QEMUTimer *ts)
6315f8e93c3SPeter Maydell {
6328b858f99SPaolo Bonzini     if (ts) {
6335f8e93c3SPeter Maydell         timer_del(ts);
6345f8e93c3SPeter Maydell         g_free(ts);
6355f8e93c3SPeter Maydell     }
6368b858f99SPaolo Bonzini }
6375f8e93c3SPeter Maydell 
6385f8e93c3SPeter Maydell /**
63954904d2aSAlex Bligh  * timer_mod_ns:
64040daca54SAlex Bligh  * @ts: the timer
64154904d2aSAlex Bligh  * @expire_time: the expiry time in nanoseconds
64254904d2aSAlex Bligh  *
64340daca54SAlex Bligh  * Modify a timer to expire at @expire_time
644978f2205SStefan Hajnoczi  *
645978f2205SStefan Hajnoczi  * This function is thread-safe but the timer and its timer list must not be
646978f2205SStefan Hajnoczi  * freed while this function is running.
647ff83c66eSAlex Bligh  */
64840daca54SAlex Bligh void timer_mod_ns(QEMUTimer *ts, int64_t expire_time);
64954904d2aSAlex Bligh 
65054904d2aSAlex Bligh /**
651add40e97SPaolo Bonzini  * timer_mod_anticipate_ns:
652add40e97SPaolo Bonzini  * @ts: the timer
653add40e97SPaolo Bonzini  * @expire_time: the expiry time in nanoseconds
654add40e97SPaolo Bonzini  *
655add40e97SPaolo Bonzini  * Modify a timer to expire at @expire_time or the current time,
656add40e97SPaolo Bonzini  * whichever comes earlier.
657add40e97SPaolo Bonzini  *
658add40e97SPaolo Bonzini  * This function is thread-safe but the timer and its timer list must not be
659add40e97SPaolo Bonzini  * freed while this function is running.
660add40e97SPaolo Bonzini  */
661add40e97SPaolo Bonzini void timer_mod_anticipate_ns(QEMUTimer *ts, int64_t expire_time);
662add40e97SPaolo Bonzini 
663add40e97SPaolo Bonzini /**
66454904d2aSAlex Bligh  * timer_mod:
66540daca54SAlex Bligh  * @ts: the timer
66640daca54SAlex Bligh  * @expire_time: the expire time in the units associated with the timer
66754904d2aSAlex Bligh  *
66840daca54SAlex Bligh  * Modify a timer to expiry at @expire_time, taking into
66940daca54SAlex Bligh  * account the scale associated with the timer.
670978f2205SStefan Hajnoczi  *
671978f2205SStefan Hajnoczi  * This function is thread-safe but the timer and its timer list must not be
672978f2205SStefan Hajnoczi  * freed while this function is running.
67354904d2aSAlex Bligh  */
67440daca54SAlex Bligh void timer_mod(QEMUTimer *ts, int64_t expire_timer);
675ff83c66eSAlex Bligh 
676f9a976b7SAlex Bligh /**
677add40e97SPaolo Bonzini  * timer_mod_anticipate:
678add40e97SPaolo Bonzini  * @ts: the timer
679420bd566SPhilippe Mathieu-Daudé  * @expire_time: the expire time in the units associated with the timer
680add40e97SPaolo Bonzini  *
681add40e97SPaolo Bonzini  * Modify a timer to expire at @expire_time or the current time, whichever
682add40e97SPaolo Bonzini  * comes earlier, taking into account the scale associated with the timer.
683add40e97SPaolo Bonzini  *
684add40e97SPaolo Bonzini  * This function is thread-safe but the timer and its timer list must not be
685add40e97SPaolo Bonzini  * freed while this function is running.
686add40e97SPaolo Bonzini  */
687add40e97SPaolo Bonzini void timer_mod_anticipate(QEMUTimer *ts, int64_t expire_time);
688add40e97SPaolo Bonzini 
689add40e97SPaolo Bonzini /**
69054904d2aSAlex Bligh  * timer_pending:
69140daca54SAlex Bligh  * @ts: the timer
69254904d2aSAlex Bligh  *
69354904d2aSAlex Bligh  * Determines whether a timer is pending (i.e. is on the
69454904d2aSAlex Bligh  * active list of timers, whether or not it has not yet expired).
69554904d2aSAlex Bligh  *
69654904d2aSAlex Bligh  * Returns: true if the timer is pending
69754904d2aSAlex Bligh  */
69854904d2aSAlex Bligh bool timer_pending(QEMUTimer *ts);
69954904d2aSAlex Bligh 
70054904d2aSAlex Bligh /**
70154904d2aSAlex Bligh  * timer_expired:
70240daca54SAlex Bligh  * @ts: the timer
70304ecbb78SCao jin  * @current_time: the current time
70454904d2aSAlex Bligh  *
70554904d2aSAlex Bligh  * Determines whether a timer has expired.
70654904d2aSAlex Bligh  *
70754904d2aSAlex Bligh  * Returns: true if the timer has expired
70854904d2aSAlex Bligh  */
70954904d2aSAlex Bligh bool timer_expired(QEMUTimer *timer_head, int64_t current_time);
71054904d2aSAlex Bligh 
71154904d2aSAlex Bligh /**
71254904d2aSAlex Bligh  * timer_expire_time_ns:
71340daca54SAlex Bligh  * @ts: the timer
71454904d2aSAlex Bligh  *
71540daca54SAlex Bligh  * Determine the expiry time of a timer
71654904d2aSAlex Bligh  *
71740daca54SAlex Bligh  * Returns: the expiry time in nanoseconds
71854904d2aSAlex Bligh  */
71954904d2aSAlex Bligh uint64_t timer_expire_time_ns(QEMUTimer *ts);
72054904d2aSAlex Bligh 
72154904d2aSAlex Bligh /**
72240daca54SAlex Bligh  * timer_get:
72340daca54SAlex Bligh  * @f: the file
72440daca54SAlex Bligh  * @ts: the timer
725f9a976b7SAlex Bligh  *
72640daca54SAlex Bligh  * Read a timer @ts from a file @f
727f9a976b7SAlex Bligh  */
72840daca54SAlex Bligh void timer_get(QEMUFile *f, QEMUTimer *ts);
729f9a976b7SAlex Bligh 
730f9a976b7SAlex Bligh /**
73140daca54SAlex Bligh  * timer_put:
73240daca54SAlex Bligh  * @f: the file
73340daca54SAlex Bligh  * @ts: the timer
734f9a976b7SAlex Bligh  */
73540daca54SAlex Bligh void timer_put(QEMUFile *f, QEMUTimer *ts);
73640daca54SAlex Bligh 
73740daca54SAlex Bligh /*
73840daca54SAlex Bligh  * General utility functions
73940daca54SAlex Bligh  */
740f9a976b7SAlex Bligh 
74154904d2aSAlex Bligh /**
74240daca54SAlex Bligh  * qemu_timeout_ns_to_ms:
74340daca54SAlex Bligh  * @ns: nanosecond timeout value
74454904d2aSAlex Bligh  *
74540daca54SAlex Bligh  * Convert a nanosecond timeout value (or -1) to
74640daca54SAlex Bligh  * a millisecond value (or -1), always rounding up.
74740daca54SAlex Bligh  *
74840daca54SAlex Bligh  * Returns: millisecond timeout value
74954904d2aSAlex Bligh  */
75040daca54SAlex Bligh int qemu_timeout_ns_to_ms(int64_t ns);
75154904d2aSAlex Bligh 
75240daca54SAlex Bligh /**
75340daca54SAlex Bligh  * qemu_poll_ns:
75440daca54SAlex Bligh  * @fds: Array of file descriptors
75540daca54SAlex Bligh  * @nfds: number of file descriptors
75640daca54SAlex Bligh  * @timeout: timeout in nanoseconds
75740daca54SAlex Bligh  *
75840daca54SAlex Bligh  * Perform a poll like g_poll but with a timeout in nanoseconds.
75940daca54SAlex Bligh  * See g_poll documentation for further details.
76040daca54SAlex Bligh  *
76140daca54SAlex Bligh  * Returns: number of fds ready
76240daca54SAlex Bligh  */
76340daca54SAlex Bligh int qemu_poll_ns(GPollFD *fds, guint nfds, int64_t timeout);
7641de7afc9SPaolo Bonzini 
76502a03a9fSAlex Bligh /**
76602a03a9fSAlex Bligh  * qemu_soonest_timeout:
76702a03a9fSAlex Bligh  * @timeout1: first timeout in nanoseconds (or -1 for infinite)
76802a03a9fSAlex Bligh  * @timeout2: second timeout in nanoseconds (or -1 for infinite)
76902a03a9fSAlex Bligh  *
77002a03a9fSAlex Bligh  * Calculates the soonest of two timeout values. -1 means infinite, which
77102a03a9fSAlex Bligh  * is later than any other value.
77202a03a9fSAlex Bligh  *
77302a03a9fSAlex Bligh  * Returns: soonest timeout value in nanoseconds (or -1 for infinite)
77402a03a9fSAlex Bligh  */
qemu_soonest_timeout(int64_t timeout1,int64_t timeout2)77502a03a9fSAlex Bligh static inline int64_t qemu_soonest_timeout(int64_t timeout1, int64_t timeout2)
77602a03a9fSAlex Bligh {
77702a03a9fSAlex Bligh     /* we can abuse the fact that -1 (which means infinite) is a maximal
77802a03a9fSAlex Bligh      * value when cast to unsigned. As this is disgusting, it's kept in
77902a03a9fSAlex Bligh      * one inline function.
78002a03a9fSAlex Bligh      */
78102a03a9fSAlex Bligh     return ((uint64_t) timeout1 < (uint64_t) timeout2) ? timeout1 : timeout2;
78202a03a9fSAlex Bligh }
78302a03a9fSAlex Bligh 
784ff83c66eSAlex Bligh /**
78540daca54SAlex Bligh  * initclocks:
78640daca54SAlex Bligh  *
78740daca54SAlex Bligh  * Initialise the clock & timer infrastructure
78840daca54SAlex Bligh  */
7893f53bc61SPaolo Bonzini void init_clocks(QEMUTimerListNotifyCB *notify_cb);
79040daca54SAlex Bligh 
get_max_clock_jump(void)791fb1a3a05SPaul Donohue static inline int64_t get_max_clock_jump(void)
792fb1a3a05SPaul Donohue {
793fb1a3a05SPaul Donohue     /* This should be small enough to prevent excessive interrupts from being
794fb1a3a05SPaul Donohue      * generated by the RTC on clock jumps, but large enough to avoid frequent
795fb1a3a05SPaul Donohue      * unnecessary resets in idle VMs.
796fb1a3a05SPaul Donohue      */
79773bcb24dSRutuja Shah     return 60 * NANOSECONDS_PER_SECOND;
798fb1a3a05SPaul Donohue }
799fb1a3a05SPaul Donohue 
80040daca54SAlex Bligh /*
80140daca54SAlex Bligh  * Low level clock functions
80240daca54SAlex Bligh  */
8031de7afc9SPaolo Bonzini 
8043224e878SCao jin /* get host real time in nanosecond */
get_clock_realtime(void)8051de7afc9SPaolo Bonzini static inline int64_t get_clock_realtime(void)
8061de7afc9SPaolo Bonzini {
8071de7afc9SPaolo Bonzini     struct timeval tv;
8081de7afc9SPaolo Bonzini 
8091de7afc9SPaolo Bonzini     gettimeofday(&tv, NULL);
8101de7afc9SPaolo Bonzini     return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000);
8111de7afc9SPaolo Bonzini }
8121de7afc9SPaolo Bonzini 
8134d834039SKeith Packard extern int64_t clock_start;
8144d834039SKeith Packard 
8151de7afc9SPaolo Bonzini /* Warning: don't insert tracepoints into these functions, they are
8161de7afc9SPaolo Bonzini    also used by simpletrace backend and tracepoints would cause
8171de7afc9SPaolo Bonzini    an infinite recursion! */
8181de7afc9SPaolo Bonzini #ifdef _WIN32
8191de7afc9SPaolo Bonzini extern int64_t clock_freq;
8201de7afc9SPaolo Bonzini 
get_clock(void)8211de7afc9SPaolo Bonzini static inline int64_t get_clock(void)
8221de7afc9SPaolo Bonzini {
8231de7afc9SPaolo Bonzini     LARGE_INTEGER ti;
8241de7afc9SPaolo Bonzini     QueryPerformanceCounter(&ti);
82573bcb24dSRutuja Shah     return muldiv64(ti.QuadPart, NANOSECONDS_PER_SECOND, clock_freq);
8261de7afc9SPaolo Bonzini }
8271de7afc9SPaolo Bonzini 
8281de7afc9SPaolo Bonzini #else
8291de7afc9SPaolo Bonzini 
8301de7afc9SPaolo Bonzini extern int use_rt_clock;
8311de7afc9SPaolo Bonzini 
get_clock(void)8321de7afc9SPaolo Bonzini static inline int64_t get_clock(void)
8331de7afc9SPaolo Bonzini {
8341de7afc9SPaolo Bonzini     if (use_rt_clock) {
8351de7afc9SPaolo Bonzini         struct timespec ts;
8361de7afc9SPaolo Bonzini         clock_gettime(CLOCK_MONOTONIC, &ts);
8371de7afc9SPaolo Bonzini         return ts.tv_sec * 1000000000LL + ts.tv_nsec;
838a284f798SPeter Maydell     } else {
8391de7afc9SPaolo Bonzini         /* XXX: using gettimeofday leads to problems if the date
8401de7afc9SPaolo Bonzini            changes, so it should be avoided. */
8411de7afc9SPaolo Bonzini         return get_clock_realtime();
8421de7afc9SPaolo Bonzini     }
8431de7afc9SPaolo Bonzini }
8441de7afc9SPaolo Bonzini #endif
8451de7afc9SPaolo Bonzini 
8461de7afc9SPaolo Bonzini /*******************************************/
8471de7afc9SPaolo Bonzini /* host CPU ticks (if available) */
8481de7afc9SPaolo Bonzini 
8491de7afc9SPaolo Bonzini #if defined(_ARCH_PPC)
8501de7afc9SPaolo Bonzini 
cpu_get_host_ticks(void)8514a7428c5SChristopher Covington static inline int64_t cpu_get_host_ticks(void)
8521de7afc9SPaolo Bonzini {
8531de7afc9SPaolo Bonzini     int64_t retval;
8541de7afc9SPaolo Bonzini #ifdef _ARCH_PPC64
8551de7afc9SPaolo Bonzini     /* This reads timebase in one 64bit go and includes Cell workaround from:
8561de7afc9SPaolo Bonzini        http://ozlabs.org/pipermail/linuxppc-dev/2006-October/027052.html
8571de7afc9SPaolo Bonzini     */
8581de7afc9SPaolo Bonzini     __asm__ __volatile__ ("mftb    %0\n\t"
8591de7afc9SPaolo Bonzini                           "cmpwi   %0,0\n\t"
8601de7afc9SPaolo Bonzini                           "beq-    $-8"
8611de7afc9SPaolo Bonzini                           : "=r" (retval));
8621de7afc9SPaolo Bonzini #else
8631de7afc9SPaolo Bonzini     /* http://ozlabs.org/pipermail/linuxppc-dev/1999-October/003889.html */
8641de7afc9SPaolo Bonzini     unsigned long junk;
8651de7afc9SPaolo Bonzini     __asm__ __volatile__ ("mfspr   %1,269\n\t"  /* mftbu */
8661de7afc9SPaolo Bonzini                           "mfspr   %L0,268\n\t" /* mftb */
8671de7afc9SPaolo Bonzini                           "mfspr   %0,269\n\t"  /* mftbu */
8681de7afc9SPaolo Bonzini                           "cmpw    %0,%1\n\t"
8691de7afc9SPaolo Bonzini                           "bne     $-16"
8701de7afc9SPaolo Bonzini                           : "=r" (retval), "=r" (junk));
8711de7afc9SPaolo Bonzini #endif
8721de7afc9SPaolo Bonzini     return retval;
8731de7afc9SPaolo Bonzini }
8741de7afc9SPaolo Bonzini 
8751de7afc9SPaolo Bonzini #elif defined(__i386__)
8761de7afc9SPaolo Bonzini 
cpu_get_host_ticks(void)8774a7428c5SChristopher Covington static inline int64_t cpu_get_host_ticks(void)
8781de7afc9SPaolo Bonzini {
8791de7afc9SPaolo Bonzini     int64_t val;
8801de7afc9SPaolo Bonzini     asm volatile ("rdtsc" : "=A" (val));
8811de7afc9SPaolo Bonzini     return val;
8821de7afc9SPaolo Bonzini }
8831de7afc9SPaolo Bonzini 
8841de7afc9SPaolo Bonzini #elif defined(__x86_64__)
8851de7afc9SPaolo Bonzini 
cpu_get_host_ticks(void)8864a7428c5SChristopher Covington static inline int64_t cpu_get_host_ticks(void)
8871de7afc9SPaolo Bonzini {
8881de7afc9SPaolo Bonzini     uint32_t low,high;
8891de7afc9SPaolo Bonzini     int64_t val;
8901de7afc9SPaolo Bonzini     asm volatile("rdtsc" : "=a" (low), "=d" (high));
8911de7afc9SPaolo Bonzini     val = high;
8921de7afc9SPaolo Bonzini     val <<= 32;
8931de7afc9SPaolo Bonzini     val |= low;
8941de7afc9SPaolo Bonzini     return val;
8951de7afc9SPaolo Bonzini }
8961de7afc9SPaolo Bonzini 
8971de7afc9SPaolo Bonzini #elif defined(__hppa__)
8981de7afc9SPaolo Bonzini 
cpu_get_host_ticks(void)8994a7428c5SChristopher Covington static inline int64_t cpu_get_host_ticks(void)
9001de7afc9SPaolo Bonzini {
9011de7afc9SPaolo Bonzini     int val;
9021de7afc9SPaolo Bonzini     asm volatile ("mfctl %%cr16, %0" : "=r"(val));
9031de7afc9SPaolo Bonzini     return val;
9041de7afc9SPaolo Bonzini }
9051de7afc9SPaolo Bonzini 
9061de7afc9SPaolo Bonzini #elif defined(__s390__)
9071de7afc9SPaolo Bonzini 
cpu_get_host_ticks(void)9084a7428c5SChristopher Covington static inline int64_t cpu_get_host_ticks(void)
9091de7afc9SPaolo Bonzini {
9101de7afc9SPaolo Bonzini     int64_t val;
9111de7afc9SPaolo Bonzini     asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc");
9121de7afc9SPaolo Bonzini     return val;
9131de7afc9SPaolo Bonzini }
9141de7afc9SPaolo Bonzini 
9151de7afc9SPaolo Bonzini #elif defined(__sparc__)
9161de7afc9SPaolo Bonzini 
cpu_get_host_ticks(void)9174a7428c5SChristopher Covington static inline int64_t cpu_get_host_ticks (void)
9181de7afc9SPaolo Bonzini {
9191de7afc9SPaolo Bonzini #if defined(_LP64)
9201de7afc9SPaolo Bonzini     uint64_t        rval;
9211de7afc9SPaolo Bonzini     asm volatile("rd %%tick,%0" : "=r"(rval));
9221de7afc9SPaolo Bonzini     return rval;
9231de7afc9SPaolo Bonzini #else
9241de7afc9SPaolo Bonzini     /* We need an %o or %g register for this.  For recent enough gcc
9251de7afc9SPaolo Bonzini        there is an "h" constraint for that.  Don't bother with that.  */
9261de7afc9SPaolo Bonzini     union {
9271de7afc9SPaolo Bonzini         uint64_t i64;
9281de7afc9SPaolo Bonzini         struct {
9291de7afc9SPaolo Bonzini             uint32_t high;
9301de7afc9SPaolo Bonzini             uint32_t low;
9311de7afc9SPaolo Bonzini         }       i32;
9321de7afc9SPaolo Bonzini     } rval;
9331de7afc9SPaolo Bonzini     asm volatile("rd %%tick,%%g1; srlx %%g1,32,%0; mov %%g1,%1"
9341de7afc9SPaolo Bonzini                  : "=r"(rval.i32.high), "=r"(rval.i32.low) : : "g1");
9351de7afc9SPaolo Bonzini     return rval.i64;
9361de7afc9SPaolo Bonzini #endif
9371de7afc9SPaolo Bonzini }
9381de7afc9SPaolo Bonzini 
9391de7afc9SPaolo Bonzini #elif defined(__mips__) && \
9401de7afc9SPaolo Bonzini     ((defined(__mips_isa_rev) && __mips_isa_rev >= 2) || defined(__linux__))
9411de7afc9SPaolo Bonzini /*
9421de7afc9SPaolo Bonzini  * binutils wants to use rdhwr only on mips32r2
9431de7afc9SPaolo Bonzini  * but as linux kernel emulate it, it's fine
9441de7afc9SPaolo Bonzini  * to use it.
9451de7afc9SPaolo Bonzini  *
9461de7afc9SPaolo Bonzini  */
9471de7afc9SPaolo Bonzini #define MIPS_RDHWR(rd, value) {                         \
9481de7afc9SPaolo Bonzini         __asm__ __volatile__ (".set   push\n\t"         \
9491de7afc9SPaolo Bonzini                               ".set mips32r2\n\t"       \
9501de7afc9SPaolo Bonzini                               "rdhwr  %0, "rd"\n\t"     \
9511de7afc9SPaolo Bonzini                               ".set   pop"              \
9521de7afc9SPaolo Bonzini                               : "=r" (value));          \
9531de7afc9SPaolo Bonzini     }
9541de7afc9SPaolo Bonzini 
cpu_get_host_ticks(void)9554a7428c5SChristopher Covington static inline int64_t cpu_get_host_ticks(void)
9561de7afc9SPaolo Bonzini {
9571de7afc9SPaolo Bonzini     /* On kernels >= 2.6.25 rdhwr <reg>, $2 and $3 are emulated */
9581de7afc9SPaolo Bonzini     uint32_t count;
9591de7afc9SPaolo Bonzini     static uint32_t cyc_per_count = 0;
9601de7afc9SPaolo Bonzini 
9611de7afc9SPaolo Bonzini     if (!cyc_per_count) {
9621de7afc9SPaolo Bonzini         MIPS_RDHWR("$3", cyc_per_count);
9631de7afc9SPaolo Bonzini     }
9641de7afc9SPaolo Bonzini 
9651de7afc9SPaolo Bonzini     MIPS_RDHWR("$2", count);
9661de7afc9SPaolo Bonzini     return (int64_t)(count * cyc_per_count);
9671de7afc9SPaolo Bonzini }
9681de7afc9SPaolo Bonzini 
9691de7afc9SPaolo Bonzini #elif defined(__alpha__)
9701de7afc9SPaolo Bonzini 
cpu_get_host_ticks(void)9714a7428c5SChristopher Covington static inline int64_t cpu_get_host_ticks(void)
9721de7afc9SPaolo Bonzini {
9731de7afc9SPaolo Bonzini     uint64_t cc;
9741de7afc9SPaolo Bonzini     uint32_t cur, ofs;
9751de7afc9SPaolo Bonzini 
9761de7afc9SPaolo Bonzini     asm volatile("rpcc %0" : "=r"(cc));
9771de7afc9SPaolo Bonzini     cur = cc;
9781de7afc9SPaolo Bonzini     ofs = cc >> 32;
9791de7afc9SPaolo Bonzini     return cur - ofs;
9801de7afc9SPaolo Bonzini }
9811de7afc9SPaolo Bonzini 
982*e8eed838SLIU Zhiwei #elif defined(__riscv) && __riscv_xlen == 32
cpu_get_host_ticks(void)983*e8eed838SLIU Zhiwei static inline int64_t cpu_get_host_ticks(void)
984*e8eed838SLIU Zhiwei {
985*e8eed838SLIU Zhiwei     uint32_t lo, hi, tmph;
986*e8eed838SLIU Zhiwei     do {
987*e8eed838SLIU Zhiwei         asm volatile("RDTIMEH %0\n\t"
988*e8eed838SLIU Zhiwei                      "RDTIME %1\n\t"
989*e8eed838SLIU Zhiwei                      "RDTIMEH %2"
990*e8eed838SLIU Zhiwei                      : "=r"(hi), "=r"(lo), "=r"(tmph));
991*e8eed838SLIU Zhiwei     } while (unlikely(tmph != hi));
992*e8eed838SLIU Zhiwei     return lo | (uint64_t)hi << 32;
993*e8eed838SLIU Zhiwei }
994*e8eed838SLIU Zhiwei 
995*e8eed838SLIU Zhiwei #elif defined(__riscv) && __riscv_xlen > 32
cpu_get_host_ticks(void)996*e8eed838SLIU Zhiwei static inline int64_t cpu_get_host_ticks(void)
997*e8eed838SLIU Zhiwei {
998*e8eed838SLIU Zhiwei     int64_t val;
999*e8eed838SLIU Zhiwei 
1000*e8eed838SLIU Zhiwei     asm volatile("RDTIME %0" : "=r"(val));
1001*e8eed838SLIU Zhiwei     return val;
1002*e8eed838SLIU Zhiwei }
1003*e8eed838SLIU Zhiwei 
10041de7afc9SPaolo Bonzini #else
10051de7afc9SPaolo Bonzini /* The host CPU doesn't have an easily accessible cycle counter.
10061de7afc9SPaolo Bonzini    Just return a monotonically increasing value.  This will be
10071de7afc9SPaolo Bonzini    totally wrong, but hopefully better than nothing.  */
cpu_get_host_ticks(void)10084a7428c5SChristopher Covington static inline int64_t cpu_get_host_ticks(void)
10091de7afc9SPaolo Bonzini {
1010d1bb099fSPranith Kumar     return get_clock();
10111de7afc9SPaolo Bonzini }
10121de7afc9SPaolo Bonzini #endif
10131de7afc9SPaolo Bonzini 
10141de7afc9SPaolo Bonzini #endif
1015