[Spice-devel] [PATCH 8/9] worker: simplify RedCompressBuf
Jonathon Jongsma
jjongsma at redhat.com
Tue Nov 17 12:47:09 PST 2015
On Tue, 2015-11-17 at 16:37 +0000, Frediano Ziglio wrote:
> From: Marc-André Lureau <marcandre.lureau at gmail.com>
>
> Make sure an allocated buffer is correctly referenced by the marshaller,
> and can't be free and reused by mistake. Simplify the code by using
> GSlice
> ---
> server/display-channel.h | 3 --
> server/red_worker.c | 111 +++++++++++-----------------------------------
> -
> 2 files changed, 25 insertions(+), 89 deletions(-)
>
> diff --git a/server/display-channel.h b/server/display-channel.h
> index a1e5947..b0af138 100644
> --- a/server/display-channel.h
> +++ b/server/display-channel.h
> @@ -81,7 +81,6 @@ struct RedCompressBuf {
> uint8_t bytes[RED_COMPRESS_BUF_SIZE];
> uint32_t words[RED_COMPRESS_BUF_SIZE / 4];
> } buf;
> - RedCompressBuf *next;
> RedCompressBuf *send_next;
> };
>
> @@ -192,8 +191,6 @@ struct DisplayChannelClient {
> uint32_t stream_outbuf_size;
> uint8_t *stream_outbuf; // caution stream buffer is also used as
> compress bufs!!!
>
> - RedCompressBuf *used_compress_bufs;
> -
> FreeList free_list;
> uint64_t pixmap_cache_items[MAX_DRAWABLE_PIXMAP_CACHE_ITEMS];
> int num_pixmap_cache_items;
> diff --git a/server/red_worker.c b/server/red_worker.c
> index 5b14836..8e3be51 100644
> --- a/server/red_worker.c
> +++ b/server/red_worker.c
> @@ -2175,16 +2175,27 @@ static void
> red_push_surface_image(DisplayChannelClient *dcc, int surface_id)
> red_channel_client_push(RED_CHANNEL_CLIENT(dcc));
> }
>
> +static RedCompressBuf *compress_buf_new(void)
> +{
> + return g_slice_new(RedCompressBuf);
> +}
> +
> +static void compress_buf_free(RedCompressBuf *buf)
> +{
> + g_slice_free(RedCompressBuf, buf);
> +}
> +
> static void marshaller_add_compressed(SpiceMarshaller *m,
> RedCompressBuf *comp_buf, size_t size)
> {
> size_t max = size;
> size_t now;
> do {
> - spice_assert(comp_buf);
> + spice_return_if_fail(comp_buf);
> now = MIN(sizeof(comp_buf->buf), max);
> max -= now;
> - spice_marshaller_add_ref(m, comp_buf->buf.bytes, now);
> + spice_marshaller_add_ref_full(m, comp_buf->buf.bytes, now,
> +
> (spice_marshaller_item_free_func)compress_buf_free, NULL);
This part makes me a little nervous. the marshaller will free the data by
calling compress_buf_free() and passing the address of comp_buf->buf.bytes. This
happens to work because buf.bytes is the very first element of the structure.
But if anybody changed the RedCompressBuf structure definition, this could
result in memory corruption. I'd be a little more comfortable if we passed
'comp_buf' as the 'opaque' parameter and used that in the free_data function.
Either that, or add a prominent comment to the RedCompressBuf struct definition
indicating that buf *must* be the first element in the structure so that nobody
accidentally changes that without thinking. The rest of the commit looks fine
to me.
> comp_buf = comp_buf->send_next;
> } while (max);
> }
> @@ -2219,66 +2230,6 @@ static inline void fill_palette(DisplayChannelClient
> *dcc,
> }
> }
>
> -static inline RedCompressBuf
> *red_display_alloc_compress_buf(DisplayChannelClient *dcc)
> -{
> - DisplayChannel *display_channel = DCC_TO_DC(dcc);
> - RedCompressBuf *ret;
> -
> - if (display_channel->free_compress_bufs) {
> - ret = display_channel->free_compress_bufs;
> - display_channel->free_compress_bufs = ret->next;
> - } else {
> - ret = spice_new(RedCompressBuf, 1);
> - }
> -
> - ret->next = dcc->send_data.used_compress_bufs;
> - dcc->send_data.used_compress_bufs = ret;
> - return ret;
> -}
> -
> -static inline void __red_display_free_compress_buf(DisplayChannel *dc,
> - RedCompressBuf *buf)
> -{
> - buf->next = dc->free_compress_bufs;
> - dc->free_compress_bufs = buf;
> -}
> -
> -static void red_display_free_compress_buf(DisplayChannelClient *dcc,
> - RedCompressBuf *buf)
> -{
> - DisplayChannel *display_channel = DCC_TO_DC(dcc);
> - RedCompressBuf **curr_used = &dcc->send_data.used_compress_bufs;
> -
> - for (;;) {
> - spice_assert(*curr_used);
> - if (*curr_used == buf) {
> - *curr_used = buf->next;
> - break;
> - }
> - curr_used = &(*curr_used)->next;
> - }
> - __red_display_free_compress_buf(display_channel, buf);
> -}
> -
> -static void red_display_reset_compress_buf(DisplayChannelClient *dcc)
> -{
> - while (dcc->send_data.used_compress_bufs) {
> - RedCompressBuf *buf = dcc->send_data.used_compress_bufs;
> - dcc->send_data.used_compress_bufs = buf->next;
> - __red_display_free_compress_buf(DCC_TO_DC(dcc), buf);
> - }
> -}
> -
> -static void red_display_destroy_compress_bufs(DisplayChannel
> *display_channel)
> -{
> - spice_assert(!red_channel_is_connected(RED_CHANNEL(display_channel)));
> - while (display_channel->free_compress_bufs) {
> - RedCompressBuf *buf = display_channel->free_compress_bufs;
> - display_channel->free_compress_bufs = buf->next;
> - free(buf);
> - }
> -}
> -
> /******************************************************
> * Global lz red drawables routines
> *******************************************************/
> @@ -2606,9 +2557,7 @@ static int encoder_usr_more_space(EncoderData *enc_data,
> uint8_t **io_ptr)
> {
> RedCompressBuf *buf;
>
> - if (!(buf = red_display_alloc_compress_buf(enc_data->dcc))) {
> - return 0;
> - }
> + buf = compress_buf_new();
> enc_data->bufs_tail->send_next = buf;
> enc_data->bufs_tail = buf;
> buf->send_next = NULL;
> @@ -2868,7 +2817,7 @@ static inline int
> red_glz_compress_image(DisplayChannelClient *dcc,
> int glz_size;
> int zlib_size;
>
> - glz_data->data.bufs_tail = red_display_alloc_compress_buf(dcc);
> + glz_data->data.bufs_tail = compress_buf_new();
> glz_data->data.bufs_head = glz_data->data.bufs_tail;
>
> if (!glz_data->data.bufs_head) {
> @@ -2904,7 +2853,7 @@ static inline int
> red_glz_compress_image(DisplayChannelClient *dcc,
> #endif
> zlib_data = &worker->zlib_data;
>
> - zlib_data->data.bufs_tail = red_display_alloc_compress_buf(dcc);
> + zlib_data->data.bufs_tail = compress_buf_new();
> zlib_data->data.bufs_head = zlib_data->data.bufs_tail;
>
> if (!zlib_data->data.bufs_head) {
> @@ -2927,7 +2876,7 @@ static inline int
> red_glz_compress_image(DisplayChannelClient *dcc,
> while (zlib_data->data.bufs_head) {
> RedCompressBuf *buf = zlib_data->data.bufs_head;
> zlib_data->data.bufs_head = buf->send_next;
> - red_display_free_compress_buf(dcc, buf);
> + compress_buf_free(buf);
> }
> goto glz;
> }
> @@ -2966,7 +2915,7 @@ static inline int
> red_lz_compress_image(DisplayChannelClient *dcc,
> stat_time_t start_time = stat_now(DCC_TO_DC(dcc)->lz_stat.clock);
> #endif
>
> - lz_data->data.bufs_tail = red_display_alloc_compress_buf(dcc);
> + lz_data->data.bufs_tail = compress_buf_new();
> lz_data->data.bufs_head = lz_data->data.bufs_tail;
>
> if (!lz_data->data.bufs_head) {
> @@ -2980,7 +2929,7 @@ static inline int
> red_lz_compress_image(DisplayChannelClient *dcc,
> while (lz_data->data.bufs_head) {
> RedCompressBuf *buf = lz_data->data.bufs_head;
> lz_data->data.bufs_head = buf->send_next;
> - red_display_free_compress_buf(dcc, buf);
> + compress_buf_free(buf);
> }
> return FALSE;
> }
> @@ -3069,7 +3018,7 @@ static int red_jpeg_compress_image(DisplayChannelClient
> *dcc, SpiceImage *dest,
> return FALSE;
> }
>
> - jpeg_data->data.bufs_tail = red_display_alloc_compress_buf(dcc);
> + jpeg_data->data.bufs_tail = compress_buf_new();
> jpeg_data->data.bufs_head = jpeg_data->data.bufs_tail;
>
> if (!jpeg_data->data.bufs_head) {
> @@ -3084,7 +3033,7 @@ static int red_jpeg_compress_image(DisplayChannelClient
> *dcc, SpiceImage *dest,
> while (jpeg_data->data.bufs_head) {
> RedCompressBuf *buf = jpeg_data->data.bufs_head;
> jpeg_data->data.bufs_head = buf->send_next;
> - red_display_free_compress_buf(dcc, buf);
> + compress_buf_free(buf);
> }
> return FALSE;
> }
> @@ -3186,7 +3135,7 @@ static int red_lz4_compress_image(DisplayChannelClient
> *dcc, SpiceImage *dest,
> stat_time_t start_time = stat_now(worker->clockid);
> #endif
>
> - lz4_data->data.bufs_tail = red_display_alloc_compress_buf(dcc);
> + lz4_data->data.bufs_tail = compress_buf_new();
> lz4_data->data.bufs_head = lz4_data->data.bufs_tail;
>
> if (!lz4_data->data.bufs_head) {
> @@ -3201,7 +3150,7 @@ static int red_lz4_compress_image(DisplayChannelClient
> *dcc, SpiceImage *dest,
> while (lz4_data->data.bufs_head) {
> RedCompressBuf *buf = lz4_data->data.bufs_head;
> lz4_data->data.bufs_head = buf->send_next;
> - red_display_free_compress_buf(dcc, buf);
> + compress_buf_free(buf);
> }
> return FALSE;
> }
> @@ -3269,13 +3218,8 @@ static inline int
> red_quic_compress_image(DisplayChannelClient *dcc, SpiceImage
> return FALSE;
> }
>
> - quic_data->data.bufs_tail = red_display_alloc_compress_buf(dcc);
> + quic_data->data.bufs_tail = compress_buf_new();
> quic_data->data.bufs_head = quic_data->data.bufs_tail;
> -
> - if (!quic_data->data.bufs_head) {
> - return FALSE;
> - }
> -
> quic_data->data.bufs_head->send_next = NULL;
> quic_data->data.dcc = dcc;
>
> @@ -3283,7 +3227,7 @@ static inline int
> red_quic_compress_image(DisplayChannelClient *dcc, SpiceImage
> while (quic_data->data.bufs_head) {
> RedCompressBuf *buf = quic_data->data.bufs_head;
> quic_data->data.bufs_head = buf->send_next;
> - red_display_free_compress_buf(dcc, buf);
> + compress_buf_free(buf);
> }
> return FALSE;
> }
> @@ -3763,7 +3707,6 @@ static void fill_attr(SpiceMarshaller *m, SpiceLineAttr
> *attr, uint32_t group_id
>
> static inline void red_display_reset_send_data(DisplayChannelClient *dcc)
> {
> - red_display_reset_compress_buf(dcc);
> dcc->send_data.free_list.res->count = 0;
> dcc->send_data.num_pixmap_cache_items = 0;
> memset(dcc->send_data.free_list.sync, 0, sizeof(dcc
> ->send_data.free_list.sync));
> @@ -5990,14 +5933,10 @@ static void
> display_channel_client_on_disconnect(RedChannelClient *rcc)
> red_release_glz(dcc);
> red_reset_palette_cache(dcc);
> free(dcc->send_data.stream_outbuf);
> - red_display_reset_compress_buf(dcc);
> free(dcc->send_data.free_list.res);
> dcc_destroy_stream_agents(dcc);
>
> // this was the last channel client
> - if (!red_channel_is_connected(rcc->channel)) {
> - red_display_destroy_compress_bufs(display);
> - }
> spice_debug("#draw=%d, #red_draw=%d, #glz_draw=%d",
> display->drawable_count, worker->red_drawable_count,
> worker->glz_drawable_count);
More information about the Spice-devel
mailing list