45 |
45 |
/* timers */
|
46 |
46 |
|
47 |
47 |
struct QEMUClock {
|
48 |
|
QEMUTimerList *main_loop_timerlist;
|
49 |
48 |
QLIST_HEAD(, QEMUTimerList) timerlists;
|
50 |
49 |
|
51 |
50 |
NotifierList reset_notifiers;
|
... | ... | |
56 |
55 |
};
|
57 |
56 |
|
58 |
57 |
QEMUTimerListGroup main_loop_tlg;
|
59 |
|
QEMUClock *qemu_clocks[QEMU_CLOCK_MAX];
|
|
58 |
QEMUClock qemu_clocks[QEMU_CLOCK_MAX];
|
60 |
59 |
|
61 |
60 |
/* A QEMUTimerList is a list of timers attached to a clock. More
|
62 |
61 |
* than one QEMUTimerList can be attached to each clock, for instance
|
... | ... | |
73 |
72 |
void *notify_opaque;
|
74 |
73 |
};
|
75 |
74 |
|
|
75 |
/**
|
|
76 |
* qemu_clock_ptr:
|
|
77 |
* @type: type of clock
|
|
78 |
*
|
|
79 |
* Translate a clock type into a pointer to QEMUClock object.
|
|
80 |
*
|
|
81 |
* Returns: a pointer to the QEMUClock object
|
|
82 |
*/
|
|
83 |
QEMUClock *qemu_clock_ptr(QEMUClockType type)
|
|
84 |
{
|
|
85 |
return &qemu_clocks[type];
|
|
86 |
}
|
|
87 |
|
76 |
88 |
static bool timer_expired_ns(QEMUTimer *timer_head, int64_t current_time)
|
77 |
89 |
{
|
78 |
90 |
return timer_head && (timer_head->expire_time <= current_time);
|
79 |
91 |
}
|
80 |
92 |
|
81 |
|
static QEMUTimerList *timerlist_new_from_clock(QEMUClock *clock,
|
82 |
|
QEMUTimerListNotifyCB *cb,
|
83 |
|
void *opaque)
|
|
93 |
QEMUTimerList *timerlist_new(QEMUClockType type,
|
|
94 |
QEMUTimerListNotifyCB *cb,
|
|
95 |
void *opaque)
|
84 |
96 |
{
|
85 |
97 |
QEMUTimerList *timer_list;
|
86 |
|
|
87 |
|
/* Assert if we do not have a clock. If you see this
|
88 |
|
* assertion in means that the clocks have not been
|
89 |
|
* initialised before a timerlist is needed. This
|
90 |
|
* normally happens if an AioContext is used before
|
91 |
|
* init_clocks() is called within main().
|
92 |
|
*/
|
93 |
|
assert(clock);
|
|
98 |
QEMUClock *clock = qemu_clock_ptr(type);
|
94 |
99 |
|
95 |
100 |
timer_list = g_malloc0(sizeof(QEMUTimerList));
|
96 |
101 |
timer_list->clock = clock;
|
... | ... | |
100 |
105 |
return timer_list;
|
101 |
106 |
}
|
102 |
107 |
|
103 |
|
QEMUTimerList *timerlist_new(QEMUClockType type,
|
104 |
|
QEMUTimerListNotifyCB *cb, void *opaque)
|
105 |
|
{
|
106 |
|
return timerlist_new_from_clock(qemu_clock_ptr(type), cb, opaque);
|
107 |
|
}
|
108 |
|
|
109 |
108 |
void timerlist_free(QEMUTimerList *timer_list)
|
110 |
109 |
{
|
111 |
110 |
assert(!timerlist_has_timers(timer_list));
|
112 |
111 |
if (timer_list->clock) {
|
113 |
112 |
QLIST_REMOVE(timer_list, list);
|
114 |
|
if (timer_list->clock->main_loop_timerlist == timer_list) {
|
115 |
|
timer_list->clock->main_loop_timerlist = NULL;
|
116 |
|
}
|
117 |
113 |
}
|
118 |
114 |
g_free(timer_list);
|
119 |
115 |
}
|
120 |
116 |
|
121 |
|
static QEMUClock *qemu_clock_new(QEMUClockType type)
|
|
117 |
static void qemu_clock_init(QEMUClockType type)
|
122 |
118 |
{
|
123 |
|
QEMUClock *clock;
|
|
119 |
QEMUClock *clock = qemu_clock_ptr(type);
|
124 |
120 |
|
125 |
|
clock = g_malloc0(sizeof(QEMUClock));
|
126 |
121 |
clock->type = type;
|
127 |
122 |
clock->enabled = true;
|
128 |
123 |
clock->last = INT64_MIN;
|
129 |
124 |
QLIST_INIT(&clock->timerlists);
|
130 |
125 |
notifier_list_init(&clock->reset_notifiers);
|
131 |
|
clock->main_loop_timerlist = timerlist_new_from_clock(clock, NULL, NULL);
|
132 |
|
return clock;
|
|
126 |
main_loop_tlg.tl[type] = timerlist_new(type, NULL, NULL);
|
133 |
127 |
}
|
134 |
128 |
|
135 |
129 |
bool qemu_clock_use_for_deadline(QEMUClockType type)
|
... | ... | |
164 |
158 |
bool qemu_clock_has_timers(QEMUClockType type)
|
165 |
159 |
{
|
166 |
160 |
return timerlist_has_timers(
|
167 |
|
qemu_clock_ptr(type)->main_loop_timerlist);
|
|
161 |
main_loop_tlg.tl[type]);
|
168 |
162 |
}
|
169 |
163 |
|
170 |
164 |
bool timerlist_expired(QEMUTimerList *timer_list)
|
... | ... | |
177 |
171 |
bool qemu_clock_expired(QEMUClockType type)
|
178 |
172 |
{
|
179 |
173 |
return timerlist_expired(
|
180 |
|
qemu_clock_ptr(type)->main_loop_timerlist);
|
|
174 |
main_loop_tlg.tl[type]);
|
181 |
175 |
}
|
182 |
176 |
|
183 |
177 |
/*
|
... | ... | |
227 |
221 |
|
228 |
222 |
QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClockType type)
|
229 |
223 |
{
|
230 |
|
return qemu_clock_ptr(type)->main_loop_timerlist;
|
|
224 |
return main_loop_tlg.tl[type];
|
231 |
225 |
}
|
232 |
226 |
|
233 |
227 |
void timerlist_notify(QEMUTimerList *timer_list)
|
... | ... | |
300 |
294 |
QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
|
301 |
295 |
QEMUTimerCB *cb, void *opaque)
|
302 |
296 |
{
|
303 |
|
return timer_new_tl(clock->main_loop_timerlist,
|
|
297 |
return timer_new_tl(main_loop_tlg.tl[clock->type],
|
304 |
298 |
scale, cb, opaque);
|
305 |
299 |
}
|
306 |
300 |
|
... | ... | |
410 |
404 |
|
411 |
405 |
bool qemu_clock_run_timers(QEMUClockType type)
|
412 |
406 |
{
|
413 |
|
return timerlist_run_timers(qemu_clock_ptr(type)->main_loop_timerlist);
|
|
407 |
return timerlist_run_timers(main_loop_tlg.tl[type]);
|
414 |
408 |
}
|
415 |
409 |
|
416 |
410 |
bool qemu_run_timers(QEMUClock *clock)
|
... | ... | |
519 |
513 |
{
|
520 |
514 |
QEMUClockType type;
|
521 |
515 |
for (type = 0; type < QEMU_CLOCK_MAX; type++) {
|
522 |
|
if (!qemu_clocks[type]) {
|
523 |
|
qemu_clocks[type] = qemu_clock_new(type);
|
524 |
|
main_loop_tlg.tl[type] = qemu_clocks[type]->main_loop_timerlist;
|
525 |
|
}
|
|
516 |
qemu_clock_init(type);
|
526 |
517 |
}
|
527 |
518 |
|
528 |
519 |
#ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
|