[Spice-devel] [spice v10 10/27] server: Make the RedDrawable refcount thread-safe

Christophe Fergeau cfergeau at redhat.com
Thu Mar 3 17:16:12 UTC 2016


On Tue, Mar 01, 2016 at 04:53:10PM +0100, Francois Gouget wrote:
> Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
> ---
> 
> In theory this could be needed by the next patch.
> 
>  server/red-parse-qxl.h | 4 ++--
>  server/red-worker.c    | 7 ++++++-
>  2 files changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/server/red-parse-qxl.h b/server/red-parse-qxl.h
> index 9c30572..220a096 100644
> --- a/server/red-parse-qxl.h
> +++ b/server/red-parse-qxl.h
> @@ -24,7 +24,7 @@
>  #include "memslot.h"
>  
>  typedef struct RedDrawable {
> -    int refs;
> +    gint refs;
>      QXLInstance *qxl;
>      QXLReleaseInfoExt release_info_ext;
>      uint32_t surface_id;
> @@ -60,7 +60,7 @@ typedef struct RedDrawable {
>  
>  static inline RedDrawable *red_drawable_ref(RedDrawable *drawable)
>  {
> -    drawable->refs++;
> +    g_atomic_int_inc(&drawable->refs);
>      return drawable;
>  }
>  
> diff --git a/server/red-worker.c b/server/red-worker.c
> index fd8eefb..f45cc3b 100644
> --- a/server/red-worker.c
> +++ b/server/red-worker.c
> @@ -124,9 +124,14 @@ static void common_release_recv_buf(RedChannelClient *rcc, uint16_t type, uint32
>  
>  void red_drawable_unref(RedDrawable *red_drawable)
>  {
> -    if (--red_drawable->refs) {
> +    gint old_refs;
> +    do {
> +        old_refs = red_drawable->refs;
> +    } while (!g_atomic_int_compare_and_exchange(&red_drawable->refs, old_refs, old_refs - 1));
> +    if (old_refs > 1) {
>          return;
>      }
> +
>      red_drawable->qxl->st->qif->release_resource(red_drawable->qxl,
>                                                   red_drawable->release_info_ext);
>      red_put_drawable(red_drawable);

Making the refcounting thread safe is one thing, but then the code
freeing the drawable needs to be thread-safe too. red_put_drawable might
be fine (only looked briefly), but release_resource which is a vfunc
provided by QEMU seems much less obvious. I think the drawable refcount
is changed in the display channel thread, so I would try to queue an
idle on its main_context, and do the unref from there. Hopefully it will
not be too messy... (and I'll mention again
g_main_context_push_thread_default which could be useful there ;) or
some thread-local storage variable).

By "queueing an idle", I mean something like
GSource *source = g_idle_source_new();
g_source_set_callback(..);
g_source_attach(source, worker->core.main_context);

Christophe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/spice-devel/attachments/20160303/57ba09f5/attachment.sig>


More information about the Spice-devel mailing list