[Spice-commits] 2 commits - common/spice_common.h server/main_channel.c server/red_dispatcher.c server/red_dispatcher.h server/red_worker.c

Alon Levy alon at kemper.freedesktop.org
Mon Nov 7 00:39:23 PST 2011


 common/spice_common.h   |    4 -
 server/main_channel.c   |    2 
 server/red_dispatcher.c |  124 ++++++++++++++++++++++++------------------------
 server/red_dispatcher.h |    3 -
 server/red_worker.c     |   24 +++++----
 5 files changed, 81 insertions(+), 76 deletions(-)

New commits:
commit af77bb577d21215167d388f908584d797cc3c303
Author: Alon Levy <alevy at redhat.com>
Date:   Sun Nov 6 16:09:35 2011 +0200

    server: add prefix argument to red_printf_debug
    
    printed before function name. No central location for prefixes.
    Adding "WORKER", "ASYNC", "MAIN" since those were the current users.

diff --git a/common/spice_common.h b/common/spice_common.h
index f6205a3..d13a94f 100644
--- a/common/spice_common.h
+++ b/common/spice_common.h
@@ -65,13 +65,13 @@
     }                                                               \
 } while (0)
 
-#define red_printf_debug(debug, format, ...) do {                   \
+#define red_printf_debug(debug, prefix, format, ...) do {                   \
     static int debug_level = -1;                                    \
     if (debug_level == -1) {                                        \
         debug_level = getenv("SPICE_DEBUG_LEVEL") != NULL ? atoi(getenv("SPICE_DEBUG_LEVEL")) : 0;  \
     }                                                               \
     if (debug <= debug_level) {                                     \
-        printf("%s: " format "\n", __FUNCTION__, ## __VA_ARGS__ );  \
+        printf("%s: %s: " format "\n", prefix, __FUNCTION__, ## __VA_ARGS__ );  \
     }                                                               \
 } while(0)
 
diff --git a/server/main_channel.c b/server/main_channel.c
index b2439b2..24cdaea 100644
--- a/server/main_channel.c
+++ b/server/main_channel.c
@@ -695,7 +695,7 @@ static void main_channel_release_pipe_item(RedChannelClient *rcc,
         case SPICE_MSG_MAIN_AGENT_DATA: {
             AgentDataPipeItem *data = (AgentDataPipeItem*)base;
             if (!--data->refs->refs) {
-                red_printf_debug(1, "SPICE_MSG_MAIN_AGENT_DATA %p %p, %d",
+                red_printf_debug(1, "MAIN", "SPICE_MSG_MAIN_AGENT_DATA %p %p, %d",
                                  data, data->refs, data->refs->refs);
                 free(data->refs);
                 data->free_data(data->data, data->opaque);
diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index c3cfa90..5257e6b 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -44,6 +44,11 @@ static int num_active_workers = 0;
 
 //volatile
 
+#define DBG_ASYNC(s, ...)   \
+    do {                    \
+        red_printf_debug(2, "ASYNC", s, ##__VA_ARGS__);   \
+    } while (0);
+
 struct AsyncCommand {
     RingItem link;
     RedWorkerMessage message;
@@ -281,6 +286,7 @@ static AsyncCommand *async_command_alloc(RedDispatcher *dispatcher,
     async_command->message = message;
     ring_add(&dispatcher->async_commands, &async_command->link);
     pthread_mutex_unlock(&dispatcher->async_lock);
+    DBG_ASYNC("%p", async_command);
     return async_command;
 }
 
@@ -385,7 +391,7 @@ red_dispatcher_destroy_primary_surface(RedDispatcher *dispatcher,
                                        uint32_t surface_id, int async, uint64_t cookie)
 {
     RedWorkerMessage message;
-    AsyncCommand *cmd;
+    AsyncCommand *cmd = NULL;
 
     if (async) {
         message = RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC;
@@ -429,7 +435,7 @@ red_dispatcher_create_primary_surface(RedDispatcher *dispatcher, uint32_t surfac
                                       QXLDevSurfaceCreate *surface, int async, uint64_t cookie)
 {
     RedWorkerMessage message;
-    AsyncCommand *cmd;
+    AsyncCommand *cmd = NULL;
 
     if (async) {
         message = RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC;
@@ -490,7 +496,7 @@ static void red_dispatcher_destroy_surface_wait(RedDispatcher *dispatcher, uint3
                                                 int async, uint64_t cookie)
 {
     RedWorkerMessage message;
-    AsyncCommand *cmd;
+    AsyncCommand *cmd = NULL;
 
     if (async ) {
         message = RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC;
@@ -835,9 +841,9 @@ void red_dispatcher_async_complete(struct RedDispatcher *dispatcher,
 {
     pthread_mutex_lock(&dispatcher->async_lock);
     ring_remove(&async_command->link);
-    red_printf_debug(2, "%p: cookie %" PRId64, async_command, async_command->cookie);
+    DBG_ASYNC("%p: cookie %" PRId64, async_command, async_command->cookie);
     if (ring_is_empty(&dispatcher->async_commands)) {
-        red_printf_debug(2, "%s: no more async commands", __func__);
+        red_printf_debug(2, "ASYNC", "no more async commands");
     }
     pthread_mutex_unlock(&dispatcher->async_lock);
     switch (async_command->message) {
@@ -918,6 +924,7 @@ RedDispatcher *red_dispatcher_init(QXLInstance *qxl)
     dispatcher = spice_new0(RedDispatcher, 1);
     dispatcher->channel = channels[0];
     ring_init(&dispatcher->async_commands);
+    DBG_ASYNC("dispatcher->async_commands.next %p", dispatcher->async_commands.next);
     init_data.qxl = dispatcher->qxl = qxl;
     init_data.id = qxl->id;
     init_data.channel = channels[1];
diff --git a/server/red_worker.c b/server/red_worker.c
index a5c2df3..de8a820 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -4778,9 +4778,9 @@ static void red_free_some(RedWorker *worker)
     DisplayChannelClient *dcc;
     RingItem *item;
 
-    red_printf_debug(3, "#draw=%d, #red_draw=%d, #glz_draw=%d", worker->drawable_count,
-                                                                worker->red_drawable_count,
-                                                                worker->glz_drawable_count);
+    red_printf_debug(3, "WORKER",
+                     "#draw=%d, #red_draw=%d, #glz_draw=%d", worker->drawable_count,
+                     worker->red_drawable_count, worker->glz_drawable_count);
     WORKER_FOREACH_DCC(worker, item, dcc) {
         GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL;
 
@@ -8651,9 +8651,9 @@ static void display_channel_client_on_disconnect(RedChannelClient *rcc)
     if (!red_channel_is_connected(rcc->channel)) {
         red_display_destroy_compress_bufs(display_channel);
     }
-    red_printf_debug(3, "#draw=%d, #red_draw=%d, #glz_draw=%d", worker->drawable_count,
-                                                                worker->red_drawable_count,
-                                                                worker->glz_drawable_count);
+    red_printf_debug(3, "WORKER", "#draw=%d, #red_draw=%d, #glz_draw=%d",
+                     worker->drawable_count, worker->red_drawable_count,
+                     worker->glz_drawable_count);
 }
 
 void red_disconnect_all_display_TODO_remove_me(RedChannel *channel)
@@ -10433,7 +10433,8 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
     case RED_WORKER_MESSAGE_OOM:
         ASSERT(worker->running);
         // streams? but without streams also leak
-        red_printf_debug(1, "OOM1 #draw=%u, #red_draw=%u, #glz_draw=%u current %u pipes %u",
+        red_printf_debug(1, "WORKER",
+                         "OOM1 #draw=%u, #red_draw=%u, #glz_draw=%u current %u pipes %u",
                          worker->drawable_count,
                          worker->red_drawable_count,
                          worker->glz_drawable_count,
@@ -10447,7 +10448,8 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
             red_free_some(worker);
             worker->qxl->st->qif->flush_resources(worker->qxl);
         }
-        red_printf_debug(1, "OOM2 #draw=%u, #red_draw=%u, #glz_draw=%u current %u pipes %u",
+        red_printf_debug(1, "WORKER",
+                         "OOM2 #draw=%u, #red_draw=%u, #glz_draw=%u current %u pipes %u",
                          worker->drawable_count,
                          worker->red_drawable_count,
                          worker->glz_drawable_count,
commit d5274eeef63872e6b3e0f4db6e1b2dbfcdf5580f
Author: Alon Levy <alevy at redhat.com>
Date:   Sat Oct 8 19:35:14 2011 +0200

    server/red_dispatcher: support concurrent asyncs
    
    This is part of the dispatcher update, extracting the dispatcher routine
    from red_dispatcher and main_dispatcher into dispatcher.
    
    Supporting multiple async operations will make it natural to support
    async monitor commands and async guest io requests that could overlap in
    time.
    
    Use a Ring for AsyncCommands.
    
    Free Desktop Bugzilla: 42463
    
    Related FD: 41622

diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index 721c79c..c3cfa90 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -26,6 +26,7 @@
 #include <pthread.h>
 #include <sys/socket.h>
 #include <signal.h>
+#include <inttypes.h>
 
 #include <spice/qxl_dev.h>
 #include "spice.h"
@@ -43,6 +44,12 @@ static int num_active_workers = 0;
 
 //volatile
 
+struct AsyncCommand {
+    RingItem link;
+    RedWorkerMessage message;
+    uint64_t cookie;
+};
+
 struct RedDispatcher {
     QXLWorker base;
     QXLInstance *qxl;
@@ -54,7 +61,7 @@ struct RedDispatcher {
     int y_res;
     int use_hardware_cursor;
     RedDispatcher *next;
-    RedWorkerMessage async_message;
+    Ring async_commands;
     pthread_mutex_t  async_lock;
     QXLDevSurfaceCreate surface_create;
 };
@@ -145,7 +152,7 @@ static void red_dispatcher_disconnect_cursor_peer(RedChannelClient *rcc)
     RedDispatcher *dispatcher;
 
     if (!rcc->channel) {
-    return;
+        return;
     }
 
     dispatcher = (RedDispatcher *)rcc->channel->data;
@@ -263,18 +270,18 @@ static void red_dispatcher_update_area(RedDispatcher *dispatcher, uint32_t surfa
     ASSERT(message == RED_WORKER_MESSAGE_READY);
 }
 
-static RedWorkerMessage red_dispatcher_async_start(RedDispatcher *dispatcher,
-                                                   RedWorkerMessage message)
+static AsyncCommand *async_command_alloc(RedDispatcher *dispatcher,
+                                         RedWorkerMessage message,
+                                         uint64_t cookie)
 {
+    AsyncCommand *async_command = spice_new0(AsyncCommand, 1);
+
     pthread_mutex_lock(&dispatcher->async_lock);
-    if (dispatcher->async_message != RED_WORKER_MESSAGE_NOP) {
-        red_printf("error: async clash. second async ignored");
-        pthread_mutex_unlock(&dispatcher->async_lock);
-        return RED_WORKER_MESSAGE_NOP;
-    }
-    dispatcher->async_message = message;
+    async_command->cookie = cookie;
+    async_command->message = message;
+    ring_add(&dispatcher->async_commands, &async_command->link);
     pthread_mutex_unlock(&dispatcher->async_lock);
-    return message;
+    return async_command;
 }
 
 static void red_dispatcher_update_area_async(RedDispatcher *dispatcher,
@@ -283,15 +290,11 @@ static void red_dispatcher_update_area_async(RedDispatcher *dispatcher,
                                          uint32_t clear_dirty_region,
                                          uint64_t cookie)
 {
-    RedWorkerMessage message = red_dispatcher_async_start(dispatcher,
-                                                          RED_WORKER_MESSAGE_UPDATE_ASYNC);
-
-    if (message == RED_WORKER_MESSAGE_NOP) {
-        return;
-    }
+    RedWorkerMessage message = RED_WORKER_MESSAGE_UPDATE_ASYNC;
+    AsyncCommand *cmd = async_command_alloc(dispatcher, message, cookie);
 
     write_message(dispatcher->channel, &message);
-    send_data(dispatcher->channel, &cookie, sizeof(cookie));
+    send_data(dispatcher->channel, &cmd, sizeof(cmd));
     send_data(dispatcher->channel, &surface_id, sizeof(uint32_t));
     send_data(dispatcher->channel, qxl_area, sizeof(QXLRect));
     send_data(dispatcher->channel, &clear_dirty_region, sizeof(uint32_t));
@@ -322,14 +325,11 @@ static void qxl_worker_add_memslot(QXLWorker *qxl_worker, QXLDevMemSlot *mem_slo
 
 static void red_dispatcher_add_memslot_async(RedDispatcher *dispatcher, QXLDevMemSlot *mem_slot, uint64_t cookie)
 {
-    RedWorkerMessage message = red_dispatcher_async_start(dispatcher,
-                                                          RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC);
+    RedWorkerMessage message = RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC;
+    AsyncCommand *cmd = async_command_alloc(dispatcher, message, cookie);
 
-    if (message == RED_WORKER_MESSAGE_NOP) {
-        return;
-    }
     write_message(dispatcher->channel, &message);
-    send_data(dispatcher->channel, &cookie, sizeof(cookie));
+    send_data(dispatcher->channel, &cmd, sizeof(cmd));
     send_data(dispatcher->channel, mem_slot, sizeof(QXLDevMemSlot));
 }
 
@@ -363,14 +363,11 @@ static void qxl_worker_destroy_surfaces(QXLWorker *qxl_worker)
 
 static void red_dispatcher_destroy_surfaces_async(RedDispatcher *dispatcher, uint64_t cookie)
 {
-    RedWorkerMessage message = red_dispatcher_async_start(dispatcher,
-                                                      RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC);
+    RedWorkerMessage message = RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC;
+    AsyncCommand *cmd = async_command_alloc(dispatcher, message, cookie);
 
-    if (message == RED_WORKER_MESSAGE_NOP) {
-        return;
-    }
     write_message(dispatcher->channel, &message);
-    send_data(dispatcher->channel, &cookie, sizeof(cookie));
+    send_data(dispatcher->channel, &cmd, sizeof(cmd));
 }
 
 static void red_dispatcher_destroy_primary_surface_complete(RedDispatcher *dispatcher)
@@ -388,20 +385,18 @@ red_dispatcher_destroy_primary_surface(RedDispatcher *dispatcher,
                                        uint32_t surface_id, int async, uint64_t cookie)
 {
     RedWorkerMessage message;
+    AsyncCommand *cmd;
 
     if (async) {
-        message = red_dispatcher_async_start(dispatcher,
-                                             RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC);
-        if (message == RED_WORKER_MESSAGE_NOP) {
-            return;
-        }
+        message = RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC;
+        cmd = async_command_alloc(dispatcher, message, cookie);
     } else {
         message = RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE;
     }
 
     write_message(dispatcher->channel, &message);
     if (async) {
-        send_data(dispatcher->channel, &cookie, sizeof(cookie));
+        send_data(dispatcher->channel, &cmd, sizeof(cmd));
     }
     send_data(dispatcher->channel, &surface_id, sizeof(uint32_t));
     if (!async) {
@@ -434,13 +429,11 @@ red_dispatcher_create_primary_surface(RedDispatcher *dispatcher, uint32_t surfac
                                       QXLDevSurfaceCreate *surface, int async, uint64_t cookie)
 {
     RedWorkerMessage message;
+    AsyncCommand *cmd;
 
     if (async) {
-        message = red_dispatcher_async_start(dispatcher,
-                                             RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC);
-        if (message == RED_WORKER_MESSAGE_NOP) {
-            return;
-        }
+        message = RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC;
+        cmd = async_command_alloc(dispatcher, message, cookie);
     } else {
         message = RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE;
     }
@@ -448,7 +441,7 @@ red_dispatcher_create_primary_surface(RedDispatcher *dispatcher, uint32_t surfac
 
     write_message(dispatcher->channel, &message);
     if (async) {
-        send_data(dispatcher->channel, &cookie, sizeof(cookie));
+        send_data(dispatcher->channel, &cmd, sizeof(cmd));
     }
     send_data(dispatcher->channel, &surface_id, sizeof(uint32_t));
     send_data(dispatcher->channel, surface, sizeof(QXLDevSurfaceCreate));
@@ -497,20 +490,18 @@ static void red_dispatcher_destroy_surface_wait(RedDispatcher *dispatcher, uint3
                                                 int async, uint64_t cookie)
 {
     RedWorkerMessage message;
+    AsyncCommand *cmd;
 
     if (async ) {
-        message = red_dispatcher_async_start(dispatcher,
-                                             RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC);
-        if (message == RED_WORKER_MESSAGE_NOP) {
-            return;
-        }
+        message = RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC;
+        cmd = async_command_alloc(dispatcher, message, cookie);
     } else {
         message = RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT;
     }
 
     write_message(dispatcher->channel, &message);
     if (async) {
-        send_data(dispatcher->channel, &cookie, sizeof(cookie));
+        send_data(dispatcher->channel, &cmd, sizeof(cmd));
     }
     send_data(dispatcher->channel, &surface_id, sizeof(uint32_t));
     if (async) {
@@ -579,14 +570,11 @@ static void qxl_worker_start(QXLWorker *qxl_worker)
 
 static void red_dispatcher_flush_surfaces_async(RedDispatcher *dispatcher, uint64_t cookie)
 {
-    RedWorkerMessage message = red_dispatcher_async_start(dispatcher,
-                                                          RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC);
+    RedWorkerMessage message = RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC;
+    AsyncCommand *cmd = async_command_alloc(dispatcher, message, cookie);
 
-    if (message == RED_WORKER_MESSAGE_NOP) {
-        return;
-    }
     write_message(dispatcher->channel, &message);
-    send_data(dispatcher->channel, &cookie, sizeof(cookie));
+    send_data(dispatcher->channel, &cmd, sizeof(cmd));
 }
 
 static void red_dispatcher_stop(RedDispatcher *dispatcher)
@@ -842,10 +830,17 @@ void spice_qxl_flush_surfaces_async(QXLInstance *instance, uint64_t cookie)
     red_dispatcher_flush_surfaces_async(instance->st->dispatcher, cookie);
 }
 
-void red_dispatcher_async_complete(struct RedDispatcher *dispatcher, uint64_t cookie)
+void red_dispatcher_async_complete(struct RedDispatcher *dispatcher,
+                                   AsyncCommand *async_command)
 {
     pthread_mutex_lock(&dispatcher->async_lock);
-    switch (dispatcher->async_message) {
+    ring_remove(&async_command->link);
+    red_printf_debug(2, "%p: cookie %" PRId64, async_command, async_command->cookie);
+    if (ring_is_empty(&dispatcher->async_commands)) {
+        red_printf_debug(2, "%s: no more async commands", __func__);
+    }
+    pthread_mutex_unlock(&dispatcher->async_lock);
+    switch (async_command->message) {
     case RED_WORKER_MESSAGE_UPDATE_ASYNC:
         break;
     case RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC:
@@ -863,11 +858,11 @@ void red_dispatcher_async_complete(struct RedDispatcher *dispatcher, uint64_t co
     case RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC:
         break;
     default:
-        red_printf("unexpected message");
+        WARN("unexpected message");
     }
-    dispatcher->async_message = RED_WORKER_MESSAGE_NOP;
-    pthread_mutex_unlock(&dispatcher->async_lock);
-    dispatcher->qxl->st->qif->async_complete(dispatcher->qxl, cookie);
+    dispatcher->qxl->st->qif->async_complete(dispatcher->qxl,
+                                             async_command->cookie);
+    free(async_command);
 }
 
 static RedChannel *red_dispatcher_display_channel_create(RedDispatcher *dispatcher)
@@ -922,6 +917,7 @@ RedDispatcher *red_dispatcher_init(QXLInstance *qxl)
 
     dispatcher = spice_new0(RedDispatcher, 1);
     dispatcher->channel = channels[0];
+    ring_init(&dispatcher->async_commands);
     init_data.qxl = dispatcher->qxl = qxl;
     init_data.id = qxl->id;
     init_data.channel = channels[1];
@@ -929,7 +925,6 @@ RedDispatcher *red_dispatcher_init(QXLInstance *qxl)
     init_data.num_renderers = num_renderers;
     memcpy(init_data.renderers, renderers, sizeof(init_data.renderers));
 
-    dispatcher->async_message = RED_WORKER_MESSAGE_NOP;
     pthread_mutex_init(&dispatcher->async_lock, NULL);
     init_data.image_compression = image_compression;
     init_data.jpeg_state = jpeg_state;
diff --git a/server/red_dispatcher.h b/server/red_dispatcher.h
index 144a40e..c2582f4 100644
--- a/server/red_dispatcher.h
+++ b/server/red_dispatcher.h
@@ -19,6 +19,7 @@
 #define _H_RED_DISPATCHER
 
 struct RedChannelClient;
+typedef struct AsyncCommand AsyncCommand;
 
 struct RedDispatcher *red_dispatcher_init(QXLInstance *qxl);
 
@@ -30,6 +31,6 @@ int red_dispatcher_count(void);
 int red_dispatcher_add_renderer(const char *name);
 uint32_t red_dispatcher_qxl_ram_size(void);
 int red_dispatcher_qxl_count(void);
-void red_dispatcher_async_complete(struct RedDispatcher*, uint64_t);
+void red_dispatcher_async_complete(struct RedDispatcher *, AsyncCommand *);
 
 #endif
diff --git a/server/red_worker.c b/server/red_worker.c
index 4337d16..a5c2df3 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -10383,7 +10383,7 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
     int ring_is_empty;
     int call_async_complete = 0;
     int write_ready = 0;
-    uint64_t cookie;
+    AsyncCommand *cmd;
 
     read_message(worker->channel, &message);
 
@@ -10398,7 +10398,7 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
     case RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC:
     case RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC:
         call_async_complete = 1;
-        receive_data(worker->channel, &cookie, sizeof(cookie));
+        receive_data(worker->channel, &cmd, sizeof(cmd));
         break;
     case RED_WORKER_MESSAGE_UPDATE:
     case RED_WORKER_MESSAGE_ADD_MEMSLOT:
@@ -10667,7 +10667,7 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
         red_error("message error");
     }
     if (call_async_complete) {
-        red_dispatcher_async_complete(worker->dispatcher, cookie);
+        red_dispatcher_async_complete(worker->dispatcher, cmd);
     }
     if (write_ready) {
         message = RED_WORKER_MESSAGE_READY;


More information about the Spice-commits mailing list