bool replay_checkpoint(ReplayCheckpoint checkpoint) { bool res = false; assert(EVENT_CHECKPOINT + checkpoint <= EVENT_CHECKPOINT_LAST); replay_save_instructions(); if (!replay_file) { return true; } replay_mutex_lock(); if (replay_mode == REPLAY_MODE_PLAY) { if (replay_next_event_is(EVENT_CHECKPOINT + checkpoint)) { replay_finish_event(); } else if (replay_state.data_kind != EVENT_ASYNC) { res = false; goto out; } replay_read_events(checkpoint); /* replay_read_events may leave some unread events. Return false if not all of the events associated with checkpoint were processed */ res = replay_state.data_kind != EVENT_ASYNC; } else if (replay_mode == REPLAY_MODE_RECORD) { replay_put_event(EVENT_CHECKPOINT + checkpoint); replay_save_events(checkpoint); res = true; } out: replay_mutex_unlock(); return res; }
void replay_char_read_all_save_buf(uint8_t *buf, int offset) { replay_save_instructions(); replay_mutex_lock(); replay_put_event(EVENT_CHAR_READ_ALL); replay_put_array(buf, offset); replay_mutex_unlock(); }
void replay_shutdown_request(void) { if (replay_mode == REPLAY_MODE_RECORD) { replay_mutex_lock(); replay_put_event(EVENT_SHUTDOWN); replay_mutex_unlock(); } }
void replay_char_read_all_save_error(int res) { assert(res < 0); replay_save_instructions(); replay_mutex_lock(); replay_put_event(EVENT_CHAR_READ_ALL_ERROR); replay_put_dword(res); replay_mutex_unlock(); }
void replay_char_write_event_save(int res, int offset) { replay_save_instructions(); replay_mutex_lock(); replay_put_event(EVENT_CHAR_WRITE); replay_put_dword(res); replay_put_dword(offset); replay_mutex_unlock(); }
int replay_get_instructions(void) { int res = 0; replay_mutex_lock(); if (replay_next_event_is(EVENT_INSTRUCTION)) { res = replay_state.instructions_count; } replay_mutex_unlock(); return res; }
bool replay_exception(void) { if (replay_mode == REPLAY_MODE_RECORD) { replay_save_instructions(); replay_mutex_lock(); replay_put_event(EVENT_EXCEPTION); replay_mutex_unlock(); return true; } else if (replay_mode == REPLAY_MODE_PLAY) { bool res = replay_has_exception(); if (res) { replay_mutex_lock(); replay_finish_event(); replay_mutex_unlock(); } return res; } return true; }
bool replay_has_interrupt(void) { bool res = false; if (replay_mode == REPLAY_MODE_PLAY) { replay_account_executed_instructions(); replay_mutex_lock(); res = replay_next_event_is(EVENT_INTERRUPT); replay_mutex_unlock(); } return res; }
bool replay_interrupt(void) { if (replay_mode == REPLAY_MODE_RECORD) { replay_save_instructions(); replay_mutex_lock(); replay_put_event(EVENT_INTERRUPT); replay_mutex_unlock(); return true; } else if (replay_mode == REPLAY_MODE_PLAY) { bool res = replay_has_interrupt(); if (res) { replay_mutex_lock(); replay_finish_event(); replay_mutex_unlock(); } return res; } return true; }
bool replay_has_exception(void) { bool res = false; if (replay_mode == REPLAY_MODE_PLAY) { replay_account_executed_instructions(); replay_mutex_lock(); res = replay_next_event_is(EVENT_EXCEPTION); replay_mutex_unlock(); } return res; }
void replay_char_write_event_load(int *res, int *offset) { replay_account_executed_instructions(); replay_mutex_lock(); if (replay_next_event_is(EVENT_CHAR_WRITE)) { *res = replay_get_dword(); *offset = replay_get_dword(); replay_finish_event(); replay_mutex_unlock(); } else { replay_mutex_unlock(); error_report("Missing character write event in the replay log"); exit(1); } }
void replay_account_executed_instructions(void) { if (replay_mode == REPLAY_MODE_PLAY) { replay_mutex_lock(); if (replay_state.instructions_count > 0) { int count = (int)(replay_get_current_step() - replay_state.current_step); replay_state.instructions_count -= count; replay_state.current_step += count; if (replay_state.instructions_count == 0) { assert(replay_state.data_kind == EVENT_INSTRUCTION); replay_finish_event(); /* Wake up iothread. This is required because timers will not expire until clock counters will be read from the log. */ qemu_notify_event(); } } replay_mutex_unlock(); } }
int replay_char_read_all_load(uint8_t *buf) { replay_mutex_lock(); if (replay_next_event_is(EVENT_CHAR_READ_ALL)) { size_t size; int res; replay_get_array(buf, &size); replay_finish_event(); replay_mutex_unlock(); res = (int)size; assert(res >= 0); return res; } else if (replay_next_event_is(EVENT_CHAR_READ_ALL_ERROR)) { int res = replay_get_dword(); replay_finish_event(); replay_mutex_unlock(); return res; } else { replay_mutex_unlock(); error_report("Missing character read all event in the replay log"); exit(1); } }
static int os_host_main_loop_wait(int64_t timeout) { GMainContext *context = g_main_context_default(); int ret; g_main_context_acquire(context); glib_pollfds_fill(&timeout); qemu_mutex_unlock_iothread(); replay_mutex_unlock(); ret = qemu_poll_ns((GPollFD *)gpollfds->data, gpollfds->len, timeout); replay_mutex_lock(); qemu_mutex_lock_iothread(); glib_pollfds_poll(); g_main_context_release(context); return ret; }
static int os_host_main_loop_wait(int64_t timeout) { GMainContext *context = g_main_context_default(); GPollFD poll_fds[1024 * 2]; /* this is probably overkill */ int select_ret = 0; int g_poll_ret, ret, i, n_poll_fds; PollingEntry *pe; WaitObjects *w = &wait_objects; gint poll_timeout; int64_t poll_timeout_ns; static struct timeval tv0; fd_set rfds, wfds, xfds; int nfds; g_main_context_acquire(context); /* XXX: need to suppress polling by better using win32 events */ ret = 0; for (pe = first_polling_entry; pe != NULL; pe = pe->next) { ret |= pe->func(pe->opaque); } if (ret != 0) { g_main_context_release(context); return ret; } FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&xfds); nfds = pollfds_fill(gpollfds, &rfds, &wfds, &xfds); if (nfds >= 0) { select_ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv0); if (select_ret != 0) { timeout = 0; } if (select_ret > 0) { pollfds_poll(gpollfds, nfds, &rfds, &wfds, &xfds); } } g_main_context_prepare(context, &max_priority); n_poll_fds = g_main_context_query(context, max_priority, &poll_timeout, poll_fds, ARRAY_SIZE(poll_fds)); g_assert(n_poll_fds <= ARRAY_SIZE(poll_fds)); for (i = 0; i < w->num; i++) { poll_fds[n_poll_fds + i].fd = (DWORD_PTR)w->events[i]; poll_fds[n_poll_fds + i].events = G_IO_IN; } if (poll_timeout < 0) { poll_timeout_ns = -1; } else { poll_timeout_ns = (int64_t)poll_timeout * (int64_t)SCALE_MS; } poll_timeout_ns = qemu_soonest_timeout(poll_timeout_ns, timeout); qemu_mutex_unlock_iothread(); replay_mutex_unlock(); g_poll_ret = qemu_poll_ns(poll_fds, n_poll_fds + w->num, poll_timeout_ns); replay_mutex_lock(); qemu_mutex_lock_iothread(); if (g_poll_ret > 0) { for (i = 0; i < w->num; i++) { w->revents[i] = poll_fds[n_poll_fds + i].revents; } for (i = 0; i < w->num; i++) { if (w->revents[i] && w->func[i]) { w->func[i](w->opaque[i]); } } } if (g_main_context_check(context, max_priority, poll_fds, n_poll_fds)) { g_main_context_dispatch(context); } g_main_context_release(context); return select_ret || g_poll_ret; }