This patch allows the wait command to be take a class mask that is used to
filter which events are waited for. Because of limitations in the monitor
callbacks, this required splitting wait into two commands: wait and poll. This
allows us to introduce the -x option to treat the mask as an exclusion mask.
Signed-off-by: Anthony Liguori <aliguori(a)us.ibm.com>
diff --git a/monitor.c b/monitor.c
index 94c14b2..1a7d026 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1746,8 +1746,12 @@ static const mon_cmd_t mon_cmds[] = {
"acl allow vnc.username fred\n"
"acl deny vnc.username bob\n"
"acl reset vnc.username\n" },
- { "wait", "-d", do_wait,
- "[-d]", "wait for an asynchronous event (use -d to poll event)"
},
+ { "wait", "-xs?", do_wait,
+ "[-x] [mask]",
+ "wait for an asynchronous event (-x to make mask exclusive, mask specifies the
event classes to wait for)" },
+ { "poll", "-xs?", do_poll,
+ "[-x] [mask]",
+ "poll for an asynchronous event (-x to make mask exclusive, mask specifies the
event classes to poll for)" },
{ NULL, NULL, },
};
diff --git a/wait.c b/wait.c
index 8f6cbad..ebc156a 100644
--- a/wait.c
+++ b/wait.c
@@ -30,6 +30,8 @@ typedef struct PendingWaiter
{
Monitor *mon;
int polling;
+ int exclusive;
+ char *mask;
TAILQ_ENTRY(PendingWaiter) node;
} PendingWaiter;
@@ -50,6 +52,12 @@ static void free_event(WaitEvent *e)
qemu_free(e);
}
+static void free_waiter(PendingWaiter *w)
+{
+ qemu_free(w->mask);
+ qemu_free(w);
+}
+
static void dispatch_event(PendingWaiter *w, WaitEvent *e)
{
monitor_printf(w->mon, "%ld.%06ld: %s: %s\n",
@@ -81,6 +89,41 @@ static void remove_stale_events(void)
}
}
+static int find_string(const char *haystack, const char *needle)
+{
+ const char *p;
+ int clen = strlen(needle);
+
+ p = haystack;
+ while (p && strlen(p) >= clen) {
+ if (memcmp(p, needle, clen) == 0 &&
+ (p[clen] == 0 || p[clen] == ' ')) {
+ return 1;
+ }
+
+ p = strchr(p, ' ');
+ if (p)
+ p++;
+ }
+
+ return 0;
+}
+
+static int event_in_mask(PendingWaiter *w, WaitEvent *e)
+{
+ int ret;
+
+ if (e->class == NULL)
+ ret = 1;
+ else
+ ret = find_string(w->mask, e->class);
+
+ if (w->exclusive)
+ ret = !ret;
+
+ return ret;
+}
+
static int try_to_process_events(void)
{
int processed_events = 0;
@@ -92,15 +135,21 @@ static int try_to_process_events(void)
e = TAILQ_FIRST(&pending_events);
TAILQ_REMOVE(&pending_events, e, node);
- w = TAILQ_FIRST(&pending_waiters);
- TAILQ_REMOVE(&pending_waiters, w, node);
+ TAILQ_FOREACH(w, &pending_waiters, node) {
+ if (event_in_mask(w, e))
+ break;
+ }
- dispatch_event(w, e);
+ if (w) {
+ TAILQ_REMOVE(&pending_waiters, w, node);
- free_event(e);
- qemu_free(w);
+ dispatch_event(w, e);
- processed_events = 1;
+ free_event(e);
+ free_waiter(w);
+
+ processed_events = 1;
+ }
}
remove_stale_events();
@@ -125,13 +174,17 @@ void qemu_notify_event(const char *class, const char *name, const
char *details)
try_to_process_events();
}
-void do_wait(Monitor *mon, int polling)
+static void wait_with_mask(Monitor *mon, int polling, int exclusive,
+ const char *mask)
{
PendingWaiter *w;
w = qemu_mallocz(sizeof(*w));
w->mon = mon;
w->polling = polling;
+ w->exclusive = exclusive;
+ if (mask && strlen(mask))
+ w->mask = qemu_strdup(mask);
TAILQ_INSERT_TAIL(&pending_waiters, w, node);
@@ -140,6 +193,16 @@ void do_wait(Monitor *mon, int polling)
if (!try_to_process_events() && w->polling) {
TAILQ_REMOVE(&pending_waiters, w, node);
- qemu_free(w);
+ free_waiter(w);
}
}
+
+void do_wait(Monitor *mon, int exclusive, const char *mask)
+{
+ wait_with_mask(mon, 0, exclusive, mask);
+}
+
+void do_poll(Monitor *mon, int exclusive, const char *mask)
+{
+ wait_with_mask(mon, 1, exclusive, mask);
+}
diff --git a/wait.h b/wait.h
index 3fb455f..0942823 100644
--- a/wait.h
+++ b/wait.h
@@ -18,6 +18,7 @@
void qemu_notify_event(const char *class, const char *name,
const char *details);
-void do_wait(Monitor *mon, int polling);
+void do_wait(Monitor *mon, int exclusive, const char *mask);
+void do_poll(Monitor *mon, int exclusive, const char *mask);
#endif