summaryrefslogtreecommitdiff
path: root/server/red-worker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'server/red-worker.cpp')
-rw-r--r--server/red-worker.cpp67
1 files changed, 62 insertions, 5 deletions
diff --git a/server/red-worker.cpp b/server/red-worker.cpp
index 912b7d55..cf9808c8 100644
--- a/server/red-worker.cpp
+++ b/server/red-worker.cpp
@@ -750,11 +750,22 @@ handle_dev_loadvm_commands(RedWorker* worker, RedWorkerMessageLoadvmCommands* ms
}
}
+bool got_event_notify;
+bool got_event_dispatch;
+
static void worker_dispatcher_record(void *opaque, uint32_t message_type, void *payload)
{
auto worker = static_cast<RedWorker *>(opaque);
- red_record_event(worker->record, 1, message_type);
+ if (message_type == RED_WORKER_MESSAGE_WAKEUP) {
+ got_event_notify = true;
+ } else {
+ got_event_dispatch = true;
+ }
+
+ if (worker->record) {
+ red_record_event(worker->record, 1, message_type);
+ }
}
template <typename T>
@@ -873,18 +884,57 @@ struct RedWorkerSource {
RedWorker *worker;
};
+#define ALL_LOOP_EVENTS \
+ LOOP_EVENT(any) \
+ LOOP_EVENT(timeout) \
+ LOOP_EVENT(stream_timeout) \
+ LOOP_EVENT(watch) \
+ LOOP_EVENT(watch_read) \
+ LOOP_EVENT(watch_write) \
+ LOOP_EVENT(dispatch) \
+ LOOP_EVENT(notify)
+
+#define LOOP_EVENT(name) extern bool got_event_ ## name;
+ALL_LOOP_EVENTS
+#undef LOOP_EVENT
+
+typedef struct WakeupEvent {
+ const char *name;
+ bool *p_got_event;
+ RedStatCounter counter;
+} WakeupEvent;
+static WakeupEvent wakeup_events[] = {
+#define LOOP_EVENT(name) { #name, &got_event_ ## name, {} },
+ ALL_LOOP_EVENTS
+#undef LOOP_EVENT
+};
+
+bool got_event_any;
+bool got_event_stream_timeout;
+
static gboolean worker_source_prepare(GSource *source, gint *p_timeout)
{
RedWorkerSource *wsource = SPICE_CONTAINEROF(source, RedWorkerSource, source);
RedWorker *worker = wsource->worker;
unsigned int timeout;
+ for (int i = 0; i < G_N_ELEMENTS(wakeup_events); ++i) {
+ const WakeupEvent *ev = &wakeup_events[i];
+ if (*ev->p_got_event) {
+ stat_inc_counter(ev->counter, 1);
+ }
+ *ev->p_got_event = false;
+ }
+ got_event_any = true;
+
timeout = MIN(worker->event_timeout,
display_channel_get_streams_timeout(worker->display_channel));
*p_timeout = (timeout == INF_EVENT_WAIT) ? -1 : timeout;
- if (*p_timeout == 0)
+ if (*p_timeout == 0) {
+ got_event_stream_timeout = true;
return TRUE;
+ }
if (worker->was_blocked && !red_process_is_blocked(worker)) {
return TRUE;
@@ -953,9 +1003,7 @@ RedWorker* red_worker_new(QXLInstance *qxl)
worker->qxl = qxl;
register_callbacks(dispatcher);
- if (worker->record) {
- dispatcher->register_universal_handler(worker_dispatcher_record);
- }
+ dispatcher->register_universal_handler(worker_dispatcher_record);
worker->driver_cap_monitors_config = false;
char worker_str[SPICE_STAT_NODE_NAME_MAX];
@@ -966,6 +1014,15 @@ RedWorker* red_worker_new(QXLInstance *qxl)
stat_init_counter(&worker->full_loop_counter, reds, &worker->stat, "full_loops", TRUE);
stat_init_counter(&worker->total_loop_counter, reds, &worker->stat, "total_loops", TRUE);
+ {
+ RedStatNode node;
+ stat_init_node(&node, reds, NULL, "wakeups", TRUE);
+ for (int i = 0; i < G_N_ELEMENTS(wakeup_events); ++i) {
+ WakeupEvent *ev = &wakeup_events[i];
+ stat_init_counter(&ev->counter, reds, &node, ev->name, TRUE);
+ }
+ }
+
worker->dispatch_watch = dispatcher->create_watch(&worker->core);
spice_assert(worker->dispatch_watch != nullptr);