Allows doing async commands from the monitor and from any vcpu thread independently, i.e. red_dispatcher can have multiple commands pending completion. red_worker still handles them sequentially off it's pipe, no magical gain here.
RHBZ: 747011 FDBZ: 41622 --- server/red_dispatcher.c | 85 ++++++++++++++++++++++++++++++++++------------ server/red_worker.c | 15 ++++++++ 2 files changed, 78 insertions(+), 22 deletions(-) diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c index 6731727..86da0b6 100644 --- a/server/red_dispatcher.c +++ b/server/red_dispatcher.c @@ -43,6 +43,13 @@ static int num_active_workers = 0; //volatile +typedef struct AsyncCommand AsyncCommand; +struct AsyncCommand { + AsyncCommand *next; + 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; + AsyncCommand* async_commands; pthread_mutex_t async_lock; QXLDevSurfaceCreate surface_create; }; @@ -263,18 +270,26 @@ 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 *push_async_command(RedDispatcher *dispatcher, + RedWorkerMessage message, + uint64_t cookie) { + AsyncCommand *async_command = spice_new(AsyncCommand, 1); + pthread_mutex_lock(&dispatcher->async_lock); - if (dispatcher->async_message != RED_WORKER_MESSAGE_NOP) { - red_printf("warning: async clash. have %d, ignoring %d", - dispatcher->async_message, message); - pthread_mutex_unlock(&dispatcher->async_lock); - return RED_WORKER_MESSAGE_NOP; - } - dispatcher->async_message = message; + async_command->cookie = cookie; + async_command->message = message; + async_command->next = dispatcher->async_commands; + dispatcher->async_commands = async_command; pthread_mutex_unlock(&dispatcher->async_lock); + return async_command; +} + +static RedWorkerMessage red_dispatcher_async_start(RedDispatcher *dispatcher, + RedWorkerMessage message, + uint64_t cookie) +{ + push_async_command(dispatcher, message, cookie); return message; } @@ -285,7 +300,8 @@ static void red_dispatcher_update_area_async(RedDispatcher *dispatcher, uint64_t cookie) { RedWorkerMessage message = red_dispatcher_async_start(dispatcher, - RED_WORKER_MESSAGE_UPDATE_ASYNC); + RED_WORKER_MESSAGE_UPDATE_ASYNC, + cookie); if (message == RED_WORKER_MESSAGE_NOP) { return; @@ -304,7 +320,7 @@ static void red_dispatcher_update_area_dirty_async(RedDispatcher *dispatcher, uint32_t clear_dirty_region, uint64_t cookie) { RedWorkerMessage message = red_dispatcher_async_start( - dispatcher, RED_WORKER_MESSAGE_UPDATE_DIRTY_ASYNC); + dispatcher, RED_WORKER_MESSAGE_UPDATE_DIRTY_ASYNC, cookie); if (message == RED_WORKER_MESSAGE_NOP) { return; @@ -345,7 +361,8 @@ 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); + RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC, + cookie); if (message == RED_WORKER_MESSAGE_NOP) { return; @@ -386,7 +403,8 @@ 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); + RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC, + cookie); if (message == RED_WORKER_MESSAGE_NOP) { return; @@ -413,7 +431,8 @@ red_dispatcher_destroy_primary_surface(RedDispatcher *dispatcher, if (async) { message = red_dispatcher_async_start(dispatcher, - RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC); + RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC, + cookie); if (message == RED_WORKER_MESSAGE_NOP) { return; } @@ -459,7 +478,8 @@ red_dispatcher_create_primary_surface(RedDispatcher *dispatcher, uint32_t surfac if (async) { message = red_dispatcher_async_start(dispatcher, - RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC); + RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC, + cookie); if (message == RED_WORKER_MESSAGE_NOP) { return; } @@ -522,7 +542,8 @@ static void red_dispatcher_destroy_surface_wait(RedDispatcher *dispatcher, uint3 if (async ) { message = red_dispatcher_async_start(dispatcher, - RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC); + RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC, + cookie); if (message == RED_WORKER_MESSAGE_NOP) { return; } @@ -602,7 +623,8 @@ 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); + RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC, + cookie); if (message == RED_WORKER_MESSAGE_NOP) { return; @@ -875,8 +897,27 @@ void spice_qxl_flush_surfaces_async(QXLInstance *instance, uint64_t cookie) void red_dispatcher_async_complete(struct RedDispatcher *dispatcher, uint64_t cookie) { + AsyncCommand *async_command; + AsyncCommand *prev; + pthread_mutex_lock(&dispatcher->async_lock); - switch (dispatcher->async_message) { + async_command = dispatcher->async_commands; + prev = NULL; + while (async_command && async_command->cookie != cookie) { + prev = async_command; + async_command = async_command->next; + }; + if (!async_command) { + WARN("unknown cookie"); + goto end; + } + if (!prev) { + red_printf_debug(2, "%s: no more async commands\n", __func__); + dispatcher->async_commands = NULL; + } else { + prev->next = async_command->next; + } + switch (async_command->message) { case RED_WORKER_MESSAGE_UPDATE_ASYNC: case RED_WORKER_MESSAGE_UPDATE_DIRTY_ASYNC: break; @@ -895,9 +936,10 @@ 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; +end: + free(async_command); pthread_mutex_unlock(&dispatcher->async_lock); dispatcher->qxl->st->qif->async_complete(dispatcher->qxl, cookie); } @@ -961,7 +1003,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_worker.c b/server/red_worker.c index 5a77f35..5f74417 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -10112,6 +10112,7 @@ static inline void handle_dev_update_async(RedWorker *worker, int with_dirty) QXLRect *qxl_dirty_rects = NULL; uint32_t num_dirty_rects; RedSurface *surface; + int i; red_printf_debug(2, ""); receive_data(worker->channel, &surface_id, sizeof(uint32_t)); @@ -10139,6 +10140,7 @@ static inline void handle_dev_update_async(RedWorker *worker, int with_dirty) qxl_dirty_rects = spice_new0(QXLRect, num_dirty_rects); } } + red_printf_debug(2, "num_dirty_rects = %d, with_dirty = %d", num_dirty_rects, with_dirty); if (num_dirty_rects > 0) { surface_dirty_region_to_rects(surface, qxl_dirty_rects, num_dirty_rects, clear_dirty_region); @@ -10150,6 +10152,19 @@ static inline void handle_dev_update_async(RedWorker *worker, int with_dirty) if (!with_dirty) { free(qxl_dirty_rects); } + for (i = 0 ; i < num_dirty_rects; ++i) { + if (qxl_dirty_rects[i].top == 0 && + qxl_dirty_rects[i].bottom == 0 && + qxl_dirty_rects[i].left == 0 && + qxl_dirty_rects[i].right == 0) { + break; + } + red_printf_debug(3, "dirty %d: %d %d %d %d", i, + qxl_dirty_rects[i].top, + qxl_dirty_rects[i].bottom, + qxl_dirty_rects[i].left, + qxl_dirty_rects[i].right); + } } static inline void handle_dev_update(RedWorker *worker) -- 1.7.7 _______________________________________________ Spice-devel mailing list Spice-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/spice-devel