Commit f186d64d authored by Pavel Dovgalyuk's avatar Pavel Dovgalyuk Committed by Paolo Bonzini
Browse files

replay: move internal data to the structure



This patch moves replay static variables into the structure
to allow saving and loading them with savevm/loadvm.

Reviewed-by: default avatarPaolo Bonzini <pbonzini@redhat.com>

Signed-off-by: default avatarPavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
Message-Id: <20160926080804.6992.87687.stgit@PASHA-ISP>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent c265e976
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -279,7 +279,7 @@ static Event *replay_read_event(int checkpoint)
/* Called with replay mutex locked */
void replay_read_events(int checkpoint)
{
    while (replay_data_kind == EVENT_ASYNC) {
    while (replay_state.data_kind == EVENT_ASYNC) {
        Event *event = replay_read_event(checkpoint);
        if (!event) {
            break;
+9 −11
Original line number Diff line number Diff line
@@ -16,11 +16,8 @@
#include "qemu/error-report.h"
#include "sysemu/sysemu.h"

unsigned int replay_data_kind = -1;
static unsigned int replay_has_unread_data;

/* Mutex to protect reading and writing events to the log.
   replay_data_kind and replay_has_unread_data are also protected
   data_kind and has_unread_data are also protected
   by this mutex.
   It also protects replay events queue which stores events to be
   written or read to the log. */
@@ -150,15 +147,16 @@ void replay_check_error(void)
void replay_fetch_data_kind(void)
{
    if (replay_file) {
        if (!replay_has_unread_data) {
            replay_data_kind = replay_get_byte();
            if (replay_data_kind == EVENT_INSTRUCTION) {
        if (!replay_state.has_unread_data) {
            replay_state.data_kind = replay_get_byte();
            if (replay_state.data_kind == EVENT_INSTRUCTION) {
                replay_state.instructions_count = replay_get_dword();
            }
            replay_check_error();
            replay_has_unread_data = 1;
            if (replay_data_kind >= EVENT_COUNT) {
                error_report("Replay: unknown event kind %d", replay_data_kind);
            replay_state.has_unread_data = 1;
            if (replay_state.data_kind >= EVENT_COUNT) {
                error_report("Replay: unknown event kind %d",
                             replay_state.data_kind);
                exit(1);
            }
        }
@@ -167,7 +165,7 @@ void replay_fetch_data_kind(void)

void replay_finish_event(void)
{
    replay_has_unread_data = 0;
    replay_state.has_unread_data = 0;
    replay_fetch_data_kind();
}

+5 −3
Original line number Diff line number Diff line
@@ -62,11 +62,13 @@ typedef struct ReplayState {
    uint64_t current_step;
    /*! Number of instructions to be executed before other events happen. */
    int instructions_count;
    /*! Type of the currently executed event. */
    unsigned int data_kind;
    /*! Flag which indicates that event is not processed yet. */
    unsigned int has_unread_data;
} ReplayState;
extern ReplayState replay_state;

extern unsigned int replay_data_kind;

/* File for replay writing */
extern FILE *replay_file;

@@ -98,7 +100,7 @@ void replay_check_error(void);
    the next event from the log. */
void replay_finish_event(void);
/*! Reads data type from the file and stores it in the
    replay_data_kind variable. */
    data_kind variable. */
void replay_fetch_data_kind(void);

/*! Saves queued events (like instructions and sound). */
+1 −1
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ int64_t replay_save_clock(ReplayClockKind kind, int64_t clock)

void replay_read_next_clock(ReplayClockKind kind)
{
    unsigned int read_kind = replay_data_kind - EVENT_CLOCK;
    unsigned int read_kind = replay_state.data_kind - EVENT_CLOCK;

    assert(read_kind == kind);

+8 −7
Original line number Diff line number Diff line
@@ -38,15 +38,15 @@ bool replay_next_event_is(int event)

    /* nothing to skip - not all instructions used */
    if (replay_state.instructions_count != 0) {
        assert(replay_data_kind == EVENT_INSTRUCTION);
        assert(replay_state.data_kind == EVENT_INSTRUCTION);
        return event == EVENT_INSTRUCTION;
    }

    while (true) {
        if (event == replay_data_kind) {
        if (event == replay_state.data_kind) {
            res = true;
        }
        switch (replay_data_kind) {
        switch (replay_state.data_kind) {
        case EVENT_SHUTDOWN:
            replay_finish_event();
            qemu_system_shutdown_request();
@@ -85,7 +85,7 @@ void replay_account_executed_instructions(void)
            replay_state.instructions_count -= count;
            replay_state.current_step += count;
            if (replay_state.instructions_count == 0) {
                assert(replay_data_kind == EVENT_INSTRUCTION);
                assert(replay_state.data_kind == EVENT_INSTRUCTION);
                replay_finish_event();
                /* Wake up iothread. This is required because
                   timers will not expire until clock counters
@@ -188,7 +188,7 @@ bool replay_checkpoint(ReplayCheckpoint checkpoint)
    if (replay_mode == REPLAY_MODE_PLAY) {
        if (replay_next_event_is(EVENT_CHECKPOINT + checkpoint)) {
            replay_finish_event();
        } else if (replay_data_kind != EVENT_ASYNC) {
        } else if (replay_state.data_kind != EVENT_ASYNC) {
            res = false;
            goto out;
        }
@@ -196,7 +196,7 @@ bool replay_checkpoint(ReplayCheckpoint checkpoint)
        /* replay_read_events may leave some unread events.
           Return false if not all of the events associated with
           checkpoint were processed */
        res = replay_data_kind != EVENT_ASYNC;
        res = replay_state.data_kind != EVENT_ASYNC;
    } else if (replay_mode == REPLAY_MODE_RECORD) {
        replay_put_event(EVENT_CHECKPOINT + checkpoint);
        replay_save_events(checkpoint);
@@ -237,9 +237,10 @@ static void replay_enable(const char *fname, int mode)
    replay_filename = g_strdup(fname);

    replay_mode = mode;
    replay_data_kind = -1;
    replay_state.data_kind = -1;
    replay_state.instructions_count = 0;
    replay_state.current_step = 0;
    replay_state.has_unread_data = 0;

    /* skip file header for RECORD and check it for PLAY */
    if (replay_mode == REPLAY_MODE_RECORD) {