mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
dcb1578069
icount-based record/replay uses qemu_clock_deadline_ns_all to measure the period until vCPU may be interrupted. This function takes in account the virtual timers, because they belong to the virtual devices that may generate interrupt request or affect the virtual machine state. However, there are a subset of virtual timers, that are marked with 'external' flag. These do not change the virtual machine state and only based on virtual clock. Calculating the deadling using the external timers breaks the determinism, because they do not belong to the replayed part of the virtual machine. This patch fixes the deadline calculation for this case by adding new parameter for skipping the external timers when it is needed. Signed-off-by: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru> -- v2 changes: - added new parameter for timer attribute mask Message-Id: <156404426682.18669.17014100602930969222.stgit@pasha-Precision-3630-Tower> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
128 lines
2.6 KiB
C
128 lines
2.6 KiB
C
/*
|
|
* Stubs for the ptimer-test
|
|
*
|
|
* Copyright (c) 2016 Dmitry Osipenko <digetx@gmail.com>
|
|
*
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
|
* See the COPYING file in the top-level directory.
|
|
*
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "qemu/main-loop.h"
|
|
#include "sysemu/replay.h"
|
|
#include "migration/vmstate.h"
|
|
|
|
#include "ptimer-test.h"
|
|
|
|
const VMStateInfo vmstate_info_uint8;
|
|
const VMStateInfo vmstate_info_uint32;
|
|
const VMStateInfo vmstate_info_uint64;
|
|
const VMStateInfo vmstate_info_int64;
|
|
const VMStateInfo vmstate_info_timer;
|
|
|
|
struct QEMUBH {
|
|
QEMUBHFunc *cb;
|
|
void *opaque;
|
|
};
|
|
|
|
QEMUTimerListGroup main_loop_tlg;
|
|
|
|
int64_t ptimer_test_time_ns;
|
|
|
|
/* Do not artificially limit period - see hw/core/ptimer.c. */
|
|
int use_icount = 1;
|
|
bool qtest_allowed;
|
|
|
|
void timer_init_full(QEMUTimer *ts,
|
|
QEMUTimerListGroup *timer_list_group, QEMUClockType type,
|
|
int scale, int attributes,
|
|
QEMUTimerCB *cb, void *opaque)
|
|
{
|
|
if (!timer_list_group) {
|
|
timer_list_group = &main_loop_tlg;
|
|
}
|
|
ts->timer_list = timer_list_group->tl[type];
|
|
ts->cb = cb;
|
|
ts->opaque = opaque;
|
|
ts->scale = scale;
|
|
ts->attributes = attributes;
|
|
ts->expire_time = -1;
|
|
}
|
|
|
|
void timer_mod(QEMUTimer *ts, int64_t expire_time)
|
|
{
|
|
QEMUTimerList *timer_list = ts->timer_list;
|
|
QEMUTimer *t = &timer_list->active_timers;
|
|
|
|
while (t->next != NULL) {
|
|
if (t->next == ts) {
|
|
break;
|
|
}
|
|
|
|
t = t->next;
|
|
}
|
|
|
|
ts->expire_time = MAX(expire_time * ts->scale, 0);
|
|
ts->next = NULL;
|
|
t->next = ts;
|
|
}
|
|
|
|
void timer_del(QEMUTimer *ts)
|
|
{
|
|
QEMUTimerList *timer_list = ts->timer_list;
|
|
QEMUTimer *t = &timer_list->active_timers;
|
|
|
|
while (t->next != NULL) {
|
|
if (t->next == ts) {
|
|
t->next = ts->next;
|
|
return;
|
|
}
|
|
|
|
t = t->next;
|
|
}
|
|
}
|
|
|
|
int64_t qemu_clock_get_ns(QEMUClockType type)
|
|
{
|
|
return ptimer_test_time_ns;
|
|
}
|
|
|
|
int64_t qemu_clock_deadline_ns_all(QEMUClockType type, int attr_mask)
|
|
{
|
|
QEMUTimerList *timer_list = main_loop_tlg.tl[QEMU_CLOCK_VIRTUAL];
|
|
QEMUTimer *t = timer_list->active_timers.next;
|
|
int64_t deadline = -1;
|
|
|
|
while (t != NULL) {
|
|
if (deadline == -1) {
|
|
deadline = t->expire_time;
|
|
} else {
|
|
deadline = MIN(deadline, t->expire_time);
|
|
}
|
|
|
|
t = t->next;
|
|
}
|
|
|
|
return deadline;
|
|
}
|
|
|
|
QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
|
|
{
|
|
QEMUBH *bh = g_new(QEMUBH, 1);
|
|
|
|
bh->cb = cb;
|
|
bh->opaque = opaque;
|
|
|
|
return bh;
|
|
}
|
|
|
|
void qemu_bh_delete(QEMUBH *bh)
|
|
{
|
|
g_free(bh);
|
|
}
|
|
|
|
void replay_bh_schedule_event(QEMUBH *bh)
|
|
{
|
|
bh->cb(bh->opaque);
|
|
}
|