On Thu, Jul 07, 2011 at 09:16:33AM +0300, Yonit Halperin wrote: > On 07/06/2011 08:37 PM, Alon Levy wrote: > >The new _ASYNC io's in qxl_dev listed at the end get six new api > >functions, and an additional callback function "async_complete". When > >the async version of a specific io is used, completion is notified by > >calling async_complete, and no READY message is written or expected by > >the dispatcher. > > > >update_area has been changed to push QXLRects to the worker thread, where > >the conversion to SpiceRect takes place. > > > >Added api: > > > >QXLWorker: > > update_area_async > > add_memslot_async > > destroy_surfaces_async > > destroy_primary_surface_async > > create_primary_surface_async > > destroy_surface_wait_async > > oom_async > > > >QXLInterface: > > async_complete > >--- > > server/red_dispatcher.c | 179 > > ++++++++++++++++++++++++++++++++++++++--------- > > server/red_parse_qxl.c | 2 +- > > server/red_parse_qxl.h | 2 +- > > server/red_worker.c | 80 ++++++++++++++------- > > server/red_worker.h | 8 ++ > > server/spice.h | 12 +++ > > 6 files changed, 221 insertions(+), 62 deletions(-) > > > >diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c > >index 56446ab..74c7af2 100644 > >--- a/server/red_dispatcher.c > >+++ b/server/red_dispatcher.c > >@@ -209,38 +209,49 @@ static void update_client_mouse_allowed(void) > > } > > } > > > >-static void qxl_worker_update_area(QXLWorker *qxl_worker, uint32_t > >surface_id, > >+static void qxl_worker_update_area_helper(QXLWorker *qxl_worker, uint32_t > >surface_id, > > QXLRect *qxl_area, QXLRect > > *qxl_dirty_rects, > >- uint32_t num_dirty_rects, uint32_t > >clear_dirty_region) > >+ uint32_t num_dirty_rects, uint32_t > >clear_dirty_region, > >+ int async) > > { > > RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; > >- RedWorkerMessage message = RED_WORKER_MESSAGE_UPDATE; > >- SpiceRect *dirty_rects = spice_new0(SpiceRect, num_dirty_rects); > >- SpiceRect *area = spice_new0(SpiceRect, 1); > >- int i; > >- > >- red_get_rect_ptr(area, qxl_area); > >+ RedWorkerMessage message; > > > >+ if (async) { > >+ message = RED_WORKER_MESSAGE_UPDATE_ASYNC; > >+ } else { > >+ message = RED_WORKER_MESSAGE_UPDATE; > >+ } > > write_message(dispatcher->channel,&message); > > send_data(dispatcher->channel,&surface_id, sizeof(uint32_t)); > >- send_data(dispatcher->channel,&area, sizeof(SpiceRect *)); > >- send_data(dispatcher->channel,&dirty_rects, sizeof(SpiceRect *)); > >+ send_data(dispatcher->channel,&qxl_area, sizeof(QXLRect *)); > >+ send_data(dispatcher->channel,&qxl_dirty_rects, sizeof(QXLRect *)); > > send_data(dispatcher->channel,&num_dirty_rects, sizeof(uint32_t)); > > send_data(dispatcher->channel,&clear_dirty_region, sizeof(uint32_t)); > >+ if (async) { > >+ return; > >+ } > > Hi, > I find it problematic to decouple the qxl operations upon QXL_IO and > the worker operations. For example: upon destroy_surfaces, the qxl > resets the tracked guest commands. However, since destroy_surfaces > is asynced, the worker might read commands from the ring before > handling destroy surfaces, and then the qxl guest commands will be > modified. > I suggest a partial decoupling: on async io, the dispatcher will > still wait for RED_WORKER_MESSAGE_READY, but the server will set it > immediately when it receives the async message. >
ok, I guess I see two solutions: 1. doing a stop on async, and a start on async_complete (a little heavy handed) 2. use the remembered io and do the "after completion" part in it, not on the io call, so from async_complete. I'll do 2. > > read_message(dispatcher->channel,&message); > > ASSERT(message == RED_WORKER_MESSAGE_READY); > >+} > > > >- for (i = 0; i< num_dirty_rects; i++) { > >- qxl_dirty_rects[i].top = dirty_rects[i].top; > >- qxl_dirty_rects[i].left = dirty_rects[i].left; > >- qxl_dirty_rects[i].bottom = dirty_rects[i].bottom; > >- qxl_dirty_rects[i].right = dirty_rects[i].right; > >- } > >+static void qxl_worker_update_area(QXLWorker *qxl_worker, uint32_t > >surface_id, > >+ QXLRect *qxl_area, QXLRect > >*qxl_dirty_rects, > >+ uint32_t num_dirty_rects, uint32_t > >clear_dirty_region) > >+{ > >+ qxl_worker_update_area_helper(qxl_worker, surface_id, qxl_area, > >qxl_dirty_rects, num_dirty_rects, > >+ clear_dirty_region, 0); > >+} > > > >- free(dirty_rects); > >- free(area); > >+static void qxl_worker_update_area_async(QXLWorker *qxl_worker, uint32_t > >surface_id, > >+ QXLRect *qxl_area, QXLRect > >*qxl_dirty_rects, > >+ uint32_t num_dirty_rects, uint32_t > >clear_dirty_region) > >+{ > >+ qxl_worker_update_area_helper(qxl_worker, surface_id, qxl_area, > >qxl_dirty_rects, num_dirty_rects, > >+ clear_dirty_region, 1); > > } > > > >+ > > static void qxl_worker_add_memslot(QXLWorker *qxl_worker, QXLDevMemSlot > > *mem_slot) > > { > > RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; > >@@ -252,6 +263,15 @@ static void qxl_worker_add_memslot(QXLWorker > >*qxl_worker, QXLDevMemSlot *mem_slo > > ASSERT(message == RED_WORKER_MESSAGE_READY); > > } > > > >+static void qxl_worker_add_memslot_async(QXLWorker *qxl_worker, > >QXLDevMemSlot *mem_slot) > >+{ > >+ RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; > >+ RedWorkerMessage message = RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC; > >+ > >+ write_message(dispatcher->channel,&message); > >+ send_data(dispatcher->channel, mem_slot, sizeof(QXLDevMemSlot)); > >+} > >+ > > static void qxl_worker_del_memslot(QXLWorker *qxl_worker, uint32_t > > slot_group_id, uint32_t slot_id) > > { > > RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; > >@@ -272,16 +292,34 @@ static void qxl_worker_destroy_surfaces(QXLWorker > >*qxl_worker) > > ASSERT(message == RED_WORKER_MESSAGE_READY); > > } > > > >-static void qxl_worker_destroy_primary(QXLWorker *qxl_worker, uint32_t > >surface_id) > >+static void qxl_worker_destroy_surfaces_async(QXLWorker *qxl_worker) > > { > > RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; > >- RedWorkerMessage message = RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE; > >+ RedWorkerMessage message = RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC; > >+ > >+ write_message(dispatcher->channel,&message); > >+} > >+ > >+static void qxl_worker_destroy_primary_surface_helper(QXLWorker > >*qxl_worker, uint32_t surface_id, > >+ int async) > >+{ > >+ RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; > >+ RedWorkerMessage message; > >+ > >+ if (async) { > >+ message = RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC; > >+ } else { > >+ message = RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE; > >+ } > > > > write_message(dispatcher->channel,&message); > > send_data(dispatcher->channel,&surface_id, sizeof(uint32_t)); > >- read_message(dispatcher->channel,&message); > >- ASSERT(message == RED_WORKER_MESSAGE_READY); > >+ if (!async) { > >+ read_message(dispatcher->channel,&message); > >+ ASSERT(message == RED_WORKER_MESSAGE_READY); > >+ } > > > >+ /* in async case this is set before primary is destroyed in worker */ > > dispatcher->x_res = 0; > > dispatcher->y_res = 0; > > dispatcher->use_hardware_cursor = FALSE; > >@@ -290,11 +328,27 @@ static void qxl_worker_destroy_primary(QXLWorker > >*qxl_worker, uint32_t surface_i > > update_client_mouse_allowed(); > > } > > > >-static void qxl_worker_create_primary(QXLWorker *qxl_worker, uint32_t > >surface_id, > >- QXLDevSurfaceCreate *surface) > >+static void qxl_worker_destroy_primary_surface(QXLWorker *qxl_worker, > >uint32_t surface_id) > >+{ > >+ qxl_worker_destroy_primary_surface_helper(qxl_worker, surface_id, 0); > >+} > >+ > >+static void qxl_worker_destroy_primary_surface_async(QXLWorker *qxl_worker, > >uint32_t surface_id) > >+{ > >+ qxl_worker_destroy_primary_surface_helper(qxl_worker, surface_id, 1); > >+} > >+ > >+static void qxl_worker_create_primary_surface_helper(QXLWorker *qxl_worker, > >uint32_t surface_id, > >+ QXLDevSurfaceCreate *surface, int > >async) > > { > > RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; > >- RedWorkerMessage message = RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE; > >+ RedWorkerMessage message; > >+ > >+ if (async) { > >+ message = RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC; > >+ } else { > >+ message = RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE; > >+ } > > > > dispatcher->x_res = surface->width; > > dispatcher->y_res = surface->height; > >@@ -304,12 +358,26 @@ static void qxl_worker_create_primary(QXLWorker > >*qxl_worker, uint32_t surface_id > > write_message(dispatcher->channel,&message); > > send_data(dispatcher->channel,&surface_id, sizeof(uint32_t)); > > send_data(dispatcher->channel, surface, sizeof(QXLDevSurfaceCreate)); > >- read_message(dispatcher->channel,&message); > >- ASSERT(message == RED_WORKER_MESSAGE_READY); > >+ if (!async) { > >+ read_message(dispatcher->channel,&message); > >+ ASSERT(message == RED_WORKER_MESSAGE_READY); > >+ } > > > > update_client_mouse_allowed(); > > } > > > >+static void qxl_worker_create_primary_surface(QXLWorker *qxl_worker, > >uint32_t surface_id, > >+ QXLDevSurfaceCreate *surface) > >+{ > >+ qxl_worker_create_primary_surface_helper(qxl_worker, surface_id, > >surface, 0); > >+} > >+ > >+static void qxl_worker_create_primary_surface_async(QXLWorker *qxl_worker, > >uint32_t surface_id, > >+ QXLDevSurfaceCreate *surface) > >+{ > >+ qxl_worker_create_primary_surface_helper(qxl_worker, surface_id, > >surface, 1); > >+} > >+ > > static void qxl_worker_reset_image_cache(QXLWorker *qxl_worker) > > { > > RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; > >@@ -330,17 +398,37 @@ static void qxl_worker_reset_cursor(QXLWorker > >*qxl_worker) > > ASSERT(message == RED_WORKER_MESSAGE_READY); > > } > > > >-static void qxl_worker_destroy_surface_wait(QXLWorker *qxl_worker, uint32_t > >surface_id) > >+static void qxl_worker_destroy_surface_wait_helper(QXLWorker *qxl_worker, > >uint32_t surface_id, > >+ int async) > > { > > RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; > >- RedWorkerMessage message = RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT; > >+ RedWorkerMessage message; > >+ > >+ if (async ) { > >+ message = RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC; > >+ } else { > >+ message = RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT; > >+ } > > > > write_message(dispatcher->channel,&message); > > send_data(dispatcher->channel,&surface_id, sizeof(uint32_t)); > >+ if (async) { > >+ return; > >+ } > > read_message(dispatcher->channel,&message); > > ASSERT(message == RED_WORKER_MESSAGE_READY); > > } > > > >+static void qxl_worker_destroy_surface_wait(QXLWorker *qxl_worker, uint32_t > >surface_id) > >+{ > >+ qxl_worker_destroy_surface_wait_helper(qxl_worker, surface_id, 0); > >+} > >+ > >+static void qxl_worker_destroy_surface_wait_async(QXLWorker *qxl_worker, > >uint32_t surface_id) > >+{ > >+ qxl_worker_destroy_surface_wait_helper(qxl_worker, surface_id, 1); > >+} > >+ > > static void qxl_worker_reset_memslots(QXLWorker *qxl_worker) > > { > > RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; > >@@ -360,16 +448,32 @@ static void qxl_worker_wakeup(QXLWorker *qxl_worker) > > } > > } > > > >-static void qxl_worker_oom(QXLWorker *qxl_worker) > >+static void qxl_worker_oom_helper(QXLWorker *qxl_worker, int async) > > { > > RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; > >+ RedWorkerMessage message; > >+ > > if (!test_bit(RED_WORKER_PENDING_OOM, dispatcher->pending)) { > >- RedWorkerMessage message = RED_WORKER_MESSAGE_OOM; > >+ if (async) { > >+ message = RED_WORKER_MESSAGE_OOM_ASYNC; > >+ } else { > >+ message = RED_WORKER_MESSAGE_OOM; > >+ } > > set_bit(RED_WORKER_PENDING_OOM,&dispatcher->pending); > > write_message(dispatcher->channel,&message); > > } > > } > > > >+static void qxl_worker_oom(QXLWorker *qxl_worker) > >+{ > >+ qxl_worker_oom_helper(qxl_worker, 0); > >+} > >+ > >+static void qxl_worker_oom_async(QXLWorker *qxl_worker) > >+{ > >+ qxl_worker_oom_helper(qxl_worker, 1); > >+} > >+ > > static void qxl_worker_start(QXLWorker *qxl_worker) > > { > > RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; > >@@ -530,14 +634,23 @@ RedDispatcher *red_dispatcher_init(QXLInstance *qxl) > > dispatcher->base.del_memslot = qxl_worker_del_memslot; > > dispatcher->base.reset_memslots = qxl_worker_reset_memslots; > > dispatcher->base.destroy_surfaces = qxl_worker_destroy_surfaces; > >- dispatcher->base.create_primary_surface = qxl_worker_create_primary; > >- dispatcher->base.destroy_primary_surface = qxl_worker_destroy_primary; > >+ dispatcher->base.create_primary_surface = > >qxl_worker_create_primary_surface; > >+ dispatcher->base.destroy_primary_surface = > >qxl_worker_destroy_primary_surface; > > > > dispatcher->base.reset_image_cache = qxl_worker_reset_image_cache; > > dispatcher->base.reset_cursor = qxl_worker_reset_cursor; > > dispatcher->base.destroy_surface_wait = > > qxl_worker_destroy_surface_wait; > > dispatcher->base.loadvm_commands = qxl_worker_loadvm_commands; > > > >+ dispatcher->base.update_area_async = qxl_worker_update_area_async; > >+ dispatcher->base.add_memslot_async = qxl_worker_add_memslot_async; > >+ dispatcher->base.reset_memslots = qxl_worker_reset_memslots; > >+ dispatcher->base.destroy_surfaces_async = > >qxl_worker_destroy_surfaces_async; > >+ dispatcher->base.destroy_primary_surface_async = > >qxl_worker_destroy_primary_surface_async; > >+ dispatcher->base.create_primary_surface_async = > >qxl_worker_create_primary_surface_async; > >+ dispatcher->base.destroy_surface_wait_async = > >qxl_worker_destroy_surface_wait_async; > >+ dispatcher->base.oom_async = qxl_worker_oom_async; > >+ > > qxl->st->qif->get_init_info(qxl,&init_info); > > > > init_data.memslot_id_bits = init_info.memslot_id_bits; > >diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c > >index 258a541..7737c04 100644 > >--- a/server/red_parse_qxl.c > >+++ b/server/red_parse_qxl.c > >@@ -148,7 +148,7 @@ static void red_get_point16_ptr(SpicePoint16 *red, > >QXLPoint16 *qxl) > > red->y = qxl->y; > > } > > > >-void red_get_rect_ptr(SpiceRect *red, QXLRect *qxl) > >+void red_get_rect_ptr(SpiceRect *red, const QXLRect *qxl) > > { > > red->top = qxl->top; > > red->left = qxl->left; > >diff --git a/server/red_parse_qxl.h b/server/red_parse_qxl.h > >index 5de0325..a713dcf 100644 > >--- a/server/red_parse_qxl.h > >+++ b/server/red_parse_qxl.h > >@@ -110,7 +110,7 @@ typedef struct RedCursorCmd { > > uint8_t *device_data; > > } RedCursorCmd; > > > >-void red_get_rect_ptr(SpiceRect *red, QXLRect *qxl); > >+void red_get_rect_ptr(SpiceRect *red, const QXLRect *qxl); > > > > void red_get_drawable(RedMemSlotInfo *slots, int group_id, > > RedDrawable *red, QXLPHYSICAL addr, uint32_t flags); > >diff --git a/server/red_worker.c b/server/red_worker.c > >index 9a61e86..1480218 100644 > >--- a/server/red_worker.c > >+++ b/server/red_worker.c > >@@ -9417,20 +9417,24 @@ static void red_wait_pipe_item_sent(RedChannel > >*channel, PipeItem *item) > > > > static inline void handle_dev_update(RedWorker *worker) > > { > >- RedWorkerMessage message; > >- const SpiceRect *rect; > >+ const QXLRect *qxl_rect; > >+ SpiceRect *rect = spice_new0(SpiceRect, 1); > >+ QXLRect *qxl_dirty_rects; > > SpiceRect *dirty_rects; > > RedSurface *surface; > > uint32_t num_dirty_rects; > > uint32_t surface_id; > > uint32_t clear_dirty_region; > >+ int i; > > > > receive_data(worker->channel,&surface_id, sizeof(uint32_t)); > >- receive_data(worker->channel,&rect, sizeof(SpiceRect *)); > >- receive_data(worker->channel,&dirty_rects, sizeof(SpiceRect *)); > >+ receive_data(worker->channel,&qxl_rect, sizeof(QXLRect *)); > >+ receive_data(worker->channel,&qxl_dirty_rects, sizeof(QXLRect *)); > > receive_data(worker->channel,&num_dirty_rects, sizeof(uint32_t)); > > receive_data(worker->channel,&clear_dirty_region, sizeof(uint32_t)); > > > >+ dirty_rects = spice_new0(SpiceRect, num_dirty_rects); > >+ red_get_rect_ptr(rect, qxl_rect); > > flush_display_commands(worker); > > > > ASSERT(worker->running); > >@@ -9444,15 +9448,17 @@ static inline void handle_dev_update(RedWorker > >*worker) > > if (clear_dirty_region) { > > region_clear(&surface->draw_dirty_region); > > } > >- > >- message = RED_WORKER_MESSAGE_READY; > >- write_message(worker->channel,&message); > >+ for (i = 0; i< num_dirty_rects; i++) { > >+ qxl_dirty_rects[i].top = dirty_rects[i].top; > >+ qxl_dirty_rects[i].left = dirty_rects[i].left; > >+ qxl_dirty_rects[i].bottom = dirty_rects[i].bottom; > >+ qxl_dirty_rects[i].right = dirty_rects[i].right; > >+ } > > } > > > > > > static inline void handle_dev_add_memslot(RedWorker *worker) > > { > >- RedWorkerMessage message; > > QXLDevMemSlot dev_slot; > > > > receive_data(worker->channel,&dev_slot, sizeof(QXLDevMemSlot)); > >@@ -9460,9 +9466,6 @@ static inline void handle_dev_add_memslot(RedWorker > >*worker) > > red_memslot_info_add_slot(&worker->mem_slots, dev_slot.slot_group_id, > > dev_slot.slot_id, > > dev_slot.addr_delta, dev_slot.virt_start, > > dev_slot.virt_end, > > dev_slot.generation); > >- > >- message = RED_WORKER_MESSAGE_READY; > >- write_message(worker->channel,&message); > > } > > > > static inline void handle_dev_del_memslot(RedWorker *worker) > >@@ -9498,7 +9501,6 @@ static inline void destroy_surface_wait(RedWorker > >*worker, int surface_id) > > > > static inline void handle_dev_destroy_surface_wait(RedWorker *worker) > > { > >- RedWorkerMessage message; > > uint32_t surface_id; > > > > receive_data(worker->channel,&surface_id, sizeof(uint32_t)); > >@@ -9510,9 +9512,6 @@ static inline void > >handle_dev_destroy_surface_wait(RedWorker *worker) > > if (worker->surfaces[0].context.canvas) { > > destroy_surface_wait(worker, 0); > > } > >- > >- message = RED_WORKER_MESSAGE_READY; > >- write_message(worker->channel,&message); > > } > > > > static inline void red_cursor_reset(RedWorker *worker) > >@@ -9540,7 +9539,6 @@ static inline void red_cursor_reset(RedWorker *worker) > > static inline void handle_dev_destroy_surfaces(RedWorker *worker) > > { > > int i; > >- RedWorkerMessage message; > > red_printf(""); > > flush_all_qxl_commands(worker); > > //to handle better > >@@ -9563,14 +9561,10 @@ static inline void > >handle_dev_destroy_surfaces(RedWorker *worker) > > red_display_clear_glz_drawables(worker->display_channel); > > > > red_cursor_reset(worker); > >- > >- message = RED_WORKER_MESSAGE_READY; > >- write_message(worker->channel,&message); > > } > > > > static inline void handle_dev_create_primary_surface(RedWorker *worker) > > { > >- RedWorkerMessage message; > > uint32_t surface_id; > > QXLDevSurfaceCreate surface; > > uint8_t *line_0; > >@@ -9600,14 +9594,10 @@ static inline void > >handle_dev_create_primary_surface(RedWorker *worker) > > if (worker->cursor_channel) { > > red_channel_pipe_add_type(&worker->cursor_channel->common.base, > > PIPE_ITEM_TYPE_CURSOR_INIT); > > } > >- > >- message = RED_WORKER_MESSAGE_READY; > >- write_message(worker->channel,&message); > > } > > > > static inline void handle_dev_destroy_primary_surface(RedWorker *worker) > > { > >- RedWorkerMessage message; > > uint32_t surface_id; > > > > receive_data(worker->channel,&surface_id, sizeof(uint32_t)); > >@@ -9623,9 +9613,6 @@ static inline void > >handle_dev_destroy_primary_surface(RedWorker *worker) > > ASSERT(!worker->surfaces[surface_id].context.canvas); > > > > red_cursor_reset(worker); > >- > >- message = RED_WORKER_MESSAGE_READY; > >- write_message(worker->channel,&message); > > } > > > > static void handle_dev_input(EventListener *listener, uint32_t events) > >@@ -9635,10 +9622,36 @@ static void handle_dev_input(EventListener > >*listener, uint32_t events) > > RedChannel *cursor_red_channel =&worker->cursor_channel->common.base; > > RedChannel *display_red_channel =&worker->display_channel->common.base; > > int ring_is_empty; > >+ int async = 0; > >+ int write_ready = 0; > > > > read_message(worker->channel,&message); > > > >+ /* for async messages we do the common work in the handler, and > >+ * send a ready or call async_complete from here, hence the added > >switch. */ > > switch (message) { > >+ case RED_WORKER_MESSAGE_UPDATE_ASYNC: > >+ case RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC: > >+ case RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC: > >+ case RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC: > >+ case RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC: > >+ case RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC: > >+ case RED_WORKER_MESSAGE_OOM_ASYNC: > >+ async = 1; > >+ break; > >+ case RED_WORKER_MESSAGE_UPDATE: > >+ case RED_WORKER_MESSAGE_ADD_MEMSLOT: > >+ case RED_WORKER_MESSAGE_DESTROY_SURFACES: > >+ case RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE: > >+ case RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE: > >+ case RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT: > >+ write_ready = 1; > >+ default: > >+ break; > >+ } > >+ > >+ switch (message) { > >+ case RED_WORKER_MESSAGE_UPDATE_ASYNC: > > case RED_WORKER_MESSAGE_UPDATE: > > handle_dev_update(worker); > > break; > >@@ -9646,6 +9659,7 @@ static void handle_dev_input(EventListener *listener, > >uint32_t events) > > clear_bit(RED_WORKER_PENDING_WAKEUP, worker->pending); > > stat_inc_counter(worker->wakeup_counter, 1); > > break; > >+ case RED_WORKER_MESSAGE_OOM_ASYNC: > > case RED_WORKER_MESSAGE_OOM: > > ASSERT(worker->running); > > while (red_process_commands(worker, MAX_PIPE_SIZE,&ring_is_empty)) > > { > >@@ -9670,15 +9684,19 @@ static void handle_dev_input(EventListener > >*listener, uint32_t events) > > message = RED_WORKER_MESSAGE_READY; > > write_message(worker->channel,&message); > > break; > >+ case RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC: > > case RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT: > > handle_dev_destroy_surface_wait(worker); > > break; > >+ case RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC: > > case RED_WORKER_MESSAGE_DESTROY_SURFACES: > > handle_dev_destroy_surfaces(worker); > > break; > >+ case RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC: > > case RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE: > > handle_dev_create_primary_surface(worker); > > break; > >+ case RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC: > > case RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE: > > handle_dev_destroy_primary_surface(worker); > > break; > >@@ -9805,6 +9823,7 @@ static void handle_dev_input(EventListener *listener, > >uint32_t events) > > receive_data(worker->channel,&worker->mouse_mode, > > sizeof(uint32_t)); > > red_printf("mouse mode %u", worker->mouse_mode); > > break; > >+ case RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC: > > case RED_WORKER_MESSAGE_ADD_MEMSLOT: > > handle_dev_add_memslot(worker); > > break; > >@@ -9850,6 +9869,13 @@ static void handle_dev_input(EventListener *listener, > >uint32_t events) > > default: > > red_error("message error"); > > } > >+ if (async) { > >+ worker->qxl->st->qif->async_complete(worker->qxl); > >+ } > >+ if (write_ready) { > >+ message = RED_WORKER_MESSAGE_READY; > >+ write_message(worker->channel,&message); > >+ } > > } > > > > static void handle_dev_free(EventListener *ctx) > >diff --git a/server/red_worker.h b/server/red_worker.h > >index b4e2ed2..9ed7156 100644 > >--- a/server/red_worker.h > >+++ b/server/red_worker.h > >@@ -70,6 +70,14 @@ enum { > > RED_WORKER_MESSAGE_RESET_IMAGE_CACHE, > > RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT, > > RED_WORKER_MESSAGE_LOADVM_COMMANDS, > >+ /* async commands */ > >+ RED_WORKER_MESSAGE_UPDATE_ASYNC, > >+ RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC, > >+ RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC, > >+ RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC, > >+ RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC, > >+ RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC, > >+ RED_WORKER_MESSAGE_OOM_ASYNC, > > }; > > > > typedef uint32_t RedWorkerMessage; > >diff --git a/server/spice.h b/server/spice.h > >index f64ff41..f0d5685 100644 > >--- a/server/spice.h > >+++ b/server/spice.h > >@@ -122,6 +122,17 @@ struct QXLWorker { > > void (*reset_cursor)(QXLWorker *worker); > > void (*destroy_surface_wait)(QXLWorker *worker, uint32_t surface_id); > > void (*loadvm_commands)(QXLWorker *worker, struct QXLCommandExt *ext, > > uint32_t count); > >+ /* async versions of commands. when complete spice calls async_complete > >*/ > >+ void (*update_area_async)(QXLWorker *qxl_worker, uint32_t surface_id, > >+ struct QXLRect *area, struct QXLRect *dirty_rects, > >+ uint32_t num_dirty_rects, uint32_t > >clear_dirty_region); > >+ void (*add_memslot_async)(QXLWorker *worker, QXLDevMemSlot *slot); > >+ void (*destroy_surfaces_async)(QXLWorker *worker); > >+ void (*destroy_primary_surface_async)(QXLWorker *worker, uint32_t > >surface_id); > >+ void (*create_primary_surface_async)(QXLWorker *worker, uint32_t > >surface_id, > >+ QXLDevSurfaceCreate *surface); > >+ void (*destroy_surface_wait_async)(QXLWorker *worker, uint32_t > >surface_id); > >+ void (*oom_async)(QXLWorker *worker); > > }; > > > > typedef struct QXLDrawArea { > >@@ -192,6 +203,7 @@ struct QXLInterface { > > int (*req_cursor_notification)(QXLInstance *qin); > > void (*notify_update)(QXLInstance *qin, uint32_t update_id); > > int (*flush_resources)(QXLInstance *qin); > >+ void (*async_complete)(QXLInstance *qin); > > }; > > > > struct QXLInstance { > _______________________________________________ Spice-devel mailing list Spice-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/spice-devel