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:
		
							parent
							
								
									c265e976f4
								
							
						
					
					
						commit
						f186d64d8f
					
				| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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). */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue