diff options
Diffstat (limited to 'vl.c')
-rw-r--r-- | vl.c | 85 |
1 files changed, 54 insertions, 31 deletions
@@ -574,6 +574,10 @@ static int default_driver_check(QemuOpts *opts, void *opaque) static RunState current_run_state = RUN_STATE_PRELAUNCH; +/* We use RUN_STATE_MAX but any invalid value will do */ +static RunState vmstop_requested = RUN_STATE_MAX; +static QemuMutex vmstop_lock; + typedef struct { RunState from; RunState to; @@ -650,10 +654,11 @@ static void runstate_init(void) const RunStateTransition *p; memset(&runstate_valid_transitions, 0, sizeof(runstate_valid_transitions)); - for (p = &runstate_transitions_def[0]; p->from != RUN_STATE_MAX; p++) { runstate_valid_transitions[p->from][p->to] = true; } + + qemu_mutex_init(&vmstop_lock); } /* This function will abort() on invalid state transitions */ @@ -693,6 +698,54 @@ StatusInfo *qmp_query_status(Error **errp) return info; } +static bool qemu_vmstop_requested(RunState *r) +{ + qemu_mutex_lock(&vmstop_lock); + *r = vmstop_requested; + vmstop_requested = RUN_STATE_MAX; + qemu_mutex_unlock(&vmstop_lock); + return *r < RUN_STATE_MAX; +} + +void qemu_system_vmstop_request_prepare(void) +{ + qemu_mutex_lock(&vmstop_lock); +} + +void qemu_system_vmstop_request(RunState state) +{ + vmstop_requested = state; + qemu_mutex_unlock(&vmstop_lock); + qemu_notify_event(); +} + +void vm_start(void) +{ + RunState requested; + + qemu_vmstop_requested(&requested); + if (runstate_is_running() && requested == RUN_STATE_MAX) { + return; + } + + /* Ensure that a STOP/RESUME pair of events is emitted if a + * vmstop request was pending. The BLOCK_IO_ERROR event, for + * example, according to documentation is always followed by + * the STOP event. + */ + if (runstate_is_running()) { + monitor_protocol_event(QEVENT_STOP, NULL); + } else { + cpu_enable_ticks(); + runstate_set(RUN_STATE_RUNNING); + vm_state_notify(1, RUN_STATE_RUNNING); + resume_all_vcpus(); + } + + monitor_protocol_event(QEVENT_RESUME, NULL); +} + + /***********************************************************/ /* real time host monotonic timer */ @@ -1658,17 +1711,6 @@ void vm_state_notify(int running, RunState state) } } -void vm_start(void) -{ - if (!runstate_is_running()) { - cpu_enable_ticks(); - runstate_set(RUN_STATE_RUNNING); - vm_state_notify(1, RUN_STATE_RUNNING); - resume_all_vcpus(); - monitor_protocol_event(QEVENT_RESUME, NULL); - } -} - /* reset/shutdown handler */ typedef struct QEMUResetEntry { @@ -1693,7 +1735,6 @@ static NotifierList suspend_notifiers = static NotifierList wakeup_notifiers = NOTIFIER_LIST_INITIALIZER(wakeup_notifiers); static uint32_t wakeup_reason_mask = ~(1 << QEMU_WAKEUP_REASON_NONE); -static RunState vmstop_requested = RUN_STATE_MAX; int qemu_shutdown_requested_get(void) { @@ -1761,18 +1802,6 @@ static int qemu_debug_requested(void) return r; } -/* We use RUN_STATE_MAX but any invalid value will do */ -static bool qemu_vmstop_requested(RunState *r) -{ - if (vmstop_requested < RUN_STATE_MAX) { - *r = vmstop_requested; - vmstop_requested = RUN_STATE_MAX; - return true; - } - - return false; -} - void qemu_register_reset(QEMUResetHandler *func, void *opaque) { QEMUResetEntry *re = g_malloc0(sizeof(QEMUResetEntry)); @@ -1922,12 +1951,6 @@ void qemu_system_debug_request(void) qemu_notify_event(); } -void qemu_system_vmstop_request(RunState state) -{ - vmstop_requested = state; - qemu_notify_event(); -} - static bool main_loop_should_exit(void) { RunState r; |