[Spice-devel] [PATCH spice-server] Save running property in QXLState

Jonathon Jongsma jjongsma at redhat.com
Thu Mar 21 20:52:01 UTC 2019


From: Frediano Ziglio <fziglio at redhat.com>

This is a preparatory patch that states the running property in QXLState
and provides accessor functions that allows us to check whether the QXL
device is running from different threads.

Signed-off-by: Jonathon Jongsma <jjongsma at redhat.com>
---
Alternate proposal for patch 7/10. I also rebased the rest of Frediano's branch that follows this
commit, which can be found in the dispatcher_red_channel branch at
https://gitlab.freedesktop.org/jjongsma/spice.git

 server/display-channel-private.h |  1 +
 server/red-qxl.c                 | 19 +++++++++++++++++++
 server/red-qxl.h                 |  2 ++
 server/red-worker.c              | 23 +++++++++++------------
 4 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/server/display-channel-private.h b/server/display-channel-private.h
index 58179531d..067c64188 100644
--- a/server/display-channel-private.h
+++ b/server/display-channel-private.h
@@ -89,6 +89,7 @@ struct DisplayChannelPrivate
     uint32_t renderer;
     int enable_jpeg;
     int enable_zlib_glz_wrap;
+    bool running;
 
     /* A ring of pending drawables for this DisplayChannel, regardless of which
      * surface they're associated with. This list is mainly used to flush older
diff --git a/server/red-qxl.c b/server/red-qxl.c
index 8274be567..152e9f068 100644
--- a/server/red-qxl.c
+++ b/server/red-qxl.c
@@ -59,6 +59,9 @@ struct QXLState {
     uint32_t device_display_ids[MAX_MONITORS_COUNT];
     size_t monitors_count;  // length of ^^^
 
+    bool running;
+    pthread_mutex_t running_mutex;
+
     pthread_mutex_t scanout_mutex;
     SpiceMsgDisplayGlScanoutUnix scanout;
     uint64_t gl_draw_cookie;
@@ -66,6 +69,21 @@ struct QXLState {
 
 #define GL_DRAW_COOKIE_INVALID (~((uint64_t) 0))
 
+bool red_qxl_is_running(QXLInstance *qxl) {
+    bool running;
+    pthread_mutex_lock(&qxl->st->running_mutex);
+    running = qxl->st->running;
+    pthread_mutex_unlock(&qxl->st->running_mutex);
+    return running;
+}
+
+void red_qxl_set_running(QXLInstance *qxl, bool running) {
+    pthread_mutex_lock(&qxl->st->running_mutex);
+    qxl->st->running = running;
+    pthread_mutex_unlock(&qxl->st->running_mutex);
+}
+
+
 int red_qxl_check_qxl_version(QXLInstance *qxl, int major, int minor)
 {
     int qxl_major = qxl_get_interface(qxl)->base.major_version;
@@ -825,6 +843,7 @@ void red_qxl_init(RedsState *reds, QXLInstance *qxl)
     qxl_state->reds = reds;
     qxl_state->qxl = qxl;
     pthread_mutex_init(&qxl_state->scanout_mutex, NULL);
+    pthread_mutex_init(&qxl_state->running_mutex, NULL);
     qxl_state->scanout.drm_dma_buf_fd = -1;
     qxl_state->gl_draw_cookie = GL_DRAW_COOKIE_INVALID;
     qxl_state->dispatcher = dispatcher_new(RED_WORKER_MESSAGE_COUNT);
diff --git a/server/red-qxl.h b/server/red-qxl.h
index 947539482..97d28d67c 100644
--- a/server/red-qxl.h
+++ b/server/red-qxl.h
@@ -60,5 +60,7 @@ void red_qxl_update_area_complete(QXLInstance *qxl, uint32_t surface_id,
 void red_qxl_set_client_capabilities(QXLInstance *qxl,
                                      uint8_t client_present,
                                      uint8_t caps[SPICE_CAPABILITIES_SIZE]);
+void red_qxl_set_running(QXLInstance *qxl, bool running);
+bool red_qxl_is_running(QXLInstance *qxl);
 
 #endif /* RED_QXL_H_ */
diff --git a/server/red-worker.c b/server/red-worker.c
index 27fe04ccb..b80fefabe 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -63,7 +63,6 @@ struct RedWorker {
     pthread_t thread;
     QXLInstance *qxl;
     SpiceWatch *dispatch_watch;
-    int running;
     SpiceCoreInterfaceInternal core;
 
     unsigned int event_timeout;
@@ -115,7 +114,7 @@ static int red_process_cursor(RedWorker *worker, int *ring_is_empty)
     QXLCommandExt ext_cmd;
     int n = 0;
 
-    if (!worker->running) {
+    if (!red_qxl_is_running(worker->qxl)) {
         *ring_is_empty = TRUE;
         return n;
     }
@@ -173,7 +172,7 @@ static int red_process_display(RedWorker *worker, int *ring_is_empty)
     int n = 0;
     uint64_t start = spice_get_monotonic_time_ns();
 
-    if (!worker->running) {
+    if (!red_qxl_is_running(worker->qxl)) {
         *ring_is_empty = TRUE;
         return n;
     }
@@ -378,7 +377,7 @@ static void guest_set_client_capabilities(RedWorker *worker)
 #define CLEAR_CAP(a,c)                                                  \
         ((a)[(c) / 8] &= ~(1 << ((c) % 8)))
 
-    if (!worker->running) {
+    if (!red_qxl_is_running(worker->qxl)) {
         return;
     }
     if ((worker->display_channel == NULL) ||
@@ -406,7 +405,7 @@ static void handle_dev_update_async(void *opaque, void *payload)
     QXLRect *qxl_dirty_rects = NULL;
     uint32_t num_dirty_rects = 0;
 
-    spice_return_if_fail(worker->running);
+    spice_return_if_fail(red_qxl_is_running(worker->qxl));
     spice_return_if_fail(qxl_get_interface(worker->qxl)->update_area_complete);
 
     flush_display_commands(worker);
@@ -426,7 +425,7 @@ static void handle_dev_update(void *opaque, void *payload)
     RedWorkerMessageUpdate *msg = payload;
     QXLRect *qxl_dirty_rects = msg->qxl_dirty_rects;
 
-    spice_return_if_fail(worker->running);
+    spice_return_if_fail(red_qxl_is_running(worker->qxl));
 
     flush_display_commands(worker);
     display_channel_update(worker->display_channel,
@@ -586,9 +585,9 @@ static void handle_dev_stop(void *opaque, void *payload)
     RedWorker *worker = opaque;
 
     spice_debug("stop");
-    spice_assert(worker->running);
+    spice_assert(red_qxl_is_running(worker->qxl));
 
-    worker->running = FALSE;
+    red_qxl_set_running(worker->qxl, false);
 
     display_channel_free_glz_drawables(worker->display_channel);
     display_channel_flush_all_surfaces(worker->display_channel);
@@ -606,7 +605,7 @@ static void handle_dev_start(void *opaque, void *payload)
 {
     RedWorker *worker = opaque;
 
-    spice_assert(!worker->running);
+    spice_assert(!red_qxl_is_running(worker->qxl));
     if (worker->cursor_channel) {
         CommonGraphicsChannel *common = COMMON_GRAPHICS_CHANNEL(worker->cursor_channel);
         common_graphics_channel_set_during_target_migrate(common, FALSE);
@@ -616,7 +615,7 @@ static void handle_dev_start(void *opaque, void *payload)
         common_graphics_channel_set_during_target_migrate(common, FALSE);
         display_channel_wait_for_migrate_data(worker->display_channel);
     }
-    worker->running = TRUE;
+    red_qxl_set_running(worker->qxl, true);
     worker->event_timeout = 0;
     guest_set_client_capabilities(worker);
 }
@@ -637,7 +636,7 @@ static void handle_dev_oom(void *opaque, void *payload)
     RedChannel *display_red_channel = RED_CHANNEL(display);
     int ring_is_empty;
 
-    spice_return_if_fail(worker->running);
+    spice_return_if_fail(red_qxl_is_running(worker->qxl));
     // streams? but without streams also leak
     display_channel_debug_oom(display, "OOM1");
     while (red_process_display(worker, &ring_is_empty)) {
@@ -1153,7 +1152,7 @@ static gboolean worker_source_check(GSource *source)
     RedWorkerSource *wsource = SPICE_CONTAINEROF(source, RedWorkerSource, source);
     RedWorker *worker = wsource->worker;
 
-    return worker->running /* TODO && worker->pending_process */;
+    return red_qxl_is_running(worker->qxl) /* TODO && worker->pending_process */;
 }
 
 static gboolean worker_source_dispatch(GSource *source, GSourceFunc callback,
-- 
2.17.2



More information about the Spice-devel mailing list