[Spice-devel] [PATCH v1 09/10] DCC: change how fill_bits() marshalls data by reference
Jonathon Jongsma
jjongsma at redhat.com
Wed Dec 14 22:10: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
More information about the Spice-devel
mailing list