[Spice-devel] [PATCH server 0.8 3/3] red_dispatcher: support concurrent asyncs

Alon Levy alevy at redhat.com
Tue Oct 11 05:55:43 PDT 2011


On Tue, Oct 11, 2011 at 02:33:06PM +0200, Marc-André Lureau wrote:
> Hi
> 

Thanks for the review.

> On Sun, Oct 9, 2011 at 4:29 PM, Alon Levy <alevy at redhat.com> wrote:
> > ---
> >  server/red_dispatcher.c |   70 +++++++++++++++++++++++++++++++++-------------
> >  1 files changed, 50 insertions(+), 20 deletions(-)
> >
> > diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
> > index a998238..8289c6b 100644
> > --- a/server/red_dispatcher.c
> > +++ b/server/red_dispatcher.c
> > @@ -40,6 +40,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;
> > @@ -51,7 +58,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;
> >  };
> > @@ -224,17 +231,27 @@ static void red_dispatcher_update_area(RedDispatcher *dispatcher, uint32_t surfa
> >     ASSERT(message == RED_WORKER_MESSAGE_READY);
> >  }
> >
> > +static AsyncCommand *push_async_command(RedDispatcher *dispatcher,
> > +                                        RedWorkerMessage message,
> > +                                        uint64_t cookie)
> > +{
> > +    AsyncCommand *async_command = spice_new(AsyncCommand, 1);
> > +
> > +    async_command->cookie = cookie;
> > +    async_command->message = message;
> > +    if (dispatcher->async_commands) {
> > +        async_command->next = dispatcher->async_commands;
> > +    }
> 
> The assignment could be unconditionnal.

Right.

> Shouldn't the function take the async_lock instead of the caller?

Right.

> 
> > +    dispatcher->async_commands = async_command;

Here (answering the last question).

> > +    return async_command;
> > +}
> > +
> >  static RedWorkerMessage red_dispatcher_async_start(RedDispatcher *dispatcher,
> > -                                                   RedWorkerMessage message)
> > +                                                   RedWorkerMessage message,
> > +                                                   uint64_t cookie)
> >  {
> >     pthread_mutex_lock(&dispatcher->async_lock);
> > -    if (dispatcher->async_message != RED_WORKER_MESSAGE_NOP) {
> > -        red_warn("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;
> > +    push_async_command(dispatcher, message, cookie);
> >     pthread_mutex_unlock(&dispatcher->async_lock);
> >     return message;
> >  }
> > @@ -246,7 +263,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;
> > @@ -265,7 +283,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;
> > @@ -306,7 +324,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;
> > @@ -347,7 +366,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;
> > @@ -374,7 +394,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;
> >         }
> > @@ -420,7 +441,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;
> >         }
> > @@ -483,7 +505,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;
> >         }
> > @@ -563,7 +586,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;
> > @@ -836,8 +860,15 @@ 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;
> >     pthread_mutex_lock(&dispatcher->async_lock);
> > -    switch (dispatcher->async_message) {
> > +    for (async_command = dispatcher->async_commands;
> > +         async_command && async_command->cookie != cookie && async_command->next;
> 
> I think the "&& async_command->next" condition is unnecessary.

Right.

> 
> > +         async_command = async_command->next) {};
> > +    if (!async_command || async_command->cookie != cookie) {
> 
> So you can only check if (!async_command)

Right.

> 
> > +        red_warn("unknown cookie");
> 
> And should return or goto fail to avoid crash later.

Right.

> 
> > +    }
> > +    switch (async_command->message) {
> >     case RED_WORKER_MESSAGE_UPDATE_ASYNC:
> >     case RED_WORKER_MESSAGE_UPDATE_DIRTY_ASYNC:
> >         break;
> > @@ -858,7 +889,7 @@ void red_dispatcher_async_complete(struct RedDispatcher *dispatcher, uint64_t co
> >     default:
> >         red_warn("unexpected message");
> >     }
> > -    dispatcher->async_message = RED_WORKER_MESSAGE_NOP;
> > +    free(async_command);
> 
> I might be missing something but where is dispatcher->async_commands updated?
> 

Answered above.

> >     pthread_mutex_unlock(&dispatcher->async_lock);
> >     dispatcher->qxl->st->qif->async_complete(dispatcher->qxl, cookie);
> >  }
> > @@ -895,7 +926,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;
> > --
> > 1.7.6.4
> >
> >
> 
> 
> 
> -- 
> Marc-André Lureau


More information about the Spice-devel mailing list