[Spice-devel] [PATCH spice-server 1/7] char_device.c: add ref count for write-to-device buffers
Hans de Goede
hdegoede at redhat.com
Thu Nov 22 01:58:15 PST 2012
Hi,
Looks good, one minor comment though, see
my remarks inline.
On 11/21/2012 08:42 PM, Yonit Halperin wrote:
> The ref count is used in order to keep buffers that were in the write
> queue and now are part of migration data, in case the char_device state
> is destroyed before we complete sending the migration data.
> ---
> server/char_device.c | 51 +++++++++++++++++++++++++++++++++++++++++----------
> server/char_device.h | 1 +
> 2 files changed, 42 insertions(+), 10 deletions(-)
>
> diff --git a/server/char_device.c b/server/char_device.c
> index 141ec88..1c48719 100644
> --- a/server/char_device.c
> +++ b/server/char_device.c
> @@ -86,6 +86,14 @@ typedef struct SpiceCharDeviceMsgToClientItem {
> SpiceCharDeviceMsgToClient *msg;
> } SpiceCharDeviceMsgToClientItem;
>
> +static void spice_char_device_write_buffer_free(SpiceCharDeviceWriteBuffer *buf)
> +{
> + if (--buf->refs == 0) {
> + free(buf->buf);
> + free(buf);
> + }
> +}
> +
> static void write_buffers_queue_free(Ring *write_queue)
> {
> while (!ring_is_empty(write_queue)) {
> @@ -94,18 +102,21 @@ static void write_buffers_queue_free(Ring *write_queue)
>
> ring_remove(item);
> buf = SPICE_CONTAINEROF(item, SpiceCharDeviceWriteBuffer, link);
> - free(buf->buf);
> - free(buf);
> + spice_char_device_write_buffer_free(buf);
> }
> }
>
> static void spice_char_device_write_buffer_pool_add(SpiceCharDeviceState *dev,
> SpiceCharDeviceWriteBuffer *buf)
> {
> - buf->buf_used = 0;
> - buf->origin = WRITE_BUFFER_ORIGIN_NONE;
> - buf->client = NULL;
> - ring_add(&dev->write_bufs_pool, &buf->link);
> + if (buf->refs == 1) {
> + buf->buf_used = 0;
> + buf->origin = WRITE_BUFFER_ORIGIN_NONE;
> + buf->client = NULL;
> + ring_add(&dev->write_bufs_pool, &buf->link);
> + } else {
> + --buf->refs;
> + }
> }
>
> static void spice_char_device_client_send_queue_free(SpiceCharDeviceState *dev,
> @@ -530,6 +541,7 @@ static SpiceCharDeviceWriteBuffer *__spice_char_device_write_buffer_get(SpiceCha
> }
>
> ret->token_price = migrated_data_tokens ? migrated_data_tokens : 1;
> + ret->refs = 1;
> return ret;
> error:
> ring_add(&dev->write_bufs_pool, &ret->link);
> @@ -542,6 +554,14 @@ SpiceCharDeviceWriteBuffer *spice_char_device_write_buffer_get(SpiceCharDeviceSt
> {
> return __spice_char_device_write_buffer_get(dev, client, size, 0);
> }
> +
> +static void spice_char_device_write_buffer_ref(SpiceCharDeviceWriteBuffer *write_buf)
> +{
> + spice_assert(write_buf);
> +
> + write_buf->refs++;
> +}
> +
It is common for ref functions to return a pointer to the object they have just reffed, ie:
static SpiceCharDeviceWriteBuffer *spice_char_device_write_buffer_ref(SpiceCharDeviceWriteBuffer *write_buf)
{
spice_assert(write_buf);
write_buf->refs++;
return write_buf;
}
> void spice_char_device_write_buffer_add(SpiceCharDeviceState *dev,
> SpiceCharDeviceWriteBuffer *write_buf)
> {
> @@ -677,7 +697,7 @@ void spice_char_device_state_destroy(SpiceCharDeviceState *char_dev)
> spice_char_device_client_free(char_dev, dev_client);
> }
> char_dev->running = FALSE;
> -
> +
> spice_char_device_state_unref(char_dev);
> }
>
> @@ -826,6 +846,13 @@ void spice_char_device_state_migrate_data_marshall_empty(SpiceMarshaller *m)
> mig_data->connected = FALSE;
> }
>
> +static void migrate_data_marshaller_write_buffer_free(uint8_t *data, void *opaque)
> +{
> + SpiceCharDeviceWriteBuffer *write_buf = (SpiceCharDeviceWriteBuffer *)opaque;
> +
> + spice_char_device_write_buffer_free(write_buf);
> +}
> +
> void spice_char_device_state_migrate_data_marshall(SpiceCharDeviceState *dev,
> SpiceMarshaller *m)
> {
> @@ -857,8 +884,10 @@ void spice_char_device_state_migrate_data_marshall(SpiceCharDeviceState *dev,
> if (dev->cur_write_buf) {
> uint32_t buf_remaining = dev->cur_write_buf->buf + dev->cur_write_buf->buf_used -
> dev->cur_write_buf_pos;
> -
> - spice_marshaller_add_ref(m2, dev->cur_write_buf_pos, buf_remaining);
> + spice_char_device_write_buffer_ref(dev->cur_write_buf);
> + spice_marshaller_add_ref_full(m2, dev->cur_write_buf_pos, buf_remaining,
> + migrate_data_marshaller_write_buffer_free,
> + dev->cur_write_buf);
With the above ref change, this could be written as:
spice_marshaller_add_ref_full(m2, dev->cur_write_buf_pos, buf_remaining,
migrate_data_marshaller_write_buffer_free,
spice_char_device_write_buffer_ref(dev->cur_write_buf));
Which IMHO is more readable.
> *write_to_dev_size_ptr += buf_remaining;
> if (dev->cur_write_buf->origin == WRITE_BUFFER_ORIGIN_CLIENT) {
> spice_assert(dev->cur_write_buf->client == client_state->client);
> @@ -870,7 +899,9 @@ void spice_char_device_state_migrate_data_marshall(SpiceCharDeviceState *dev,
> SpiceCharDeviceWriteBuffer *write_buf;
>
> write_buf = SPICE_CONTAINEROF(item, SpiceCharDeviceWriteBuffer, link);
> - spice_marshaller_add_ref(m2, write_buf->buf, write_buf->buf_used);
> + spice_char_device_write_buffer_ref(write_buf);
> + spice_marshaller_add_ref_full(m2, write_buf->buf, write_buf->buf_used,
> + migrate_data_marshaller_write_buffer_free, write_buf);
> *write_to_dev_size_ptr += write_buf->buf_used;
> if (write_buf->origin == WRITE_BUFFER_ORIGIN_CLIENT) {
> spice_assert(write_buf->client == client_state->client);
Idem.
> diff --git a/server/char_device.h b/server/char_device.h
> index d6d75e3..8bfe4ec 100644
> --- a/server/char_device.h
> +++ b/server/char_device.h
> @@ -73,6 +73,7 @@ typedef struct SpiceCharDeviceWriteBuffer {
> uint32_t buf_size;
> uint32_t buf_used;
> uint32_t token_price;
> + uint32_t refs;
> } SpiceCharDeviceWriteBuffer;
>
> typedef void SpiceCharDeviceMsgToClient;
>
Regards,
Hans
More information about the Spice-devel
mailing list