summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/event-loop.c11
-rw-r--r--server/red-worker.cpp67
-rw-r--r--server/video-stream.cpp3
3 files changed, 76 insertions, 5 deletions
diff --git a/server/event-loop.c b/server/event-loop.c
index e5291b5a..d295e42e 100644
--- a/server/event-loop.c
+++ b/server/event-loop.c
@@ -86,6 +86,11 @@ typedef struct SpiceTimerGlib {
GSource *source;
} SpiceTimerGlib;
+bool got_event_watch;
+bool got_event_watch_read;
+bool got_event_watch_write;
+bool got_event_timeout;
+
static SpiceTimer* timer_add(const SpiceCoreInterfaceInternal *iface,
SpiceTimerFunc func, void *opaque)
{
@@ -103,6 +108,7 @@ static gboolean timer_func(gpointer user_data)
{
SpiceTimerGlib *timer = (SpiceTimerGlib*) user_data;
+ got_event_timeout = true;
timer->func(timer->opaque);
/* timer might be free after func(), don't touch */
@@ -183,6 +189,11 @@ static gboolean watch_func(GIOChannel *source, GIOCondition condition,
// this works also under Windows despite the name
int fd = g_io_channel_unix_get_fd(source);
+ got_event_watch = true;
+ if (condition & G_IO_IN)
+ got_event_watch_read = true;
+ if (condition & G_IO_OUT)
+ got_event_watch_write = true;
watch->func(fd, giocondition_to_spice_event(condition), watch->opaque);
return TRUE;
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);
diff --git a/server/video-stream.cpp b/server/video-stream.cpp
index 056d0c31..62a96bce 100644
--- a/server/video-stream.cpp
+++ b/server/video-stream.cpp
@@ -930,6 +930,8 @@ void video_stream_detach_and_stop(DisplayChannel *display)
}
}
+extern bool got_event_stream_timeout;
+
void video_stream_timeout(DisplayChannel *display)
{
Ring *ring = &display->priv->streams;
@@ -941,6 +943,7 @@ void video_stream_timeout(DisplayChannel *display)
VideoStream *stream = SPICE_CONTAINEROF(item, VideoStream, link);
item = ring_next(ring, item);
if (now >= (stream->last_time + RED_STREAM_TIMEOUT)) {
+ got_event_stream_timeout = true;
detach_video_stream_gracefully(display, stream, nullptr);
video_stream_stop(display, stream);
}