See: https://bugs.freedesktop.org/show_bug.cgi?id=8801 http://lists.freedesktop.org/archives/cairo/2006-December/008945.html diff -ru cairo-1.2.6/src/cairo-cache.c cairo-1.2.6-locking/src/cairo-cache.c --- cairo-1.2.6/src/cairo-cache.c 2006-11-01 03:27:38.000000000 +0100 +++ cairo-1.2.6-locking/src/cairo-cache.c 2007-01-18 20:23:06.000000000 +0100 @@ -38,6 +38,8 @@ #include "cairoint.h" +CAIRO_MUTEX_DECLARE (cairo_cache_refcount_mutex); + struct _cairo_cache { cairo_hash_table_t *hash_table; @@ -188,9 +190,11 @@ void _cairo_cache_freeze (cairo_cache_t *cache) { + CAIRO_MUTEX_LOCK (cairo_cache_refcount_mutex); assert (cache->freeze_count >= 0); cache->freeze_count++; + CAIRO_MUTEX_UNLOCK (cairo_cache_refcount_mutex); } /** @@ -210,12 +214,14 @@ void _cairo_cache_thaw (cairo_cache_t *cache) { + CAIRO_MUTEX_LOCK (cairo_cache_refcount_mutex); assert (cache->freeze_count > 0); cache->freeze_count--; if (cache->freeze_count == 0) _cairo_cache_shrink_to_accomodate (cache, 0); + CAIRO_MUTEX_UNLOCK (cairo_cache_refcount_mutex); } /** @@ -312,16 +318,20 @@ cairo_cache_entry_t *entry) { cairo_status_t status; + CAIRO_MUTEX_LOCK (cairo_cache_refcount_mutex); _cairo_cache_shrink_to_accomodate (cache, entry->size); status = _cairo_hash_table_insert (cache->hash_table, (cairo_hash_entry_t *) entry); - if (status) + if (status){ + CAIRO_MUTEX_UNLOCK (cairo_cache_refcount_mutex); return status; + } cache->size += entry->size; + CAIRO_MUTEX_UNLOCK (cairo_cache_refcount_mutex); return CAIRO_STATUS_SUCCESS; } @@ -341,6 +351,7 @@ _cairo_cache_remove (cairo_cache_t *cache, cairo_cache_entry_t *entry) { + CAIRO_MUTEX_LOCK (cairo_cache_refcount_mutex); cache->size -= entry->size; _cairo_hash_table_remove (cache->hash_table, @@ -348,6 +359,7 @@ if (cache->entry_destroy) cache->entry_destroy (entry); + CAIRO_MUTEX_UNLOCK (cairo_cache_refcount_mutex); } /** diff -ru cairo-1.2.6/src/cairo-pattern.c cairo-1.2.6-locking/src/cairo-pattern.c --- cairo-1.2.6/src/cairo-pattern.c 2006-11-02 23:53:40.000000000 +0100 +++ cairo-1.2.6-locking/src/cairo-pattern.c 2007-01-18 20:23:06.000000000 +0100 @@ -29,6 +29,8 @@ #include "cairoint.h" +CAIRO_MUTEX_DECLARE (cairo_pattern_refcount_mutex); + const cairo_solid_pattern_t cairo_pattern_nil = { { CAIRO_PATTERN_TYPE_SOLID, /* type */ CAIRO_REF_COUNT_INVALID, /* ref_count */ @@ -497,13 +499,18 @@ if (pattern == NULL) return NULL; - if (pattern->ref_count == CAIRO_REF_COUNT_INVALID) + CAIRO_MUTEX_LOCK (cairo_pattern_refcount_mutex); + + if (pattern->ref_count == CAIRO_REF_COUNT_INVALID){ + CAIRO_MUTEX_UNLOCK (cairo_pattern_refcount_mutex); return pattern; + } assert (pattern->ref_count > 0); pattern->ref_count++; + CAIRO_MUTEX_UNLOCK (cairo_pattern_refcount_mutex); return pattern; } slim_hidden_def (cairo_pattern_reference); @@ -557,17 +564,23 @@ if (pattern == NULL) return; - if (pattern->ref_count == CAIRO_REF_COUNT_INVALID) + CAIRO_MUTEX_LOCK (cairo_pattern_refcount_mutex); + if (pattern->ref_count == CAIRO_REF_COUNT_INVALID){ + CAIRO_MUTEX_UNLOCK (cairo_pattern_refcount_mutex); return; + } assert (pattern->ref_count > 0); pattern->ref_count--; - if (pattern->ref_count) + if (pattern->ref_count){ + CAIRO_MUTEX_UNLOCK (cairo_pattern_refcount_mutex); return; + } _cairo_pattern_fini (pattern); free (pattern); + CAIRO_MUTEX_UNLOCK (cairo_pattern_refcount_mutex); } slim_hidden_def (cairo_pattern_destroy); diff -ru cairo-1.2.6/src/cairo-scaled-font.c cairo-1.2.6-locking/src/cairo-scaled-font.c --- cairo-1.2.6/src/cairo-scaled-font.c 2006-11-01 03:27:38.000000000 +0100 +++ cairo-1.2.6-locking/src/cairo-scaled-font.c 2007-01-18 20:23:06.000000000 +0100 @@ -906,6 +906,8 @@ if (scaled_font->status) return scaled_font->status; + _cairo_scaled_font_freeze_cache (scaled_font); + if (scaled_font->backend->show_glyphs != NULL) { status = scaled_font->backend->show_glyphs (scaled_font, op, pattern, @@ -914,16 +916,16 @@ dest_x, dest_y, width, height, glyphs, num_glyphs); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) + if (status != CAIRO_INT_STATUS_UNSUPPORTED){ + _cairo_scaled_font_thaw_cache (scaled_font); return status; + } } /* Font display routine either does not exist or failed. */ status = CAIRO_STATUS_SUCCESS; - _cairo_cache_freeze (scaled_font->glyphs); - for (i = 0; i < num_glyphs; i++) { int x, y; cairo_surface_pattern_t glyph_pattern; @@ -1005,7 +1007,7 @@ } CLEANUP_MASK: - _cairo_cache_thaw (scaled_font->glyphs); + _cairo_scaled_font_thaw_cache (scaled_font); if (mask != NULL) cairo_surface_destroy (mask); diff -ru cairo-1.2.6/src/cairo-surface.c cairo-1.2.6-locking/src/cairo-surface.c --- cairo-1.2.6/src/cairo-surface.c 2006-11-02 23:53:40.000000000 +0100 +++ cairo-1.2.6-locking/src/cairo-surface.c 2007-01-18 20:23:06.000000000 +0100 @@ -41,6 +41,8 @@ #include "cairo-surface-fallback-private.h" #include "cairo-clip-private.h" +CAIRO_MUTEX_DECLARE (cairo_surface_refcount_mutex); + const cairo_surface_t _cairo_surface_nil = { &cairo_image_surface_backend, /* backend */ CAIRO_SURFACE_TYPE_IMAGE, @@ -410,13 +412,18 @@ if (surface == NULL) return NULL; - if (surface->ref_count == CAIRO_REF_COUNT_INVALID) + CAIRO_MUTEX_LOCK (cairo_surface_refcount_mutex); + + if (surface->ref_count == CAIRO_REF_COUNT_INVALID){ + CAIRO_MUTEX_UNLOCK (cairo_surface_refcount_mutex); return surface; + } assert (surface->ref_count > 0); surface->ref_count++; + CAIRO_MUTEX_UNLOCK (cairo_surface_refcount_mutex); return surface; } slim_hidden_def (cairo_surface_reference); @@ -435,20 +442,27 @@ if (surface == NULL) return; - if (surface->ref_count == CAIRO_REF_COUNT_INVALID) + CAIRO_MUTEX_LOCK (cairo_surface_refcount_mutex); + + if (surface->ref_count == CAIRO_REF_COUNT_INVALID){ + CAIRO_MUTEX_UNLOCK (cairo_surface_refcount_mutex); return; + } assert (surface->ref_count > 0); surface->ref_count--; - if (surface->ref_count) + if (surface->ref_count){ + CAIRO_MUTEX_UNLOCK (cairo_surface_refcount_mutex); return; + } cairo_surface_finish (surface); _cairo_user_data_array_fini (&surface->user_data); free (surface); + CAIRO_MUTEX_UNLOCK (cairo_surface_refcount_mutex); } slim_hidden_def(cairo_surface_destroy); diff -ru cairo-1.2.6/src/cairo-win32-surface.c cairo-1.2.6-locking/src/cairo-win32-surface.c --- cairo-1.2.6/src/cairo-win32-surface.c 2006-11-02 23:53:40.000000000 +0100 +++ cairo-1.2.6-locking/src/cairo-win32-surface.c 2007-01-18 20:24:20.000000000 +0100 @@ -1179,6 +1179,10 @@ CRITICAL_SECTION cairo_scaled_font_map_mutex; CRITICAL_SECTION cairo_ft_unscaled_font_map_mutex; +CRITICAL_SECTION cairo_cache_refcount_mutex; +CRITICAL_SECTION cairo_pattern_refcount_mutex; +CRITICAL_SECTION cairo_surface_refcount_mutex; + static int _cairo_win32_initialized = 0; void @@ -1191,6 +1195,10 @@ InitializeCriticalSection (&cairo_scaled_font_map_mutex); InitializeCriticalSection (&cairo_ft_unscaled_font_map_mutex); + InitializeCriticalSection (&cairo_cache_refcount_mutex); + InitializeCriticalSection (&cairo_pattern_refcount_mutex); + InitializeCriticalSection (&cairo_surface_refcount_mutex); + _cairo_win32_initialized = 1; } @@ -1209,6 +1217,9 @@ DeleteCriticalSection (&cairo_toy_font_face_hash_table_mutex); DeleteCriticalSection (&cairo_scaled_font_map_mutex); DeleteCriticalSection (&cairo_ft_unscaled_font_map_mutex); + DeleteCriticalSection (&cairo_cache_refcount_mutex); + DeleteCriticalSection (&cairo_pattern_refcount_mutex); + DeleteCriticalSection (&cairo_surface_refcount_mutex); break; } return TRUE;