[cairo-commit] 5 commits - configure.ac src/cairo-atomic-private.h src/cairo.c src/cairo-debug.c src/cairo-freelist.c src/cairo-gstate.c src/cairoint.h src/cairo-mutex-list-private.h src/cairo-path-fixed.c src/cairo-pattern.c src/cairo-pen.c src/cairo-polygon.c src/cairo-region.c src/cairo-scaled-font.c src/cairo-scaled-font-private.h src/cairo-stroke-style.c src/cairo-traps.c

Chris Wilson ickle at kemper.freedesktop.org
Thu Jun 4 23:37:05 PDT 2009


 configure.ac                    |    2 
 src/cairo-atomic-private.h      |    1 
 src/cairo-debug.c               |    2 
 src/cairo-freelist.c            |   19 ++-
 src/cairo-gstate.c              |    7 +
 src/cairo-mutex-list-private.h  |    1 
 src/cairo-path-fixed.c          |   10 -
 src/cairo-pattern.c             |  217 +++++++++++++++++++++++++++++-----------
 src/cairo-pen.c                 |    8 +
 src/cairo-polygon.c             |    4 
 src/cairo-region.c              |    5 
 src/cairo-scaled-font-private.h |    6 -
 src/cairo-scaled-font.c         |   33 ++++--
 src/cairo-stroke-style.c        |    6 +
 src/cairo-traps.c               |    4 
 src/cairo.c                     |    1 
 src/cairoint.h                  |    4 
 17 files changed, 241 insertions(+), 89 deletions(-)

New commits:
commit 60aefd0d634c531353c92b77b36424b142efeb93
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jun 5 07:30:13 2009 +0100

    [configure] Bump pixman dependency.
    
    Reflect was only fixed in the 0.15 series, so require at least that
    version of pixman so we can that advantage of that and drop our
    workaround.

diff --git a/configure.ac b/configure.ac
index 8afadcc..5856f59 100644
--- a/configure.ac
+++ b/configure.ac
@@ -450,7 +450,7 @@ CAIRO_ENABLE(test_surfaces, test surfaces, no)
 dnl ===========================================================================
 
 CAIRO_ENABLE_SURFACE_BACKEND(image, image, always, [
-  pixman_REQUIRES="pixman-1 >= 0.12.0"
+  pixman_REQUIRES="pixman-1 >= 0.15.0"
   PKG_CHECK_MODULES(pixman, $pixman_REQUIRES, , [AC_MSG_RESULT(no)
   use_image="no (requires $pixman_REQUIRES http://cairographics.org/releases/)"])
   image_REQUIRES=$pixman_REQUIRES
commit 9d7a7e76b8bccc2517950976bb8557cd7b955a11
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jun 4 22:19:31 2009 +0100

    [scaled-font] Close race from 16d128
    
    Whilst waiting for the fontmap lock on destruction another thread may not
    only have resurrected the font but also destroyed it acquired the lock
    first and inserted into the holdovers before the first thread resumes. So
    check that the font is not already in the holdovers array before
    inserting.

diff --git a/src/cairo-scaled-font-private.h b/src/cairo-scaled-font-private.h
index f6c9748..dc16ea8 100644
--- a/src/cairo-scaled-font-private.h
+++ b/src/cairo-scaled-font-private.h
@@ -92,9 +92,9 @@ struct _cairo_scaled_font {
     cairo_matrix_t ctm;	          /* user space => device space */
     cairo_font_options_t options;
 
-    cairo_bool_t placeholder; /*  protected by fontmap mutex */
-
-    cairo_bool_t finished;
+    unsigned int placeholder : 1; /*  protected by fontmap mutex */
+    unsigned int holdover : 1;
+    unsigned int finished : 1;
 
     /* "live" scaled_font members */
     cairo_matrix_t scale;	     /* font space => device space */
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 89fc8b0..22f4395 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -218,6 +218,7 @@ static const cairo_scaled_font_t _cairo_scaled_font_nil = {
       CAIRO_HINT_STYLE_DEFAULT,
       CAIRO_HINT_METRICS_DEFAULT} ,
     FALSE,			/* placeholder */
+    FALSE,			/* holdover */
     TRUE,			/* finished */
     { 1., 0., 0., 1., 0, 0},	/* scale */
     { 1., 0., 0., 1., 0, 0},	/* scale_inverse */
@@ -726,6 +727,7 @@ _cairo_scaled_font_init (cairo_scaled_font_t               *scaled_font,
     scaled_font->cache_frozen = FALSE;
     scaled_font->global_cache_frozen = FALSE;
 
+    scaled_font->holdover = FALSE;
     scaled_font->finished = FALSE;
 
     CAIRO_REFERENCE_COUNT_INIT (&scaled_font->ref_count, 1);
@@ -955,16 +957,20 @@ cairo_scaled_font_create (cairo_font_face_t          *font_face,
 	     * array, unless we caught the font in the middle of destruction.
 	     */
 	    if (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count)) {
-		int i;
-
-		for (i = 0; i < font_map->num_holdovers; i++)
-		    if (font_map->holdovers[i] == scaled_font)
-			break;
-		if (i < font_map->num_holdovers) {
-		    font_map->num_holdovers--;
-		    memmove (&font_map->holdovers[i],
-			     &font_map->holdovers[i+1],
-			     (font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*));
+		if (scaled_font->holdover) {
+		    int i;
+
+		    for (i = 0; i < font_map->num_holdovers; i++) {
+			if (font_map->holdovers[i] == scaled_font) {
+			    font_map->num_holdovers--;
+			    memmove (&font_map->holdovers[i],
+				     &font_map->holdovers[i+1],
+				     (font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*));
+			    break;
+			}
+		    }
+
+		    scaled_font->holdover = FALSE;
 		}
 
 		/* reset any error status */
@@ -1160,12 +1166,17 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
 	if (! scaled_font->placeholder &&
 	    scaled_font->hash_entry.hash != ZOMBIE)
 	{
+	    /* Another thread may have already inserted us into the holdovers */
+	    if (scaled_font->holdover)
+		goto unlock;
+
 	    /* Rather than immediately destroying this object, we put it into
 	     * the font_map->holdovers array in case it will get used again
 	     * soon (and is why we must hold the lock over the atomic op on
 	     * the reference count). To make room for it, we do actually
 	     * destroy the least-recently-used holdover.
 	     */
+
 	    if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS) {
 		lru = font_map->holdovers[0];
 		assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&lru->ref_count));
@@ -1180,10 +1191,12 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
 	    }
 
 	    font_map->holdovers[font_map->num_holdovers++] = scaled_font;
+	    scaled_font->holdover = TRUE;
 	} else
 	    lru = scaled_font;
     }
 
+  unlock:
     _cairo_scaled_font_map_unlock ();
 
     /* If we pulled an item from the holdovers array, (while the font
commit f4d9a4482fa1bfa37783ca139e3716c8d8649f32
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jun 4 14:13:06 2009 +0100

    [pattern] Generalise the freed pattern pool
    
    Also cache recently freed surface and gradient patterns. With thanks to
    Jonathan Morton for the inspiration and initial pointer pool code for
    pixman.

diff --git a/src/cairo-atomic-private.h b/src/cairo-atomic-private.h
index 2914a02..97e2e0f 100644
--- a/src/cairo-atomic-private.h
+++ b/src/cairo-atomic-private.h
@@ -54,6 +54,7 @@ typedef int cairo_atomic_int_t;
 # define _cairo_atomic_int_inc(x) ((void) __sync_fetch_and_add(x, 1))
 # define _cairo_atomic_int_dec_and_test(x) (__sync_fetch_and_add(x, -1) == 1)
 # define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv)
+# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv)
 
 #endif
 
diff --git a/src/cairo-mutex-list-private.h b/src/cairo-mutex-list-private.h
index 8f62cb9..a807d7a 100644
--- a/src/cairo-mutex-list-private.h
+++ b/src/cairo-mutex-list-private.h
@@ -36,7 +36,6 @@
 #define CAIRO_MUTEX_DECLARE(mutex)
 #endif
 
-CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_pattern_cache_lock)
 CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_surface_cache_lock)
 
 CAIRO_MUTEX_DECLARE (_cairo_toy_font_face_mutex)
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index a815b4b..38aa253 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -408,28 +408,101 @@ _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
 /* We use a small freed pattern cache here, because we don't want to
  * constantly reallocate simple colors. */
 #define MAX_PATTERN_CACHE_SIZE 4
-static struct {
-    cairo_solid_pattern_t *patterns[MAX_PATTERN_CACHE_SIZE];
-    int size;
-} solid_pattern_cache;
+typedef struct {
+    void *pool[MAX_PATTERN_CACHE_SIZE];
+    int top;
+} freed_pool_t;
 
-cairo_pattern_t *
-_cairo_pattern_create_solid (const cairo_color_t *color,
-			     cairo_content_t	  content)
+static freed_pool_t freed_pattern_pool[4];
+
+static void *
+_atomic_fetch (void **slot)
 {
-    cairo_solid_pattern_t *pattern = NULL;
+    return _cairo_atomic_ptr_cmpxchg (slot, *slot, NULL);
+}
+
+static cairo_bool_t
+_atomic_store (void **slot, void *pattern)
+{
+    return _cairo_atomic_ptr_cmpxchg (slot, NULL, pattern) == NULL;
+}
+
+static void *
+_freed_pattern_get (freed_pool_t *pool)
+{
+    cairo_pattern_t *pattern;
+    int i;
+
+    i = pool->top - 1;
+    if (i < 0)
+	i = 0;
+
+    pattern = _atomic_fetch (&pool->pool[i]);
+    if (pattern != NULL) {
+	pool->top = i;
+	return pattern;
+    }
+
+    /* either empty or contended */
+    for (i = ARRAY_LENGTH (pool->pool); i--;) {
+	pattern = _atomic_fetch (&pool->pool[i]);
+	if (pattern != NULL) {
+	    pool->top = i;
+	    return pattern;
+	}
+    }
+
+    /* empty */
+    pool->top = 0;
+    return NULL;
+}
 
-    CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock);
+static void
+_freed_pattern_put (freed_pool_t *pool,
+		   cairo_pattern_t *pattern)
+{
+    int i = pool->top;
 
-    if (solid_pattern_cache.size) {
-	int i = --solid_pattern_cache.size %
-	    ARRAY_LENGTH (solid_pattern_cache.patterns);
-	pattern = solid_pattern_cache.patterns[i];
-	solid_pattern_cache.patterns[i] = NULL;
+    if (_atomic_store (&pool->pool[i], pattern)) {
+	pool->top = i + 1;
+	return;
     }
 
-    CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock);
+    /* either full or contended */
+    for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) {
+	if (_atomic_store (&pool->pool[i], pattern)) {
+	    pool->top = i + 1;
+	    return;
+	}
+    }
 
+    /* full */
+    pool->top = ARRAY_LENGTH (pool->pool);
+    free (pattern);
+}
+
+static void
+_freed_patterns_reset (void)
+{
+    int i, j;
+
+    for (i = 0; i < ARRAY_LENGTH (freed_pattern_pool); i++) {
+	freed_pool_t *pool = &freed_pattern_pool[i];
+	for (j = 0; j < ARRAY_LENGTH (pool->pool); j++) {
+	    free (pool->pool[j]);
+	    pool->pool[j] = NULL;
+	}
+    }
+}
+
+cairo_pattern_t *
+_cairo_pattern_create_solid (const cairo_color_t *color,
+			     cairo_content_t	  content)
+{
+    cairo_solid_pattern_t *pattern = NULL;
+
+    pattern =
+	_freed_pattern_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SOLID]);
     if (unlikely (pattern == NULL)) {
 	/* None cached, need to create a new pattern. */
 	pattern = malloc (sizeof (cairo_solid_pattern_t));
@@ -445,23 +518,6 @@ _cairo_pattern_create_solid (const cairo_color_t *color,
     return &pattern->base;
 }
 
-static void
-_cairo_pattern_reset_solid_pattern_cache (void)
-{
-    int i;
-
-    CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock);
-
-    for (i = 0; i < MIN (ARRAY_LENGTH (solid_pattern_cache.patterns), solid_pattern_cache.size); i++) {
-	if (solid_pattern_cache.patterns[i])
-	    free (solid_pattern_cache.patterns[i]);
-	solid_pattern_cache.patterns[i] = NULL;
-    }
-    solid_pattern_cache.size = 0;
-
-    CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock);
-}
-
 static const cairo_pattern_t *
 _cairo_pattern_create_in_error (cairo_status_t status)
 {
@@ -584,10 +640,14 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface)
     if (surface->status)
 	return (cairo_pattern_t*) _cairo_pattern_create_in_error (surface->status);
 
-    pattern = malloc (sizeof (cairo_surface_pattern_t));
+    pattern =
+	_freed_pattern_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SURFACE]);
     if (unlikely (pattern == NULL)) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_pattern_t *)&_cairo_pattern_nil.base;
+	pattern = malloc (sizeof (cairo_surface_pattern_t));
+	if (unlikely (pattern == NULL)) {
+	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	    return (cairo_pattern_t *)&_cairo_pattern_nil.base;
+	}
     }
 
     CAIRO_MUTEX_INITIALIZE ();
@@ -630,10 +690,14 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
 {
     cairo_linear_pattern_t *pattern;
 
-    pattern = malloc (sizeof (cairo_linear_pattern_t));
+    pattern =
+	_freed_pattern_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_LINEAR]);
     if (unlikely (pattern == NULL)) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_pattern_t *) &_cairo_pattern_nil.base;
+	pattern = malloc (sizeof (cairo_linear_pattern_t));
+	if (unlikely (pattern == NULL)) {
+	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	    return (cairo_pattern_t *) &_cairo_pattern_nil.base;
+	}
     }
 
     CAIRO_MUTEX_INITIALIZE ();
@@ -678,10 +742,14 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0,
 {
     cairo_radial_pattern_t *pattern;
 
-    pattern = malloc (sizeof (cairo_radial_pattern_t));
+    pattern =
+	_freed_pattern_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_RADIAL]);
     if (unlikely (pattern == NULL)) {
-	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_pattern_t *) &_cairo_pattern_nil.base;
+	pattern = malloc (sizeof (cairo_radial_pattern_t));
+	if (unlikely (pattern == NULL)) {
+	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+	    return (cairo_pattern_t *) &_cairo_pattern_nil.base;
+	}
     }
 
     CAIRO_MUTEX_INITIALIZE ();
@@ -780,23 +848,7 @@ cairo_pattern_destroy (cairo_pattern_t *pattern)
     _cairo_pattern_fini (pattern);
 
     /* maintain a small cache of freed patterns */
-    if (type == CAIRO_PATTERN_TYPE_SOLID) {
-	int i;
-
-	CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock);
-
-	i = solid_pattern_cache.size++ %
-	    ARRAY_LENGTH (solid_pattern_cache.patterns);
-	/* swap an old pattern for this 'cache-hot' pattern */
-	if (solid_pattern_cache.patterns[i])
-	    free (solid_pattern_cache.patterns[i]);
-
-	solid_pattern_cache.patterns[i] = (cairo_solid_pattern_t *) pattern;
-
-	CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock);
-    } else {
-	free (pattern);
-    }
+    _freed_pattern_put (&freed_pattern_pool[type], pattern);
 }
 slim_hidden_def (cairo_pattern_destroy);
 
@@ -2931,6 +2983,6 @@ cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
 void
 _cairo_pattern_reset_static_data (void)
 {
-    _cairo_pattern_reset_solid_pattern_cache ();
+    _freed_patterns_reset ();
     _cairo_pattern_reset_solid_surface_cache ();
 }
commit 132f44dce1884c9beed8c5e6588140ee8fa9cfbe
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jun 4 14:12:20 2009 +0100

    valgrindify init/fini routines
    
    Annotate object init/fini routines to detect use-after-free for
    on-stack/embedded objects.

diff --git a/src/cairo-debug.c b/src/cairo-debug.c
index 2270249..8d310a5 100644
--- a/src/cairo-debug.c
+++ b/src/cairo-debug.c
@@ -79,8 +79,6 @@ cairo_debug_reset_static_data (void)
 }
 
 #if HAVE_VALGRIND
-#include <memcheck.h>
-
 void
 _cairo_debug_check_image_surface_is_defined (const cairo_surface_t *surface)
 {
diff --git a/src/cairo-freelist.c b/src/cairo-freelist.c
index e39a01e..f6eb4fe 100644
--- a/src/cairo-freelist.c
+++ b/src/cairo-freelist.c
@@ -24,13 +24,6 @@
 
 #include "cairo-freelist-private.h"
 
-#if HAVE_VALGRIND
-#include <memcheck.h>
-#define VG(x) x
-#else
-#define VG(x)
-#endif
-
 void
 _cairo_freelist_init (cairo_freelist_t *freelist, unsigned nodesize)
 {
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 6a1fa72..8f6f01b 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -77,6 +77,8 @@ _cairo_gstate_init (cairo_gstate_t  *gstate,
 {
     cairo_status_t status;
 
+    VG (VALGRIND_MAKE_MEM_UNDEFINED (gstate, sizeof (cairo_gstate_t)));
+
     gstate->next = NULL;
 
     gstate->op = CAIRO_GSTATE_OPERATOR_DEFAULT;
@@ -140,6 +142,8 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
 {
     cairo_status_t status;
 
+    VG (VALGRIND_MAKE_MEM_UNDEFINED (gstate, sizeof (cairo_gstate_t)));
+
     gstate->op = other->op;
 
     gstate->tolerance = other->tolerance;
@@ -212,6 +216,8 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
 
     cairo_pattern_destroy (gstate->source);
     gstate->source = NULL;
+
+    VG (VALGRIND_MAKE_MEM_NOACCESS (gstate, sizeof (cairo_gstate_t)));
 }
 
 /**
@@ -270,6 +276,7 @@ _cairo_gstate_restore (cairo_gstate_t **gstate, cairo_gstate_t **freelist)
     *gstate = top->next;
 
     _cairo_gstate_fini (top);
+    VG (VALGRIND_MAKE_MEM_UNDEFINED (&top->next, sizeof (cairo_gstate_t *)));
     top->next = *freelist;
     *freelist = top;
 
diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index a90c317..53d6cd4 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -69,6 +69,8 @@ _cairo_path_buf_add_points (cairo_path_buf_t *buf,
 void
 _cairo_path_fixed_init (cairo_path_fixed_t *path)
 {
+    VG (VALGRIND_MAKE_MEM_UNDEFINED (path, sizeof (cairo_path_fixed_t)));
+
     path->buf_head.base.next = NULL;
     path->buf_head.base.prev = NULL;
     path->buf_tail = &path->buf_head.base;
@@ -334,14 +336,8 @@ _cairo_path_fixed_fini (cairo_path_fixed_t *path)
 	buf = buf->next;
 	_cairo_path_buf_destroy (this);
     }
-    path->buf_head.base.next = NULL;
-    path->buf_head.base.prev = NULL;
-    path->buf_tail = &path->buf_head.base;
-    path->buf_head.base.num_ops = 0;
-    path->buf_head.base.num_points = 0;
 
-    path->has_current_point = FALSE;
-    path->has_curve_to = FALSE;
+    VG (VALGRIND_MAKE_MEM_NOACCESS (path, sizeof (cairo_path_fixed_t)));
 }
 
 void
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 704ae4c..a815b4b 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -96,6 +96,23 @@ _cairo_pattern_set_error (cairo_pattern_t *pattern,
 static void
 _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
 {
+#if HAVE_VALGRIND
+    switch (type) {
+    case CAIRO_PATTERN_TYPE_SOLID:
+	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t));
+	break;
+    case CAIRO_PATTERN_TYPE_SURFACE:
+	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t));
+	break;
+    case CAIRO_PATTERN_TYPE_LINEAR:
+	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t));
+	break;
+    case CAIRO_PATTERN_TYPE_RADIAL:
+	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t));
+	break;
+    }
+#endif
+
     pattern->type      = type;
     pattern->status    = CAIRO_STATUS_SUCCESS;
 
@@ -168,12 +185,16 @@ _cairo_pattern_init_copy (cairo_pattern_t	*pattern,
 	cairo_solid_pattern_t *dst = (cairo_solid_pattern_t *) pattern;
 	cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) other;
 
+	VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t)));
+
 	*dst = *src;
     } break;
     case CAIRO_PATTERN_TYPE_SURFACE: {
 	cairo_surface_pattern_t *dst = (cairo_surface_pattern_t *) pattern;
 	cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) other;
 
+	VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t)));
+
 	*dst = *src;
 	cairo_surface_reference (dst->surface);
     } break;
@@ -183,6 +204,12 @@ _cairo_pattern_init_copy (cairo_pattern_t	*pattern,
 	cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other;
 	cairo_status_t status;
 
+	if (other->type == CAIRO_PATTERN_TYPE_LINEAR) {
+	    VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t)));
+	} else {
+	    VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t)));
+	}
+
 	status = _cairo_gradient_pattern_init_copy (dst, src);
 	if (unlikely (status))
 	    return status;
@@ -250,6 +277,23 @@ _cairo_pattern_fini (cairo_pattern_t *pattern)
 	    free (gradient->stops);
     } break;
     }
+
+#if HAVE_VALGRIND
+    switch (pattern->type) {
+    case CAIRO_PATTERN_TYPE_SOLID:
+	VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_solid_pattern_t));
+	break;
+    case CAIRO_PATTERN_TYPE_SURFACE:
+	VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_surface_pattern_t));
+	break;
+    case CAIRO_PATTERN_TYPE_LINEAR:
+	VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_linear_pattern_t));
+	break;
+    case CAIRO_PATTERN_TYPE_RADIAL:
+	VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_radial_pattern_t));
+	break;
+    }
+#endif
 }
 
 cairo_status_t
@@ -721,6 +765,8 @@ slim_hidden_def (cairo_pattern_status);
 void
 cairo_pattern_destroy (cairo_pattern_t *pattern)
 {
+    cairo_pattern_type_t type;
+
     if (pattern == NULL ||
 	    CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
 	return;
@@ -730,10 +776,11 @@ cairo_pattern_destroy (cairo_pattern_t *pattern)
     if (! _cairo_reference_count_dec_and_test (&pattern->ref_count))
 	return;
 
+    type = pattern->type;
     _cairo_pattern_fini (pattern);
 
     /* maintain a small cache of freed patterns */
-    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
+    if (type == CAIRO_PATTERN_TYPE_SOLID) {
 	int i;
 
 	CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock);
diff --git a/src/cairo-pen.c b/src/cairo-pen.c
index eb66b1a..b2fd855 100644
--- a/src/cairo-pen.c
+++ b/src/cairo-pen.c
@@ -58,6 +58,8 @@ _cairo_pen_init (cairo_pen_t	*pen,
     if (CAIRO_INJECT_FAULT ())
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
+    VG (VALGRIND_MAKE_MEM_UNDEFINED (pen, sizeof (cairo_pen_t)));
+
     pen->radius = radius;
     pen->tolerance = tolerance;
 
@@ -103,13 +105,15 @@ _cairo_pen_fini (cairo_pen_t *pen)
     if (pen->vertices != pen->vertices_embedded)
 	free (pen->vertices);
 
-    pen->vertices = pen->vertices_embedded;
-    pen->num_vertices = 0;
+
+    VG (VALGRIND_MAKE_MEM_NOACCESS (pen, sizeof (cairo_pen_t)));
 }
 
 cairo_status_t
 _cairo_pen_init_copy (cairo_pen_t *pen, const cairo_pen_t *other)
 {
+    VG (VALGRIND_MAKE_MEM_UNDEFINED (pen, sizeof (cairo_pen_t)));
+
     *pen = *other;
 
     if (CAIRO_INJECT_FAULT ())
diff --git a/src/cairo-polygon.c b/src/cairo-polygon.c
index d74d098..202cb4d 100644
--- a/src/cairo-polygon.c
+++ b/src/cairo-polygon.c
@@ -39,6 +39,8 @@
 void
 _cairo_polygon_init (cairo_polygon_t *polygon)
 {
+    VG (VALGRIND_MAKE_MEM_UNDEFINED (polygon, sizeof (cairo_polygon_t)));
+
     polygon->status = CAIRO_STATUS_SUCCESS;
 
     polygon->num_edges = 0;
@@ -54,6 +56,8 @@ _cairo_polygon_fini (cairo_polygon_t *polygon)
 {
     if (polygon->edges != polygon->edges_embedded)
 	free (polygon->edges);
+
+    VG (VALGRIND_MAKE_MEM_NOACCESS (polygon, sizeof (cairo_polygon_t)));
 }
 
 /* make room for at least one more edge */
diff --git a/src/cairo-region.c b/src/cairo-region.c
index 5d1f2c5..c355b4a 100644
--- a/src/cairo-region.c
+++ b/src/cairo-region.c
@@ -79,6 +79,8 @@ _cairo_region_set_error (cairo_region_t *region,
 void
 _cairo_region_init (cairo_region_t *region)
 {
+    VG (VALGRIND_MAKE_MEM_UNDEFINED (region, sizeof (cairo_region_t)));
+
     region->status = CAIRO_STATUS_SUCCESS;
     pixman_region32_init (&region->rgn);
 }
@@ -87,6 +89,8 @@ void
 _cairo_region_init_rectangle (cairo_region_t *region,
 			      const cairo_rectangle_int_t *rectangle)
 {
+    VG (VALGRIND_MAKE_MEM_UNDEFINED (region, sizeof (cairo_region_t)));
+
     region->status = CAIRO_STATUS_SUCCESS;
     pixman_region32_init_rect (&region->rgn,
 			       rectangle->x, rectangle->y,
@@ -97,6 +101,7 @@ void
 _cairo_region_fini (cairo_region_t *region)
 {
     pixman_region32_fini (&region->rgn);
+    VG (VALGRIND_MAKE_MEM_NOACCESS (region, sizeof (cairo_region_t)));
 }
 
 /**
diff --git a/src/cairo-stroke-style.c b/src/cairo-stroke-style.c
index 462b868..9ab91e5 100644
--- a/src/cairo-stroke-style.c
+++ b/src/cairo-stroke-style.c
@@ -38,6 +38,8 @@
 void
 _cairo_stroke_style_init (cairo_stroke_style_t *style)
 {
+    VG (VALGRIND_MAKE_MEM_UNDEFINED (style, sizeof (cairo_stroke_style_t)));
+
     style->line_width = CAIRO_GSTATE_LINE_WIDTH_DEFAULT;
     style->line_cap = CAIRO_GSTATE_LINE_CAP_DEFAULT;
     style->line_join = CAIRO_GSTATE_LINE_JOIN_DEFAULT;
@@ -55,6 +57,8 @@ _cairo_stroke_style_init_copy (cairo_stroke_style_t *style,
     if (CAIRO_INJECT_FAULT ())
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
+    VG (VALGRIND_MAKE_MEM_UNDEFINED (style, sizeof (cairo_stroke_style_t)));
+
     style->line_width = other->line_width;
     style->line_cap = other->line_cap;
     style->line_join = other->line_join;
@@ -86,6 +90,8 @@ _cairo_stroke_style_fini (cairo_stroke_style_t *style)
 	style->dash = NULL;
     }
     style->num_dashes = 0;
+
+    VG (VALGRIND_MAKE_MEM_NOACCESS (style, sizeof (cairo_stroke_style_t)));
 }
 
 /*
diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index fed3f10..092bd9d 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -47,6 +47,8 @@ _compare_point_fixed_by_y (const void *av, const void *bv);
 void
 _cairo_traps_init (cairo_traps_t *traps)
 {
+    VG (VALGRIND_MAKE_MEM_UNDEFINED (traps, sizeof (cairo_traps_t)));
+
     traps->status = CAIRO_STATUS_SUCCESS;
 
     traps->num_traps = 0;
@@ -91,6 +93,8 @@ _cairo_traps_fini (cairo_traps_t *traps)
 {
     if (traps->traps != traps->traps_embedded)
 	free (traps->traps);
+
+    VG (VALGRIND_MAKE_MEM_NOACCESS (traps, sizeof (cairo_traps_t)));
 }
 
 /**
diff --git a/src/cairo.c b/src/cairo.c
index bb30e9a..0c58cfe 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -1408,6 +1408,7 @@ cairo_new_path (cairo_t *cr)
 	return;
 
     _cairo_path_fixed_fini (cr->path);
+    _cairo_path_fixed_init (cr->path);
 }
 slim_hidden_def(cairo_new_path);
 
diff --git a/src/cairoint.h b/src/cairoint.h
index c878cd2..81b1690 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2771,12 +2771,16 @@ CAIRO_END_DECLS
 #include "cairo-hash-private.h"
 
 #if HAVE_VALGRIND
+#include <memcheck.h>
+
+#define VG(x) x
 
 cairo_private void
 _cairo_debug_check_image_surface_is_defined (const cairo_surface_t *surface);
 
 #else
 
+#define VG(x)
 #define _cairo_debug_check_image_surface_is_defined(X)
 
 #endif
commit e89828c5331579d0d4019b6339df09ba1e2aa32e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jun 3 21:52:02 2009 +0100

    [freelist] valgrindify freed blocks
    
    Mark freed blocks as unaccessible upon free() and then as undefined
    on alloc().

diff --git a/src/cairo-freelist.c b/src/cairo-freelist.c
index 3887f4b..e39a01e 100644
--- a/src/cairo-freelist.c
+++ b/src/cairo-freelist.c
@@ -24,10 +24,17 @@
 
 #include "cairo-freelist-private.h"
 
+#if HAVE_VALGRIND
+#include <memcheck.h>
+#define VG(x) x
+#else
+#define VG(x)
+#endif
+
 void
 _cairo_freelist_init (cairo_freelist_t *freelist, unsigned nodesize)
 {
-    memset (freelist, 0, sizeof(cairo_freelist_t));
+    memset (freelist, 0, sizeof (cairo_freelist_t));
     freelist->nodesize = nodesize;
 }
 
@@ -36,7 +43,11 @@ _cairo_freelist_fini (cairo_freelist_t *freelist)
 {
     cairo_freelist_node_t *node = freelist->first_free_node;
     while (node) {
-	cairo_freelist_node_t *next = node->next;
+	cairo_freelist_node_t *next;
+
+	VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next)));
+	next = node->next;
+
 	free (node);
 	node = next;
     }
@@ -46,10 +57,16 @@ void *
 _cairo_freelist_alloc (cairo_freelist_t *freelist)
 {
     if (freelist->first_free_node) {
-	cairo_freelist_node_t *node = freelist->first_free_node;
+	cairo_freelist_node_t *node;
+
+	node = freelist->first_free_node;
+	VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next)));
 	freelist->first_free_node = node->next;
-	return (void*)node;
+	VG (VALGRIND_MAKE_MEM_UNDEFINED (node, freelist->nodesize));
+
+	return node;
     }
+
     return malloc (freelist->nodesize);
 }
 
@@ -69,5 +86,6 @@ _cairo_freelist_free (cairo_freelist_t *freelist, void *voidnode)
     if (node) {
 	node->next = freelist->first_free_node;
 	freelist->first_free_node = node;
+	VG (VALGRIND_MAKE_MEM_NOACCESS (node, freelist->nodesize));
     }
 }


More information about the cairo-commit mailing list