root / include / qemu / timer.h @ 7bf8fbde
History | View | Annotate | Download (26.4 kB)
1 |
#ifndef QEMU_TIMER_H
|
---|---|
2 |
#define QEMU_TIMER_H
|
3 |
|
4 |
#include "qemu/typedefs.h" |
5 |
#include "qemu-common.h" |
6 |
#include "qemu/notify.h" |
7 |
|
8 |
/* timers */
|
9 |
|
10 |
#define SCALE_MS 1000000 |
11 |
#define SCALE_US 1000 |
12 |
#define SCALE_NS 1 |
13 |
|
14 |
/**
|
15 |
* QEMUClockType:
|
16 |
*
|
17 |
* The following clock types are available:
|
18 |
*
|
19 |
* @QEMU_CLOCK_REALTIME: Real time clock
|
20 |
*
|
21 |
* The real time clock should be used only for stuff which does not
|
22 |
* change the virtual machine state, as it is run even if the virtual
|
23 |
* machine is stopped. The real time clock has a frequency of 1000
|
24 |
* Hz.
|
25 |
*
|
26 |
* @QEMU_CLOCK_VIRTUAL: virtual clock
|
27 |
*
|
28 |
* The virtual clock is only run during the emulation. It is stopped
|
29 |
* when the virtual machine is stopped. Virtual timers use a high
|
30 |
* precision clock, usually cpu cycles (use ticks_per_sec).
|
31 |
*
|
32 |
* @QEMU_CLOCK_HOST: host clock
|
33 |
*
|
34 |
* The host clock should be use for device models that emulate accurate
|
35 |
* real time sources. It will continue to run when the virtual machine
|
36 |
* is suspended, and it will reflect system time changes the host may
|
37 |
* undergo (e.g. due to NTP). The host clock has the same precision as
|
38 |
* the virtual clock.
|
39 |
*/
|
40 |
|
41 |
typedef enum { |
42 |
QEMU_CLOCK_REALTIME = 0,
|
43 |
QEMU_CLOCK_VIRTUAL = 1,
|
44 |
QEMU_CLOCK_HOST = 2,
|
45 |
QEMU_CLOCK_MAX |
46 |
} QEMUClockType; |
47 |
|
48 |
typedef struct QEMUClock QEMUClock; |
49 |
typedef struct QEMUTimerList QEMUTimerList; |
50 |
|
51 |
struct QEMUTimerListGroup {
|
52 |
QEMUTimerList *tl[QEMU_CLOCK_MAX]; |
53 |
}; |
54 |
|
55 |
typedef void QEMUTimerCB(void *opaque); |
56 |
typedef void QEMUTimerListNotifyCB(void *opaque); |
57 |
|
58 |
struct QEMUTimer {
|
59 |
int64_t expire_time; /* in nanoseconds */
|
60 |
QEMUTimerList *timer_list; |
61 |
QEMUTimerCB *cb; |
62 |
void *opaque;
|
63 |
QEMUTimer *next; |
64 |
int scale;
|
65 |
}; |
66 |
|
67 |
extern QEMUTimerListGroup main_loop_tlg;
|
68 |
|
69 |
/*
|
70 |
* QEMUClock & QEMUClockType
|
71 |
*/
|
72 |
|
73 |
/**
|
74 |
* qemu_clock_ptr:
|
75 |
* @type: type of clock
|
76 |
*
|
77 |
* Translate a clock type into a pointer to QEMUClock object.
|
78 |
*
|
79 |
* Returns: a pointer to the QEMUClock object
|
80 |
*/
|
81 |
QEMUClock *qemu_clock_ptr(QEMUClockType type); |
82 |
|
83 |
/**
|
84 |
* qemu_clock_get_ns;
|
85 |
* @type: the clock type
|
86 |
*
|
87 |
* Get the nanosecond value of a clock with
|
88 |
* type @type
|
89 |
*
|
90 |
* Returns: the clock value in nanoseconds
|
91 |
*/
|
92 |
int64_t qemu_clock_get_ns(QEMUClockType type); |
93 |
|
94 |
/**
|
95 |
* qemu_clock_get_ms;
|
96 |
* @type: the clock type
|
97 |
*
|
98 |
* Get the millisecond value of a clock with
|
99 |
* type @type
|
100 |
*
|
101 |
* Returns: the clock value in milliseconds
|
102 |
*/
|
103 |
static inline int64_t qemu_clock_get_ms(QEMUClockType type) |
104 |
{ |
105 |
return qemu_clock_get_ns(type) / SCALE_MS;
|
106 |
} |
107 |
|
108 |
/**
|
109 |
* qemu_clock_get_us;
|
110 |
* @type: the clock type
|
111 |
*
|
112 |
* Get the microsecond value of a clock with
|
113 |
* type @type
|
114 |
*
|
115 |
* Returns: the clock value in microseconds
|
116 |
*/
|
117 |
static inline int64_t qemu_clock_get_us(QEMUClockType type) |
118 |
{ |
119 |
return qemu_clock_get_ns(type) / SCALE_US;
|
120 |
} |
121 |
|
122 |
/**
|
123 |
* qemu_clock_has_timers:
|
124 |
* @type: the clock type
|
125 |
*
|
126 |
* Determines whether a clock's default timer list
|
127 |
* has timers attached
|
128 |
*
|
129 |
* Returns: true if the clock's default timer list
|
130 |
* has timers attached
|
131 |
*/
|
132 |
bool qemu_clock_has_timers(QEMUClockType type);
|
133 |
|
134 |
/**
|
135 |
* qemu_clock_expired:
|
136 |
* @type: the clock type
|
137 |
*
|
138 |
* Determines whether a clock's default timer list
|
139 |
* has an expired clock.
|
140 |
*
|
141 |
* Returns: true if the clock's default timer list has
|
142 |
* an expired timer
|
143 |
*/
|
144 |
bool qemu_clock_expired(QEMUClockType type);
|
145 |
|
146 |
/**
|
147 |
* qemu_clock_use_for_deadline:
|
148 |
* @type: the clock type
|
149 |
*
|
150 |
* Determine whether a clock should be used for deadline
|
151 |
* calculations. Some clocks, for instance vm_clock with
|
152 |
* use_icount set, do not count in nanoseconds. Such clocks
|
153 |
* are not used for deadline calculations, and are presumed
|
154 |
* to interrupt any poll using qemu_notify/aio_notify
|
155 |
* etc.
|
156 |
*
|
157 |
* Returns: true if the clock runs in nanoseconds and
|
158 |
* should be used for a deadline.
|
159 |
*/
|
160 |
bool qemu_clock_use_for_deadline(QEMUClockType type);
|
161 |
|
162 |
/**
|
163 |
* qemu_clock_deadline_ns_all:
|
164 |
* @type: the clock type
|
165 |
*
|
166 |
* Calculate the deadline across all timer lists associated
|
167 |
* with a clock (as opposed to just the default one)
|
168 |
* in nanoseconds, or -1 if no timer is set to expire.
|
169 |
*
|
170 |
* Returns: time until expiry in nanoseconds or -1
|
171 |
*/
|
172 |
int64_t qemu_clock_deadline_ns_all(QEMUClockType type); |
173 |
|
174 |
/**
|
175 |
* qemu_clock_get_main_loop_timerlist:
|
176 |
* @type: the clock type
|
177 |
*
|
178 |
* Return the default timer list assocatiated with a clock.
|
179 |
*
|
180 |
* Returns: the default timer list
|
181 |
*/
|
182 |
QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClockType type); |
183 |
|
184 |
/**
|
185 |
* qemu_clock_nofify:
|
186 |
* @type: the clock type
|
187 |
*
|
188 |
* Call the notifier callback connected with the default timer
|
189 |
* list linked to the clock, or qemu_notify() if none.
|
190 |
*/
|
191 |
void qemu_clock_notify(QEMUClockType type);
|
192 |
|
193 |
/**
|
194 |
* qemu_clock_enable:
|
195 |
* @type: the clock type
|
196 |
* @enabled: true to enable, false to disable
|
197 |
*
|
198 |
* Enable or disable a clock
|
199 |
*/
|
200 |
void qemu_clock_enable(QEMUClockType type, bool enabled); |
201 |
|
202 |
/**
|
203 |
* qemu_clock_warp:
|
204 |
* @type: the clock type
|
205 |
*
|
206 |
* Warp a clock to a new value
|
207 |
*/
|
208 |
void qemu_clock_warp(QEMUClockType type);
|
209 |
|
210 |
/**
|
211 |
* qemu_clock_register_reset_notifier:
|
212 |
* @type: the clock type
|
213 |
* @notifier: the notifier function
|
214 |
*
|
215 |
* Register a notifier function to call when the clock
|
216 |
* concerned is reset.
|
217 |
*/
|
218 |
void qemu_clock_register_reset_notifier(QEMUClockType type,
|
219 |
Notifier *notifier); |
220 |
|
221 |
/**
|
222 |
* qemu_clock_unregister_reset_notifier:
|
223 |
* @type: the clock type
|
224 |
* @notifier: the notifier function
|
225 |
*
|
226 |
* Unregister a notifier function to call when the clock
|
227 |
* concerned is reset.
|
228 |
*/
|
229 |
void qemu_clock_unregister_reset_notifier(QEMUClockType type,
|
230 |
Notifier *notifier); |
231 |
|
232 |
/**
|
233 |
* qemu_clock_run_timers:
|
234 |
* @type: clock on which to operate
|
235 |
*
|
236 |
* Run all the timers associated with the default timer list
|
237 |
* of a clock.
|
238 |
*
|
239 |
* Returns: true if any timer ran.
|
240 |
*/
|
241 |
bool qemu_clock_run_timers(QEMUClockType type);
|
242 |
|
243 |
/**
|
244 |
* qemu_clock_run_all_timers:
|
245 |
*
|
246 |
* Run all the timers associated with the default timer list
|
247 |
* of every clock.
|
248 |
*
|
249 |
* Returns: true if any timer ran.
|
250 |
*/
|
251 |
bool qemu_clock_run_all_timers(void); |
252 |
|
253 |
/*
|
254 |
* QEMUTimerList
|
255 |
*/
|
256 |
|
257 |
/**
|
258 |
* timerlist_new:
|
259 |
* @type: the clock type to associate with the timerlist
|
260 |
* @cb: the callback to call on notification
|
261 |
* @opaque: the opaque pointer to pass to the callback
|
262 |
*
|
263 |
* Create a new timerlist associated with the clock of
|
264 |
* type @type.
|
265 |
*
|
266 |
* Returns: a pointer to the QEMUTimerList created
|
267 |
*/
|
268 |
QEMUTimerList *timerlist_new(QEMUClockType type, |
269 |
QEMUTimerListNotifyCB *cb, void *opaque);
|
270 |
|
271 |
/**
|
272 |
* timerlist_free:
|
273 |
* @timer_list: the timer list to free
|
274 |
*
|
275 |
* Frees a timer_list. It must have no active timers.
|
276 |
*/
|
277 |
void timerlist_free(QEMUTimerList *timer_list);
|
278 |
|
279 |
/**
|
280 |
* timerlist_has_timers:
|
281 |
* @timer_list: the timer list to operate on
|
282 |
*
|
283 |
* Determine whether a timer list has active timers
|
284 |
*
|
285 |
* Returns: true if the timer list has timers.
|
286 |
*/
|
287 |
bool timerlist_has_timers(QEMUTimerList *timer_list);
|
288 |
|
289 |
/**
|
290 |
* timerlist_expired:
|
291 |
* @timer_list: the timer list to operate on
|
292 |
*
|
293 |
* Determine whether a timer list has any timers which
|
294 |
* are expired.
|
295 |
*
|
296 |
* Returns: true if the timer list has timers which
|
297 |
* have expired.
|
298 |
*/
|
299 |
bool timerlist_expired(QEMUTimerList *timer_list);
|
300 |
|
301 |
/**
|
302 |
* timerlist_deadline_ns:
|
303 |
* @timer_list: the timer list to operate on
|
304 |
*
|
305 |
* Determine the deadline for a timer_list, i.e.
|
306 |
* the number of nanoseconds until the first timer
|
307 |
* expires. Return -1 if there are no timers.
|
308 |
*
|
309 |
* Returns: the number of nanoseconds until the earliest
|
310 |
* timer expires -1 if none
|
311 |
*/
|
312 |
int64_t timerlist_deadline_ns(QEMUTimerList *timer_list); |
313 |
|
314 |
/**
|
315 |
* timerlist_get_clock:
|
316 |
* @timer_list: the timer list to operate on
|
317 |
*
|
318 |
* Determine the clock type associated with a timer list.
|
319 |
*
|
320 |
* Returns: the clock type associated with the
|
321 |
* timer list.
|
322 |
*/
|
323 |
QEMUClockType timerlist_get_clock(QEMUTimerList *timer_list); |
324 |
|
325 |
/**
|
326 |
* timerlist_run_timers:
|
327 |
* @timer_list: the timer list to use
|
328 |
*
|
329 |
* Call all expired timers associated with the timer list.
|
330 |
*
|
331 |
* Returns: true if any timer expired
|
332 |
*/
|
333 |
bool timerlist_run_timers(QEMUTimerList *timer_list);
|
334 |
|
335 |
/**
|
336 |
* timerlist_notify:
|
337 |
* @timer_list: the timer list to use
|
338 |
*
|
339 |
* call the notifier callback associated with the timer list.
|
340 |
*/
|
341 |
void timerlist_notify(QEMUTimerList *timer_list);
|
342 |
|
343 |
/*
|
344 |
* QEMUTimerListGroup
|
345 |
*/
|
346 |
|
347 |
/**
|
348 |
* timerlistgroup_init:
|
349 |
* @tlg: the timer list group
|
350 |
* @cb: the callback to call when a notify is required
|
351 |
* @opaque: the opaque pointer to be passed to the callback.
|
352 |
*
|
353 |
* Initialise a timer list group. This must already be
|
354 |
* allocated in memory and zeroed. The notifier callback is
|
355 |
* called whenever a clock in the timer list group is
|
356 |
* reenabled or whenever a timer associated with any timer
|
357 |
* list is modified. If @cb is specified as null, qemu_notify()
|
358 |
* is used instead.
|
359 |
*/
|
360 |
void timerlistgroup_init(QEMUTimerListGroup *tlg,
|
361 |
QEMUTimerListNotifyCB *cb, void *opaque);
|
362 |
|
363 |
/**
|
364 |
* timerlistgroup_deinit:
|
365 |
* @tlg: the timer list group
|
366 |
*
|
367 |
* Deinitialise a timer list group. This must already be
|
368 |
* initialised. Note the memory is not freed.
|
369 |
*/
|
370 |
void timerlistgroup_deinit(QEMUTimerListGroup *tlg);
|
371 |
|
372 |
/**
|
373 |
* timerlistgroup_run_timers:
|
374 |
* @tlg: the timer list group
|
375 |
*
|
376 |
* Run the timers associated with a timer list group.
|
377 |
* This will run timers on multiple clocks.
|
378 |
*
|
379 |
* Returns: true if any timer callback ran
|
380 |
*/
|
381 |
bool timerlistgroup_run_timers(QEMUTimerListGroup *tlg);
|
382 |
|
383 |
/**
|
384 |
* timerlistgroup_deadline_ns:
|
385 |
* @tlg: the timer list group
|
386 |
*
|
387 |
* Determine the deadline of the soonest timer to
|
388 |
* expire associated with any timer list linked to
|
389 |
* the timer list group. Only clocks suitable for
|
390 |
* deadline calculation are included.
|
391 |
*
|
392 |
* Returns: the deadline in nanoseconds or -1 if no
|
393 |
* timers are to expire.
|
394 |
*/
|
395 |
int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg); |
396 |
|
397 |
/*
|
398 |
* QEMUTimer
|
399 |
*/
|
400 |
|
401 |
/**
|
402 |
* timer_init:
|
403 |
* @ts: the timer to be initialised
|
404 |
* @timer_list: the timer list to attach the timer to
|
405 |
* @scale: the scale value for the tiemr
|
406 |
* @cb: the callback to be called when the timer expires
|
407 |
* @opaque: the opaque pointer to be passed to the callback
|
408 |
*
|
409 |
* Initialise a new timer and associate it with @timer_list.
|
410 |
* The caller is responsible for allocating the memory.
|
411 |
*
|
412 |
* You need not call an explicit deinit call. Simply make
|
413 |
* sure it is not on a list with timer_del.
|
414 |
*/
|
415 |
void timer_init(QEMUTimer *ts,
|
416 |
QEMUTimerList *timer_list, int scale,
|
417 |
QEMUTimerCB *cb, void *opaque);
|
418 |
|
419 |
/**
|
420 |
* timer_new_tl:
|
421 |
* @timer_list: the timer list to attach the timer to
|
422 |
* @scale: the scale value for the tiemr
|
423 |
* @cb: the callback to be called when the timer expires
|
424 |
* @opaque: the opaque pointer to be passed to the callback
|
425 |
*
|
426 |
* Creeate a new timer and associate it with @timer_list.
|
427 |
* The memory is allocated by the function.
|
428 |
*
|
429 |
* This is not the preferred interface unless you know you
|
430 |
* are going to call timer_free. Use timer_init instead.
|
431 |
*
|
432 |
* Returns: a pointer to the timer
|
433 |
*/
|
434 |
static inline QEMUTimer *timer_new_tl(QEMUTimerList *timer_list, |
435 |
int scale,
|
436 |
QEMUTimerCB *cb, |
437 |
void *opaque)
|
438 |
{ |
439 |
QEMUTimer *ts = g_malloc0(sizeof(QEMUTimer));
|
440 |
timer_init(ts, timer_list, scale, cb, opaque); |
441 |
return ts;
|
442 |
} |
443 |
|
444 |
/**
|
445 |
* timer_new:
|
446 |
* @type: the clock type to use
|
447 |
* @scale: the scale value for the tiemr
|
448 |
* @cb: the callback to be called when the timer expires
|
449 |
* @opaque: the opaque pointer to be passed to the callback
|
450 |
*
|
451 |
* Creeate a new timer and associate it with the default
|
452 |
* timer list for the clock type @type.
|
453 |
*
|
454 |
* Returns: a pointer to the timer
|
455 |
*/
|
456 |
static inline QEMUTimer *timer_new(QEMUClockType type, int scale, |
457 |
QEMUTimerCB *cb, void *opaque)
|
458 |
{ |
459 |
return timer_new_tl(main_loop_tlg.tl[type], scale, cb, opaque);
|
460 |
} |
461 |
|
462 |
/**
|
463 |
* timer_new_ns:
|
464 |
* @clock: the clock to associate with the timer
|
465 |
* @callback: the callback to call when the timer expires
|
466 |
* @opaque: the opaque pointer to pass to the callback
|
467 |
*
|
468 |
* Create a new timer with nanosecond scale on the default timer list
|
469 |
* associated with the clock.
|
470 |
*
|
471 |
* Returns: a pointer to the newly created timer
|
472 |
*/
|
473 |
static inline QEMUTimer *timer_new_ns(QEMUClockType type, QEMUTimerCB *cb, |
474 |
void *opaque)
|
475 |
{ |
476 |
return timer_new(type, SCALE_NS, cb, opaque);
|
477 |
} |
478 |
|
479 |
/**
|
480 |
* timer_new_us:
|
481 |
* @clock: the clock to associate with the timer
|
482 |
* @callback: the callback to call when the timer expires
|
483 |
* @opaque: the opaque pointer to pass to the callback
|
484 |
*
|
485 |
* Create a new timer with microsecond scale on the default timer list
|
486 |
* associated with the clock.
|
487 |
*
|
488 |
* Returns: a pointer to the newly created timer
|
489 |
*/
|
490 |
static inline QEMUTimer *timer_new_us(QEMUClockType type, QEMUTimerCB *cb, |
491 |
void *opaque)
|
492 |
{ |
493 |
return timer_new(type, SCALE_US, cb, opaque);
|
494 |
} |
495 |
|
496 |
/**
|
497 |
* timer_new_ms:
|
498 |
* @clock: the clock to associate with the timer
|
499 |
* @callback: the callback to call when the timer expires
|
500 |
* @opaque: the opaque pointer to pass to the callback
|
501 |
*
|
502 |
* Create a new timer with millisecond scale on the default timer list
|
503 |
* associated with the clock.
|
504 |
*
|
505 |
* Returns: a pointer to the newly created timer
|
506 |
*/
|
507 |
static inline QEMUTimer *timer_new_ms(QEMUClockType type, QEMUTimerCB *cb, |
508 |
void *opaque)
|
509 |
{ |
510 |
return timer_new(type, SCALE_MS, cb, opaque);
|
511 |
} |
512 |
|
513 |
/**
|
514 |
* timer_free:
|
515 |
* @ts: the timer
|
516 |
*
|
517 |
* Free a timer (it must not be on the active list)
|
518 |
*/
|
519 |
void timer_free(QEMUTimer *ts);
|
520 |
|
521 |
/**
|
522 |
* timer_del:
|
523 |
* @ts: the timer
|
524 |
*
|
525 |
* Delete a timer from the active list.
|
526 |
*/
|
527 |
void timer_del(QEMUTimer *ts);
|
528 |
|
529 |
/**
|
530 |
* timer_mod_ns:
|
531 |
* @ts: the timer
|
532 |
* @expire_time: the expiry time in nanoseconds
|
533 |
*
|
534 |
* Modify a timer to expire at @expire_time
|
535 |
*/
|
536 |
void timer_mod_ns(QEMUTimer *ts, int64_t expire_time);
|
537 |
|
538 |
/**
|
539 |
* timer_mod:
|
540 |
* @ts: the timer
|
541 |
* @expire_time: the expire time in the units associated with the timer
|
542 |
*
|
543 |
* Modify a timer to expiry at @expire_time, taking into
|
544 |
* account the scale associated with the timer.
|
545 |
*/
|
546 |
void timer_mod(QEMUTimer *ts, int64_t expire_timer);
|
547 |
|
548 |
/**
|
549 |
* timer_pending:
|
550 |
* @ts: the timer
|
551 |
*
|
552 |
* Determines whether a timer is pending (i.e. is on the
|
553 |
* active list of timers, whether or not it has not yet expired).
|
554 |
*
|
555 |
* Returns: true if the timer is pending
|
556 |
*/
|
557 |
bool timer_pending(QEMUTimer *ts);
|
558 |
|
559 |
/**
|
560 |
* timer_expired:
|
561 |
* @ts: the timer
|
562 |
*
|
563 |
* Determines whether a timer has expired.
|
564 |
*
|
565 |
* Returns: true if the timer has expired
|
566 |
*/
|
567 |
bool timer_expired(QEMUTimer *timer_head, int64_t current_time);
|
568 |
|
569 |
/**
|
570 |
* timer_expire_time_ns:
|
571 |
* @ts: the timer
|
572 |
*
|
573 |
* Determine the expiry time of a timer
|
574 |
*
|
575 |
* Returns: the expiry time in nanoseconds
|
576 |
*/
|
577 |
uint64_t timer_expire_time_ns(QEMUTimer *ts); |
578 |
|
579 |
/**
|
580 |
* timer_get:
|
581 |
* @f: the file
|
582 |
* @ts: the timer
|
583 |
*
|
584 |
* Read a timer @ts from a file @f
|
585 |
*/
|
586 |
void timer_get(QEMUFile *f, QEMUTimer *ts);
|
587 |
|
588 |
/**
|
589 |
* timer_put:
|
590 |
* @f: the file
|
591 |
* @ts: the timer
|
592 |
*/
|
593 |
void timer_put(QEMUFile *f, QEMUTimer *ts);
|
594 |
|
595 |
/*
|
596 |
* General utility functions
|
597 |
*/
|
598 |
|
599 |
/**
|
600 |
* qemu_timeout_ns_to_ms:
|
601 |
* @ns: nanosecond timeout value
|
602 |
*
|
603 |
* Convert a nanosecond timeout value (or -1) to
|
604 |
* a millisecond value (or -1), always rounding up.
|
605 |
*
|
606 |
* Returns: millisecond timeout value
|
607 |
*/
|
608 |
int qemu_timeout_ns_to_ms(int64_t ns);
|
609 |
|
610 |
/**
|
611 |
* qemu_poll_ns:
|
612 |
* @fds: Array of file descriptors
|
613 |
* @nfds: number of file descriptors
|
614 |
* @timeout: timeout in nanoseconds
|
615 |
*
|
616 |
* Perform a poll like g_poll but with a timeout in nanoseconds.
|
617 |
* See g_poll documentation for further details.
|
618 |
*
|
619 |
* Returns: number of fds ready
|
620 |
*/
|
621 |
int qemu_poll_ns(GPollFD *fds, guint nfds, int64_t timeout);
|
622 |
|
623 |
/**
|
624 |
* qemu_soonest_timeout:
|
625 |
* @timeout1: first timeout in nanoseconds (or -1 for infinite)
|
626 |
* @timeout2: second timeout in nanoseconds (or -1 for infinite)
|
627 |
*
|
628 |
* Calculates the soonest of two timeout values. -1 means infinite, which
|
629 |
* is later than any other value.
|
630 |
*
|
631 |
* Returns: soonest timeout value in nanoseconds (or -1 for infinite)
|
632 |
*/
|
633 |
static inline int64_t qemu_soonest_timeout(int64_t timeout1, int64_t timeout2) |
634 |
{ |
635 |
/* we can abuse the fact that -1 (which means infinite) is a maximal
|
636 |
* value when cast to unsigned. As this is disgusting, it's kept in
|
637 |
* one inline function.
|
638 |
*/
|
639 |
return ((uint64_t) timeout1 < (uint64_t) timeout2) ? timeout1 : timeout2;
|
640 |
} |
641 |
|
642 |
/**
|
643 |
* initclocks:
|
644 |
*
|
645 |
* Initialise the clock & timer infrastructure
|
646 |
*/
|
647 |
void init_clocks(void); |
648 |
|
649 |
int64_t cpu_get_ticks(void);
|
650 |
void cpu_enable_ticks(void); |
651 |
void cpu_disable_ticks(void); |
652 |
|
653 |
static inline int64_t get_ticks_per_sec(void) |
654 |
{ |
655 |
return 1000000000LL; |
656 |
} |
657 |
|
658 |
/**************************************************
|
659 |
* LEGACY API SECTION
|
660 |
*
|
661 |
* All these calls will be deleted in due course
|
662 |
*/
|
663 |
|
664 |
/* These three clocks are maintained here with separate variable
|
665 |
* names for compatibility only.
|
666 |
*/
|
667 |
#define rt_clock (qemu_clock_ptr(QEMU_CLOCK_REALTIME))
|
668 |
#define vm_clock (qemu_clock_ptr(QEMU_CLOCK_VIRTUAL))
|
669 |
#define host_clock (qemu_clock_ptr(QEMU_CLOCK_HOST))
|
670 |
|
671 |
/** LEGACY
|
672 |
* qemu_get_clock_ns:
|
673 |
* @clock: the clock to operate on
|
674 |
*
|
675 |
* Get the nanosecond value of a clock
|
676 |
*
|
677 |
* Returns: the clock value in nanoseconds
|
678 |
*/
|
679 |
int64_t qemu_get_clock_ns(QEMUClock *clock); |
680 |
|
681 |
/** LEGACY
|
682 |
* qemu_get_clock_ms:
|
683 |
* @clock: the clock to operate on
|
684 |
*
|
685 |
* Get the millisecond value of a clock
|
686 |
*
|
687 |
* Returns: the clock value in milliseconds
|
688 |
*/
|
689 |
static inline int64_t qemu_get_clock_ms(QEMUClock *clock) |
690 |
{ |
691 |
return qemu_get_clock_ns(clock) / SCALE_MS;
|
692 |
} |
693 |
|
694 |
/** LEGACY
|
695 |
* qemu_register_clock_reset_notifier:
|
696 |
* @clock: the clock to operate on
|
697 |
* @notifier: the notifier function
|
698 |
*
|
699 |
* Register a notifier function to call when the clock
|
700 |
* concerned is reset.
|
701 |
*/
|
702 |
void qemu_register_clock_reset_notifier(QEMUClock *clock,
|
703 |
Notifier *notifier); |
704 |
|
705 |
/** LEGACY
|
706 |
* qemu_unregister_clock_reset_notifier:
|
707 |
* @clock: the clock to operate on
|
708 |
* @notifier: the notifier function
|
709 |
*
|
710 |
* Unregister a notifier function to call when the clock
|
711 |
* concerned is reset.
|
712 |
*/
|
713 |
void qemu_unregister_clock_reset_notifier(QEMUClock *clock,
|
714 |
Notifier *notifier); |
715 |
|
716 |
/** LEGACY
|
717 |
* qemu_new_timer:
|
718 |
* @clock: the clock to operate on
|
719 |
* @scale: the scale of the clock
|
720 |
* @cb: the callback function to call when the timer expires
|
721 |
* @opaque: an opaque pointer to pass to the callback
|
722 |
*
|
723 |
* Produce a new timer attached to clock @clock. This is a legacy
|
724 |
* function. Use timer_new instead.
|
725 |
*
|
726 |
* Returns: a pointer to the new timer allocated.
|
727 |
*/
|
728 |
QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
|
729 |
QEMUTimerCB *cb, void *opaque);
|
730 |
|
731 |
/** LEGACY
|
732 |
* qemu_free_timer:
|
733 |
* @ts: the timer to operate on
|
734 |
*
|
735 |
* free the timer @ts. @ts must not be active.
|
736 |
*
|
737 |
* This is a legacy function. Use timer_free instead.
|
738 |
*/
|
739 |
static inline void qemu_free_timer(QEMUTimer *ts) |
740 |
{ |
741 |
timer_free(ts); |
742 |
} |
743 |
|
744 |
/** LEGACY
|
745 |
* qemu_del_timer:
|
746 |
* @ts: the timer to operate on
|
747 |
*
|
748 |
* Delete a timer. This makes it inactive. It does not free
|
749 |
* memory.
|
750 |
*
|
751 |
* This is a legacy function. Use timer_del instead.
|
752 |
*/
|
753 |
static inline void qemu_del_timer(QEMUTimer *ts) |
754 |
{ |
755 |
timer_del(ts); |
756 |
} |
757 |
|
758 |
/** LEGACY
|
759 |
* qemu_mod_timer_ns:
|
760 |
* @ts: the timer to operate on
|
761 |
* @expire_time: the expiry time in nanoseconds
|
762 |
*
|
763 |
* Modify a timer such that the expiry time is @expire_time
|
764 |
* as measured in nanoseconds
|
765 |
*
|
766 |
* This is a legacy function. Use timer_mod_ns.
|
767 |
*/
|
768 |
static inline void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time) |
769 |
{ |
770 |
timer_mod_ns(ts, expire_time); |
771 |
} |
772 |
|
773 |
/** LEGACY
|
774 |
* qemu_mod_timer:
|
775 |
* @ts: the timer to operate on
|
776 |
* @expire_time: the expiry time
|
777 |
*
|
778 |
* Modify a timer such that the expiry time is @expire_time
|
779 |
* as measured in the timer's scale
|
780 |
*
|
781 |
* This is a legacy function. Use timer_mod.
|
782 |
*/
|
783 |
static inline void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time) |
784 |
{ |
785 |
timer_mod(ts, expire_time); |
786 |
} |
787 |
|
788 |
/** LEGACY
|
789 |
* qemu_run_timers:
|
790 |
* @clock: clock on which to operate
|
791 |
*
|
792 |
* Run all the timers associated with the default timer list
|
793 |
* of a clock.
|
794 |
*
|
795 |
* Returns: true if any timer ran.
|
796 |
*/
|
797 |
bool qemu_run_timers(QEMUClock *clock);
|
798 |
|
799 |
/** LEGACY
|
800 |
* qemu_new_timer_ns:
|
801 |
* @clock: the clock to associate with the timer
|
802 |
* @callback: the callback to call when the timer expires
|
803 |
* @opaque: the opaque pointer to pass to the callback
|
804 |
*
|
805 |
* Create a new timer with nanosecond scale on the default timer list
|
806 |
* associated with the clock.
|
807 |
*
|
808 |
* Returns: a pointer to the newly created timer
|
809 |
*/
|
810 |
static inline QEMUTimer *qemu_new_timer_ns(QEMUClock *clock, QEMUTimerCB *cb, |
811 |
void *opaque)
|
812 |
{ |
813 |
return qemu_new_timer(clock, SCALE_NS, cb, opaque);
|
814 |
} |
815 |
|
816 |
/** LEGACY
|
817 |
* qemu_new_timer_us:
|
818 |
* @clock: the clock to associate with the timer
|
819 |
* @callback: the callback to call when the timer expires
|
820 |
* @opaque: the opaque pointer to pass to the callback
|
821 |
*
|
822 |
* Create a new timer with microsecond scale on the default timer list
|
823 |
* associated with the clock.
|
824 |
*
|
825 |
* Returns: a pointer to the newly created timer
|
826 |
*/
|
827 |
static inline QEMUTimer *qemu_new_timer_us(QEMUClock *clock, |
828 |
QEMUTimerCB *cb, |
829 |
void *opaque)
|
830 |
{ |
831 |
return qemu_new_timer(clock, SCALE_US, cb, opaque);
|
832 |
} |
833 |
|
834 |
/** LEGACY
|
835 |
* qemu_new_timer_ms:
|
836 |
* @clock: the clock to associate with the timer
|
837 |
* @callback: the callback to call when the timer expires
|
838 |
* @opaque: the opaque pointer to pass to the callback
|
839 |
*
|
840 |
* Create a new timer with millisecond scale on the default timer list
|
841 |
* associated with the clock.
|
842 |
*
|
843 |
* Returns: a pointer to the newly created timer
|
844 |
*/
|
845 |
static inline QEMUTimer *qemu_new_timer_ms(QEMUClock *clock, |
846 |
QEMUTimerCB *cb, |
847 |
void *opaque)
|
848 |
{ |
849 |
return qemu_new_timer(clock, SCALE_MS, cb, opaque);
|
850 |
} |
851 |
|
852 |
/****************************************************
|
853 |
* END OF LEGACY API SECTION
|
854 |
*/
|
855 |
|
856 |
|
857 |
/*
|
858 |
* Low level clock functions
|
859 |
*/
|
860 |
|
861 |
/* real time host monotonic timer */
|
862 |
static inline int64_t get_clock_realtime(void) |
863 |
{ |
864 |
struct timeval tv;
|
865 |
|
866 |
gettimeofday(&tv, NULL);
|
867 |
return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000); |
868 |
} |
869 |
|
870 |
/* Warning: don't insert tracepoints into these functions, they are
|
871 |
also used by simpletrace backend and tracepoints would cause
|
872 |
an infinite recursion! */
|
873 |
#ifdef _WIN32
|
874 |
extern int64_t clock_freq;
|
875 |
|
876 |
static inline int64_t get_clock(void) |
877 |
{ |
878 |
LARGE_INTEGER ti; |
879 |
QueryPerformanceCounter(&ti); |
880 |
return muldiv64(ti.QuadPart, get_ticks_per_sec(), clock_freq);
|
881 |
} |
882 |
|
883 |
#else
|
884 |
|
885 |
extern int use_rt_clock; |
886 |
|
887 |
static inline int64_t get_clock(void) |
888 |
{ |
889 |
#ifdef CLOCK_MONOTONIC
|
890 |
if (use_rt_clock) {
|
891 |
struct timespec ts;
|
892 |
clock_gettime(CLOCK_MONOTONIC, &ts); |
893 |
return ts.tv_sec * 1000000000LL + ts.tv_nsec; |
894 |
} else
|
895 |
#endif
|
896 |
{ |
897 |
/* XXX: using gettimeofday leads to problems if the date
|
898 |
changes, so it should be avoided. */
|
899 |
return get_clock_realtime();
|
900 |
} |
901 |
} |
902 |
#endif
|
903 |
|
904 |
/* icount */
|
905 |
int64_t cpu_get_icount(void);
|
906 |
int64_t cpu_get_clock(void);
|
907 |
|
908 |
/*******************************************/
|
909 |
/* host CPU ticks (if available) */
|
910 |
|
911 |
#if defined(_ARCH_PPC)
|
912 |
|
913 |
static inline int64_t cpu_get_real_ticks(void) |
914 |
{ |
915 |
int64_t retval; |
916 |
#ifdef _ARCH_PPC64
|
917 |
/* This reads timebase in one 64bit go and includes Cell workaround from:
|
918 |
http://ozlabs.org/pipermail/linuxppc-dev/2006-October/027052.html
|
919 |
*/
|
920 |
__asm__ __volatile__ ("mftb %0\n\t"
|
921 |
"cmpwi %0,0\n\t"
|
922 |
"beq- $-8"
|
923 |
: "=r" (retval));
|
924 |
#else
|
925 |
/* http://ozlabs.org/pipermail/linuxppc-dev/1999-October/003889.html */
|
926 |
unsigned long junk; |
927 |
__asm__ __volatile__ ("mfspr %1,269\n\t" /* mftbu */ |
928 |
"mfspr %L0,268\n\t" /* mftb */ |
929 |
"mfspr %0,269\n\t" /* mftbu */ |
930 |
"cmpw %0,%1\n\t"
|
931 |
"bne $-16"
|
932 |
: "=r" (retval), "=r" (junk)); |
933 |
#endif
|
934 |
return retval;
|
935 |
} |
936 |
|
937 |
#elif defined(__i386__)
|
938 |
|
939 |
static inline int64_t cpu_get_real_ticks(void) |
940 |
{ |
941 |
int64_t val; |
942 |
asm volatile ("rdtsc" : "=A" (val)); |
943 |
return val;
|
944 |
} |
945 |
|
946 |
#elif defined(__x86_64__)
|
947 |
|
948 |
static inline int64_t cpu_get_real_ticks(void) |
949 |
{ |
950 |
uint32_t low,high; |
951 |
int64_t val; |
952 |
asm volatile("rdtsc" : "=a" (low), "=d" (high)); |
953 |
val = high; |
954 |
val <<= 32;
|
955 |
val |= low; |
956 |
return val;
|
957 |
} |
958 |
|
959 |
#elif defined(__hppa__)
|
960 |
|
961 |
static inline int64_t cpu_get_real_ticks(void) |
962 |
{ |
963 |
int val;
|
964 |
asm volatile ("mfctl %%cr16, %0" : "=r"(val)); |
965 |
return val;
|
966 |
} |
967 |
|
968 |
#elif defined(__ia64)
|
969 |
|
970 |
static inline int64_t cpu_get_real_ticks(void) |
971 |
{ |
972 |
int64_t val; |
973 |
asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory"); |
974 |
return val;
|
975 |
} |
976 |
|
977 |
#elif defined(__s390__)
|
978 |
|
979 |
static inline int64_t cpu_get_real_ticks(void) |
980 |
{ |
981 |
int64_t val; |
982 |
asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc"); |
983 |
return val;
|
984 |
} |
985 |
|
986 |
#elif defined(__sparc__)
|
987 |
|
988 |
static inline int64_t cpu_get_real_ticks (void) |
989 |
{ |
990 |
#if defined(_LP64)
|
991 |
uint64_t rval; |
992 |
asm volatile("rd %%tick,%0" : "=r"(rval)); |
993 |
return rval;
|
994 |
#else
|
995 |
/* We need an %o or %g register for this. For recent enough gcc
|
996 |
there is an "h" constraint for that. Don't bother with that. */
|
997 |
union {
|
998 |
uint64_t i64; |
999 |
struct {
|
1000 |
uint32_t high; |
1001 |
uint32_t low; |
1002 |
} i32; |
1003 |
} rval; |
1004 |
asm volatile("rd %%tick,%%g1; srlx %%g1,32,%0; mov %%g1,%1" |
1005 |
: "=r"(rval.i32.high), "=r"(rval.i32.low) : : "g1"); |
1006 |
return rval.i64;
|
1007 |
#endif
|
1008 |
} |
1009 |
|
1010 |
#elif defined(__mips__) && \
|
1011 |
((defined(__mips_isa_rev) && __mips_isa_rev >= 2) || defined(__linux__))
|
1012 |
/*
|
1013 |
* binutils wants to use rdhwr only on mips32r2
|
1014 |
* but as linux kernel emulate it, it's fine
|
1015 |
* to use it.
|
1016 |
*
|
1017 |
*/
|
1018 |
#define MIPS_RDHWR(rd, value) { \
|
1019 |
__asm__ __volatile__ (".set push\n\t" \
|
1020 |
".set mips32r2\n\t" \
|
1021 |
"rdhwr %0, "rd"\n\t" \ |
1022 |
".set pop" \
|
1023 |
: "=r" (value)); \
|
1024 |
} |
1025 |
|
1026 |
static inline int64_t cpu_get_real_ticks(void) |
1027 |
{ |
1028 |
/* On kernels >= 2.6.25 rdhwr <reg>, $2 and $3 are emulated */
|
1029 |
uint32_t count; |
1030 |
static uint32_t cyc_per_count = 0; |
1031 |
|
1032 |
if (!cyc_per_count) {
|
1033 |
MIPS_RDHWR("$3", cyc_per_count);
|
1034 |
} |
1035 |
|
1036 |
MIPS_RDHWR("$2", count);
|
1037 |
return (int64_t)(count * cyc_per_count);
|
1038 |
} |
1039 |
|
1040 |
#elif defined(__alpha__)
|
1041 |
|
1042 |
static inline int64_t cpu_get_real_ticks(void) |
1043 |
{ |
1044 |
uint64_t cc; |
1045 |
uint32_t cur, ofs; |
1046 |
|
1047 |
asm volatile("rpcc %0" : "=r"(cc)); |
1048 |
cur = cc; |
1049 |
ofs = cc >> 32;
|
1050 |
return cur - ofs;
|
1051 |
} |
1052 |
|
1053 |
#else
|
1054 |
/* The host CPU doesn't have an easily accessible cycle counter.
|
1055 |
Just return a monotonically increasing value. This will be
|
1056 |
totally wrong, but hopefully better than nothing. */
|
1057 |
static inline int64_t cpu_get_real_ticks (void) |
1058 |
{ |
1059 |
static int64_t ticks = 0; |
1060 |
return ticks++;
|
1061 |
} |
1062 |
#endif
|
1063 |
|
1064 |
#ifdef CONFIG_PROFILER
|
1065 |
static inline int64_t profile_getclock(void) |
1066 |
{ |
1067 |
return cpu_get_real_ticks();
|
1068 |
} |
1069 |
|
1070 |
extern int64_t qemu_time, qemu_time_start;
|
1071 |
extern int64_t tlb_flush_time;
|
1072 |
extern int64_t dev_time;
|
1073 |
#endif
|
1074 |
|
1075 |
#endif
|