|
@@ -17,6 +17,7 @@
|
|
|
#include "clients.h"
|
|
|
#include "qemu/error-report.h"
|
|
|
#include "qapi/error.h"
|
|
|
+#include "sysemu/runstate.h"
|
|
|
|
|
|
#include <vmnet/vmnet.h>
|
|
|
#include <dispatch/dispatch.h>
|
|
@@ -242,6 +243,35 @@ static void vmnet_bufs_init(VmnetState *s)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * Called on state change to un-register/re-register handlers
|
|
|
+ */
|
|
|
+static void vmnet_vm_state_change_cb(void *opaque, bool running, RunState state)
|
|
|
+{
|
|
|
+ VmnetState *s = opaque;
|
|
|
+
|
|
|
+ if (running) {
|
|
|
+ vmnet_interface_set_event_callback(
|
|
|
+ s->vmnet_if,
|
|
|
+ VMNET_INTERFACE_PACKETS_AVAILABLE,
|
|
|
+ s->if_queue,
|
|
|
+ ^(interface_event_t event_id, xpc_object_t event) {
|
|
|
+ assert(event_id == VMNET_INTERFACE_PACKETS_AVAILABLE);
|
|
|
+ /*
|
|
|
+ * This function is being called from a non qemu thread, so
|
|
|
+ * we only schedule a BH, and do the rest of the io completion
|
|
|
+ * handling from vmnet_send_bh() which runs in a qemu context.
|
|
|
+ */
|
|
|
+ qemu_bh_schedule(s->send_bh);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ vmnet_interface_set_event_callback(
|
|
|
+ s->vmnet_if,
|
|
|
+ VMNET_INTERFACE_PACKETS_AVAILABLE,
|
|
|
+ NULL,
|
|
|
+ NULL);
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
int vmnet_if_create(NetClientState *nc,
|
|
|
xpc_object_t if_desc,
|
|
@@ -329,19 +359,9 @@ int vmnet_if_create(NetClientState *nc,
|
|
|
s->packets_send_current_pos = 0;
|
|
|
s->packets_send_end_pos = 0;
|
|
|
|
|
|
- vmnet_interface_set_event_callback(
|
|
|
- s->vmnet_if,
|
|
|
- VMNET_INTERFACE_PACKETS_AVAILABLE,
|
|
|
- s->if_queue,
|
|
|
- ^(interface_event_t event_id, xpc_object_t event) {
|
|
|
- assert(event_id == VMNET_INTERFACE_PACKETS_AVAILABLE);
|
|
|
- /*
|
|
|
- * This function is being called from a non qemu thread, so
|
|
|
- * we only schedule a BH, and do the rest of the io completion
|
|
|
- * handling from vmnet_send_bh() which runs in a qemu context.
|
|
|
- */
|
|
|
- qemu_bh_schedule(s->send_bh);
|
|
|
- });
|
|
|
+ vmnet_vm_state_change_cb(s, 1, RUN_STATE_RUNNING);
|
|
|
+
|
|
|
+ s->change = qemu_add_vm_change_state_handler(vmnet_vm_state_change_cb, s);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -356,6 +376,8 @@ void vmnet_cleanup_common(NetClientState *nc)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ vmnet_vm_state_change_cb(s, 0, RUN_STATE_SHUTDOWN);
|
|
|
+ qemu_del_vm_change_state_handler(s->change);
|
|
|
if_stopped_sem = dispatch_semaphore_create(0);
|
|
|
vmnet_stop_interface(
|
|
|
s->vmnet_if,
|