aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2019-06-20 18:37:07 +0100
committerKevin Wolf <kwolf@redhat.com>2019-07-08 16:00:26 +0200
commit60dbc5a1c5176269669ffc26c081ab2cfb7f12f7 (patch)
tree6d03666bb9bf575826f6654293c0327f6e5128cf
parentdf34fe314b5da628bc9a2664fb1b887bc0a6cc6d (diff)
vl: add qemu_add_vm_change_state_handler_prio()
Add an API for registering vm change state handlers with a well-defined ordering. This is necessary when handlers depend on each other. Small coding style fixes are included to make checkpatch.pl happy. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
-rw-r--r--include/sysemu/sysemu.h2
-rw-r--r--vl.c59
2 files changed, 49 insertions, 12 deletions
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 61579ae71e..984c439ac9 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -29,6 +29,8 @@ typedef void VMChangeStateHandler(void *opaque, int running, RunState state);
VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
void *opaque);
+VMChangeStateEntry *qemu_add_vm_change_state_handler_prio(
+ VMChangeStateHandler *cb, void *opaque, int priority);
void qemu_del_vm_change_state_handler(VMChangeStateEntry *e);
void vm_state_notify(int running, RunState state);
diff --git a/vl.c b/vl.c
index 280e709e2c..5089fce6c5 100644
--- a/vl.c
+++ b/vl.c
@@ -1365,28 +1365,57 @@ static int machine_help_func(QemuOpts *opts, MachineState *machine)
struct vm_change_state_entry {
VMChangeStateHandler *cb;
void *opaque;
- QLIST_ENTRY (vm_change_state_entry) entries;
+ QTAILQ_ENTRY(vm_change_state_entry) entries;
+ int priority;
};
-static QLIST_HEAD(, vm_change_state_entry) vm_change_state_head;
+static QTAILQ_HEAD(, vm_change_state_entry) vm_change_state_head;
-VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
- void *opaque)
+/**
+ * qemu_add_vm_change_state_handler_prio:
+ * @cb: the callback to invoke
+ * @opaque: user data passed to the callback
+ * @priority: low priorities execute first when the vm runs and the reverse is
+ * true when the vm stops
+ *
+ * Register a callback function that is invoked when the vm starts or stops
+ * running.
+ *
+ * Returns: an entry to be freed using qemu_del_vm_change_state_handler()
+ */
+VMChangeStateEntry *qemu_add_vm_change_state_handler_prio(
+ VMChangeStateHandler *cb, void *opaque, int priority)
{
VMChangeStateEntry *e;
+ VMChangeStateEntry *other;
- e = g_malloc0(sizeof (*e));
-
+ e = g_malloc0(sizeof(*e));
e->cb = cb;
e->opaque = opaque;
- QLIST_INSERT_HEAD(&vm_change_state_head, e, entries);
+ e->priority = priority;
+
+ /* Keep list sorted in ascending priority order */
+ QTAILQ_FOREACH(other, &vm_change_state_head, entries) {
+ if (priority < other->priority) {
+ QTAILQ_INSERT_BEFORE(other, e, entries);
+ return e;
+ }
+ }
+
+ QTAILQ_INSERT_TAIL(&vm_change_state_head, e, entries);
return e;
}
+VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
+ void *opaque)
+{
+ return qemu_add_vm_change_state_handler_prio(cb, opaque, 0);
+}
+
void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
{
- QLIST_REMOVE (e, entries);
- g_free (e);
+ QTAILQ_REMOVE(&vm_change_state_head, e, entries);
+ g_free(e);
}
void vm_state_notify(int running, RunState state)
@@ -1395,8 +1424,14 @@ void vm_state_notify(int running, RunState state)
trace_vm_state_notify(running, state, RunState_str(state));
- QLIST_FOREACH_SAFE(e, &vm_change_state_head, entries, next) {
- e->cb(e->opaque, running, state);
+ if (running) {
+ QTAILQ_FOREACH_SAFE(e, &vm_change_state_head, entries, next) {
+ e->cb(e->opaque, running, state);
+ }
+ } else {
+ QTAILQ_FOREACH_REVERSE_SAFE(e, &vm_change_state_head, entries, next) {
+ e->cb(e->opaque, running, state);
+ }
}
}
@@ -2911,7 +2946,7 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
- QLIST_INIT (&vm_change_state_head);
+ QTAILQ_INIT(&vm_change_state_head);
os_setup_early_signal_handling();
cpu_option = NULL;