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: Paolo Bonzini <pbonzini@redhat.com>

Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
Message-Id: <20160926080804.6992.87687.stgit@PASHA-ISP>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Pavel Dovgalyuk 2016-09-26 11:08:04 +03:00 committed by Paolo Bonzini
parent c265e976f4
commit f186d64d8f
5 changed files with 24 additions and 23 deletions

View File

@ -279,7 +279,7 @@ static Event *replay_read_event(int checkpoint)
/* Called with replay mutex locked */ /* Called with replay mutex locked */
void replay_read_events(int checkpoint) 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); Event *event = replay_read_event(checkpoint);
if (!event) { if (!event) {
break; break;

View File

@ -16,11 +16,8 @@
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "sysemu/sysemu.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. /* 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. by this mutex.
It also protects replay events queue which stores events to be It also protects replay events queue which stores events to be
written or read to the log. */ written or read to the log. */
@ -150,15 +147,16 @@ void replay_check_error(void)
void replay_fetch_data_kind(void) void replay_fetch_data_kind(void)
{ {
if (replay_file) { if (replay_file) {
if (!replay_has_unread_data) { if (!replay_state.has_unread_data) {
replay_data_kind = replay_get_byte(); replay_state.data_kind = replay_get_byte();
if (replay_data_kind == EVENT_INSTRUCTION) { if (replay_state.data_kind == EVENT_INSTRUCTION) {
replay_state.instructions_count = replay_get_dword(); replay_state.instructions_count = replay_get_dword();
} }
replay_check_error(); replay_check_error();
replay_has_unread_data = 1; replay_state.has_unread_data = 1;
if (replay_data_kind >= EVENT_COUNT) { if (replay_state.data_kind >= EVENT_COUNT) {
error_report("Replay: unknown event kind %d", replay_data_kind); error_report("Replay: unknown event kind %d",
replay_state.data_kind);
exit(1); exit(1);
} }
} }
@ -167,7 +165,7 @@ void replay_fetch_data_kind(void)
void replay_finish_event(void) void replay_finish_event(void)
{ {
replay_has_unread_data = 0; replay_state.has_unread_data = 0;
replay_fetch_data_kind(); replay_fetch_data_kind();
} }

View File

@ -62,11 +62,13 @@ typedef struct ReplayState {
uint64_t current_step; uint64_t current_step;
/*! Number of instructions to be executed before other events happen. */ /*! Number of instructions to be executed before other events happen. */
int instructions_count; 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; } ReplayState;
extern ReplayState replay_state; extern ReplayState replay_state;
extern unsigned int replay_data_kind;
/* File for replay writing */ /* File for replay writing */
extern FILE *replay_file; extern FILE *replay_file;
@ -98,7 +100,7 @@ void replay_check_error(void);
the next event from the log. */ the next event from the log. */
void replay_finish_event(void); void replay_finish_event(void);
/*! Reads data type from the file and stores it in the /*! Reads data type from the file and stores it in the
replay_data_kind variable. */ data_kind variable. */
void replay_fetch_data_kind(void); void replay_fetch_data_kind(void);
/*! Saves queued events (like instructions and sound). */ /*! Saves queued events (like instructions and sound). */

View File

@ -31,7 +31,7 @@ int64_t replay_save_clock(ReplayClockKind kind, int64_t clock)
void replay_read_next_clock(ReplayClockKind kind) 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); assert(read_kind == kind);

View File

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