[Spice-devel] [PATCH v1 09/10] DCC: change how fill_bits() marshalls data by reference

Frediano Ziglio fziglio at redhat.com
Fri Dec 16 09:25:21 UTC 2016


> 
> On Wed, 2016-12-14 at 16:03 -0500, Frediano Ziglio wrote:
> > > 
> > > 
> > > The fill_bits() function marshalls some data by reference. This
> > > data is
> > > owned by the RedDrawable that is owned by the Drawable that is
> > > owned by
> > > the RedDrawablePipeItem.  Instead of keeping the RedPipeItem alive
> > > by
> > > passing it to red_channel_client_init_send_data(), simply reference
> > > the
> > > Drawable and marshall it with _add_by_ref_full(). This means that
> > > we
> > > can't use  the _add_chunks_by_ref() convenience function since that
> > > function doesn't allow us to pass a free function to clean up the
> > > data
> > > after it is sent.
> > > 
> > > This change is not perfect since the fill_bits() function makes an
> > > assumption that 'simage' is owned by the 'drawable'. On the other
> > > hand,
> > > the previous code made a much bigger assumption: that the caller
> > > would
> > > ensure that the data would be kept alive
> > > ---
> > >  server/dcc-send.c | 55
> > >  ++++++++++++++++++++++++++++++++++++++-----------------
> > >  1 file changed, 38 insertions(+), 17 deletions(-)
> > > 
> > > diff --git a/server/dcc-send.c b/server/dcc-send.c
> > > index db42ab8..09a2bb4 100644
> > > --- a/server/dcc-send.c
> > > +++ b/server/dcc-send.c
> > > @@ -343,8 +343,17 @@ static void
> > > marshaller_add_compressed(SpiceMarshaller
> > > *m,
> > >      } while (max);
> > >  }
> > >  
> > > +static void marshaller_unref_drawable(uint8_t *data, void *opaque)
> > > +{
> > > +    Drawable *drawable = opaque;
> > > +    drawable_unref(drawable);
> > > +}
> > > +
> > 
> > This function is copied multiple times. Should be defined and reused.
> 
> I don't think this function is really copied multiple times. In other
> files, it's generally a RedPipeItem that is being referenced and
> unreferenced. In this file, it's a Drawable.
> 
> I thought about making the helper function for unreffing a RedPipeItem
> accessible from different files, but I couldn't decide on a good place
> to put it. The signature of the function is pretty marshaller-specific,
> so I'm not sure that I'd want to put that function in red-pipe-item.h.
> But maybe...
> 
> > 
> > > 
> > >  /* if the number of times fill_bits can be called per one
> > > qxl_drawable
> > >  increases -
> > >     MAX_LZ_DRAWABLE_INSTANCES must be increased as well */
> > > +/* NOTE: 'simage' should be owned by the drawable. The drawable
> > > will be kept
> > > + * alive until the marshalled message has been sent. See comments
> > > below for
> > > + * more information */
> > >  static FillBitsType fill_bits(DisplayChannelClient *dcc,
> > > SpiceMarshaller *m,
> > >                                SpiceImage *simage, Drawable
> > > *drawable, int
> > >                                can_lossy)
> > >  {
> > > @@ -449,7 +458,14 @@ static FillBitsType
> > > fill_bits(DisplayChannelClient *dcc,
> > > SpiceMarshaller *m,
> > >                  spice_marshall_Palette(bitmap_palette_out,
> > > palette);
> > >              }
> > >  
> > > -            spice_marshaller_add_chunks_by_ref(m, bitmap->data);
> > > +            /* 'drawable' owns this bitmap data, so it must be
> > > kept
> > > +             * alive until the message is sent. */
> > > +            for (unsigned int i = 0; i < bitmap->data->num_chunks;
> > > i++) {
> > > +                drawable->refs++;
> > > +                spice_marshaller_add_by_ref_full(m,
> > > bitmap->data->chunk[i].data,
> > > +                                                 bitmap->data-
> > > >chunk[i].len,
> > > +                                                 marshaller_unref_
> > > drawable,
> > > drawable);
> > > +            }
> > 
> > could this became a function? Or perhaps adding a
> > spice_marshaller_add_chunks_by_ref_full?
> > I think just adding a reference for the last chunk is enough (but
> > this is an optimization).
> 
> Yeah, I was initially going to add a _add_chunks_by_ref_full()
> function, but didn't because I was thinking I'd need to add a reference
> for each chunk and that wasn't really feasible within the
> _add_chunks_by_ref_full() function (since that function doesn't know
> what object to ref). I suppose that it would be possible if you only
> add a reference for the last chunk, but that feels a bit hacky to me.
> 
> You'd end up with something like:
> 
> void spice_marshaller_add_chunks_by_ref_full(SpiceMarshaller *m,
> SpiceChunks *chunks, free_func, opaque) {
>     unsigned int i;
> 
>     for (i = 0; i < chunks->num_chunks; i++) {
>     	if (last_chunk)
> 		spice_marshaller_add_by_ref_full(...)
> 	else
> 		spice_marshaller_add_by_ref(...)
>     }
> }
> 
> 
> 
> > 
> > > 
> > >              pthread_mutex_unlock(&dcc->priv->pixmap_cache->lock);
> > >              return FILL_BITS_TYPE_BITMAP;
> > >          } else {
> > > @@ -481,7 +497,14 @@ static FillBitsType
> > > fill_bits(DisplayChannelClient *dcc,
> > > SpiceMarshaller *m,
> > >                               &bitmap_palette_out,
> > > &lzplt_palette_out);
> > >          spice_assert(bitmap_palette_out == NULL);
> > >          spice_assert(lzplt_palette_out == NULL);
> > > -        spice_marshaller_add_chunks_by_ref(m, image.u.quic.data);
> > > +        /* 'drawable' owns this image data, so it must be kept
> > > +         * alive until the message is sent. */
> > > +        for (unsigned int i = 0; i < image.u.quic.data-
> > > >num_chunks; i++) {
> > > +            drawable->refs++;
> > > +            spice_marshaller_add_by_ref_full(m,
> > > image.u.quic.data->chunk[i].data,
> > > +
> > > image.u.quic.data->chunk[i].len,
> > > +                                             marshaller_unref_draw
> > > able,
> > > drawable);
> > > +        }
> > >          pthread_mutex_unlock(&dcc->priv->pixmap_cache->lock);
> > >          return FILL_BITS_TYPE_COMPRESS_LOSSLESS;
> > >      default:
> > > @@ -531,7 +554,7 @@ static void
> > > marshall_qxl_draw_fill(RedChannelClient *rcc,
> > >      SpiceMarshaller *mask_bitmap_out;
> > >      SpiceFill fill;
> > >  
> > > -    red_channel_client_init_send_data(rcc,
> > > SPICE_MSG_DISPLAY_DRAW_FILL,
> > > &dpi->dpi_pipe_item);
> > > +    red_channel_client_init_send_data(rcc,
> > > SPICE_MSG_DISPLAY_DRAW_FILL,
> > > NULL);
> > >      fill_base(base_marshaller, item);
> > >      fill = drawable->u.fill;
> > >      spice_marshall_Fill(base_marshaller,
> > 
> > Could this cause some problem destroying the primary surface?
> > Deleting a surface causes dpi to be deleted and a check on Drawables
> > (if I remember).
> 
> Hmm, I didn't notice any potential problems here. Can you be a little
> more specific about what you think the problem might be?
> 
> Jonathon
> 

This could be related :(

(process:9392): Spice-ERROR **: display-channel.c:1835:display_channel_destroy_surfaces: assertion `!display->priv->surfaces[i].context.canvas' failed

Didn't narrow down. I was just starting a Windows 7 machine with 4 monitors (I don't know if the monitor information is related).

Frediano


More information about the Spice-devel mailing list