From 75ab0c6817715725fcc023236e4688851a1bd0cf Mon Sep 17 00:00:00 2001 From: Marc-AndrĂ© Lureau Date: Tue, 24 Sep 2013 17:29:00 +0200 Subject: worker: move more free_glz_drawable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Fabiano FidĂȘncio Acked-by: Frediano Ziglio --- server/dcc-encoders.c | 55 ++++++++++++++++++++++++++++++++++++++ server/dcc-encoders.h | 7 +++-- server/display-channel.c | 22 +++++++++++---- server/display-channel.h | 1 + server/red_worker.c | 69 ------------------------------------------------ 5 files changed, 78 insertions(+), 76 deletions(-) diff --git a/server/dcc-encoders.c b/server/dcc-encoders.c index 59b2c155..f5e4dc56 100644 --- a/server/dcc-encoders.c +++ b/server/dcc-encoders.c @@ -484,6 +484,39 @@ void dcc_free_glz_drawable_instance(DisplayChannelClient *dcc, } } +/* + * Releases all the instances of the drawable from the dictionary and the display channel client. + * The release of the last instance will also release the drawable itself and the qxl drawable + * if possible. + * NOTE - the caller should prevent encoding using the dictionary during this operation + */ +void dcc_free_glz_drawable(DisplayChannelClient *dcc, RedGlzDrawable *drawable) +{ + RingItem *head_instance = ring_get_head(&drawable->instances); + int cont = (head_instance != NULL); + + while (cont) { + if (drawable->instances_count == 1) { + /* Last instance: dcc_free_glz_drawable_instance will free the drawable */ + cont = FALSE; + } + GlzDrawableInstanceItem *instance = SPICE_CONTAINEROF(head_instance, + GlzDrawableInstanceItem, + glz_link); + if (!ring_item_is_linked(&instance->free_link)) { + // the instance didn't get out from window yet + glz_enc_dictionary_remove_image(dcc->glz_dict->dict, + instance->context, + &dcc->glz_data.usr); + } + dcc_free_glz_drawable_instance(dcc, instance); + + if (cont) { + head_instance = ring_get_head(&drawable->instances); + } + } +} + void dcc_free_glz_drawables_to_free(DisplayChannelClient* dcc) { RingItem *ring_link; @@ -501,6 +534,28 @@ void dcc_free_glz_drawables_to_free(DisplayChannelClient* dcc) pthread_mutex_unlock(&dcc->glz_drawables_inst_to_free_lock); } +/* Clear all lz drawables - enforce their removal from the global dictionary. + NOTE - prevents encoding using the dictionary during the operation*/ +void dcc_free_glz_drawables(DisplayChannelClient *dcc) +{ + RingItem *ring_link; + GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL; + + if (!glz_dict) { + return; + } + + // assure no display channel is during global lz encoding + pthread_rwlock_wrlock(&glz_dict->encode_lock); + while ((ring_link = ring_get_head(&dcc->glz_drawables))) { + RedGlzDrawable *drawable = SPICE_CONTAINEROF(ring_link, RedGlzDrawable, link); + // no need to lock the to_free list, since we assured no other thread is encoding and + // thus not other thread access the to_free list of the channel + dcc_free_glz_drawable(dcc, drawable); + } + pthread_rwlock_unlock(&glz_dict->encode_lock); +} + void dcc_freeze_glz(DisplayChannelClient *dcc) { pthread_rwlock_wrlock(&dcc->glz_dict->encode_lock); diff --git a/server/dcc-encoders.h b/server/dcc-encoders.h index 4530e193..6c19cf42 100644 --- a/server/dcc-encoders.h +++ b/server/dcc-encoders.h @@ -34,11 +34,16 @@ typedef struct RedCompressBuf RedCompressBuf; typedef struct GlzDrawableInstanceItem GlzDrawableInstanceItem; +typedef struct RedGlzDrawable RedGlzDrawable; + void dcc_encoders_init (DisplayChannelClient *dcc); void dcc_encoders_free (DisplayChannelClient *dcc); void dcc_free_glz_drawable_instance (DisplayChannelClient *dcc, GlzDrawableInstanceItem *item); +void dcc_free_glz_drawable (DisplayChannelClient *dcc, + RedGlzDrawable *drawable); +void dcc_free_glz_drawables (DisplayChannelClient *dcc); void dcc_free_glz_drawables_to_free (DisplayChannelClient* dcc); void dcc_freeze_glz (DisplayChannelClient *dcc); @@ -126,8 +131,6 @@ typedef struct { #define MAX_GLZ_DRAWABLE_INSTANCES 2 -typedef struct RedGlzDrawable RedGlzDrawable; - /* for each qxl drawable, there may be several instances of lz drawables */ /* TODO - reuse this stuff for the top level. I just added a second level of multiplicity * at the Drawable by keeping a ring, so: diff --git a/server/display-channel.c b/server/display-channel.c index 3b7a0164..d455a0db 100644 --- a/server/display-channel.c +++ b/server/display-channel.c @@ -850,14 +850,26 @@ void display_channel_flush_all_surfaces(DisplayChannel *display) } } -static void rcc_free_glz_drawables_to_free(RedChannelClient *rcc) +void display_channel_free_glz_drawables_to_free(DisplayChannel *display) { - DisplayChannelClient *dcc = RCC_TO_DCC(rcc); + RingItem *link, *next; + DisplayChannelClient *dcc; - dcc_free_glz_drawables_to_free(dcc); + spice_return_if_fail(display); + + DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(display)) { + dcc_free_glz_drawables_to_free(dcc); + } } -void display_channel_free_glz_drawables_to_free(DisplayChannel *display) +void display_channel_free_glz_drawables(DisplayChannel *display) { - red_channel_apply_clients(RED_CHANNEL(display), rcc_free_glz_drawables_to_free); + RingItem *link, *next; + DisplayChannelClient *dcc; + + spice_return_if_fail(display); + + DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(display)) { + dcc_free_glz_drawables(dcc); + } } diff --git a/server/display-channel.h b/server/display-channel.h index d47abf7f..bad61d1a 100644 --- a/server/display-channel.h +++ b/server/display-channel.h @@ -277,6 +277,7 @@ void display_channel_current_flush (DisplayCha int display_channel_wait_for_migrate_data (DisplayChannel *display); void display_channel_flush_all_surfaces (DisplayChannel *display); void display_channel_free_glz_drawables_to_free(DisplayChannel *display); +void display_channel_free_glz_drawables (DisplayChannel *display); static inline int is_equal_path(SpicePath *path1, SpicePath *path2) { diff --git a/server/red_worker.c b/server/red_worker.c index 4e342bd8..faa50ed6 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -183,7 +183,6 @@ static void red_update_area_till(DisplayChannel *display, const SpiceRect *area, static inline void display_begin_send_message(RedChannelClient *rcc); static void dcc_release_glz(DisplayChannelClient *dcc); static int red_display_free_some_independent_glz_drawables(DisplayChannelClient *dcc); -static void dcc_free_glz_drawable(DisplayChannelClient *dcc, RedGlzDrawable *drawable); static void display_channel_client_release_item_before_push(DisplayChannelClient *dcc, PipeItem *item); static void display_channel_client_release_item_after_push(DisplayChannelClient *dcc, @@ -1987,74 +1986,6 @@ static void fill_base(SpiceMarshaller *base_marshaller, Drawable *drawable) spice_marshall_DisplayBase(base_marshaller, &base); } -/* - * Releases all the instances of the drawable from the dictionary and the display channel client. - * The release of the last instance will also release the drawable itself and the qxl drawable - * if possible. - * NOTE - the caller should prevent encoding using the dictionary during this operation - */ -static void dcc_free_glz_drawable(DisplayChannelClient *dcc, RedGlzDrawable *drawable) -{ - RingItem *head_instance = ring_get_head(&drawable->instances); - int cont = (head_instance != NULL); - - while (cont) { - if (drawable->instances_count == 1) { - /* Last instance: dcc_free_glz_drawable_instance will free the drawable */ - cont = FALSE; - } - GlzDrawableInstanceItem *instance = SPICE_CONTAINEROF(head_instance, - GlzDrawableInstanceItem, - glz_link); - if (!ring_item_is_linked(&instance->free_link)) { - // the instance didn't get out from window yet - glz_enc_dictionary_remove_image(dcc->glz_dict->dict, - instance->context, - &dcc->glz_data.usr); - } - dcc_free_glz_drawable_instance(dcc, instance); - - if (cont) { - head_instance = ring_get_head(&drawable->instances); - } - } -} - -/* Clear all lz drawables - enforce their removal from the global dictionary. - NOTE - prevents encoding using the dictionary during the operation*/ -static void dcc_free_glz_drawables(DisplayChannelClient *dcc) -{ - RingItem *ring_link; - GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL; - - if (!glz_dict) { - return; - } - - // assure no display channel is during global lz encoding - pthread_rwlock_wrlock(&glz_dict->encode_lock); - while ((ring_link = ring_get_head(&dcc->glz_drawables))) { - RedGlzDrawable *drawable = SPICE_CONTAINEROF(ring_link, RedGlzDrawable, link); - // no need to lock the to_free list, since we assured no other thread is encoding and - // thus not other thread access the to_free list of the channel - dcc_free_glz_drawable(dcc, drawable); - } - pthread_rwlock_unlock(&glz_dict->encode_lock); -} - -static void display_channel_free_glz_drawables(DisplayChannel *display_channel) -{ - RingItem *link, *next; - DisplayChannelClient *dcc; - - if (!display_channel) { - return; - } - DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(display_channel)) { - dcc_free_glz_drawables(dcc); - } -} - /* * Remove from the global lz dictionary some glz_drawables that have no reference to * Drawable (their qxl drawables are released too). -- cgit