[Spice-devel] [PATCH spice-server 1/7] char_device.c: add ref count for write-to-device buffers

Yonit Halperin yhalperi at redhat.com
Mon Nov 26 07:57:57 PST 2012


On 11/22/2012 04:58 AM, Hans de Goede wrote:
> Hi,
>
> Looks good, one minor comment though, see
> my remarks inline.
>
I'll fix it. Thanks for the review.

> 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