[cairo] [PATCH] scaled-font: Hold the scaled font mutex whilst reaping from the global cache

Chris Wilson chris at chris-wilson.co.uk
Tue Jan 8 03:26:56 PST 2013


If we need to reap the global cache, this will call back into the scaled
font to free the glyph page. We therefore need to be careful not to run
concurrently with a user adding to the glyph page, ergo we need locking.
To complicate matters we need to be wary of a lock-inversion as we hold
the scaled_font lock whilst thawing the global cache. We prevent the
deadlock by careful ordering of the thaw-unlock and by inspecting the
current frozen state of the scaled-font before releasing the glyph
page.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 src/cairo-scaled-font.c |   10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index dc6a6fd..e1cb095 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -449,6 +449,7 @@ _cairo_scaled_font_map_destroy (void)
  CLEANUP_MUTEX_LOCK:
     CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
 }
+
 static void
 _cairo_scaled_glyph_page_destroy (void *closure)
 {
@@ -459,11 +460,16 @@ _cairo_scaled_glyph_page_destroy (void *closure)
     assert (! cairo_list_is_empty (&page->link));
 
     scaled_font = (cairo_scaled_font_t *) page->cache_entry.hash;
+    assert (!scaled_font->cache_frozen);
+    assert (!scaled_font->global_cache_frozen);
+
+    CAIRO_MUTEX_LOCK(scaled_font->mutex);
     for (n = 0; n < page->num_glyphs; n++) {
 	_cairo_hash_table_remove (scaled_font->glyphs,
 				  &page->glyphs[n].hash_entry);
 	_cairo_scaled_glyph_fini (scaled_font, &page->glyphs[n]);
     }
+    CAIRO_MUTEX_UNLOCK(scaled_font->mutex);
 
     cairo_list_del (&page->link);
 
@@ -788,16 +794,14 @@ _cairo_scaled_font_freeze_cache (cairo_scaled_font_t *scaled_font)
 void
 _cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font)
 {
-    scaled_font->cache_frozen = FALSE;
-
     if (scaled_font->global_cache_frozen) {
 	CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
 	_cairo_cache_thaw (&cairo_scaled_glyph_page_cache);
 	CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
-
 	scaled_font->global_cache_frozen = FALSE;
     }
 
+    scaled_font->cache_frozen = FALSE;
     CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
 }
 
-- 
1.7.10.4



More information about the cairo mailing list