[cairo] Add attribute(warn_unused_result)

Chris Wilson chris at chris-wilson.co.uk
Thu Mar 29 13:26:20 PDT 2007


And with this patch, all malloc call sites triggered by cairo-perf for
xlib and image have been tested and do not cause cairo to fallover.
[Ok, that's not the same as all code paths but it's a good first step
with a finite runtime ;]

-------------- next part --------------
>From 8e87f5d1b36469e8c15e6b8a65ef73bdf1e81d6d Mon Sep 17 00:00:00 2001
From: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu, 29 Mar 2007 19:27:09 +0100
Subject: [PATCH] Return the correct status from _cairo_pen_stroke_spline

Don't blindly return CAIRO_STATUS_SUCCESS when the normal return path
also handle the error returns.
---
 src/cairo-pen.c |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/cairo-pen.c b/src/cairo-pen.c
index 74d2996..8bbc199 100644
--- a/src/cairo-pen.c
+++ b/src/cairo-pen.c
@@ -36,13 +36,13 @@
 
 #include "cairoint.h"
 
-static int
+cairo_static int
 _cairo_pen_vertices_needed (double tolerance, double radius, cairo_matrix_t *matrix);
 
-static void
+cairo_static void
 _cairo_pen_compute_slopes (cairo_pen_t *pen);
 
-static cairo_status_t
+cairo_static cairo_status_t
 _cairo_pen_stroke_spline_half (cairo_pen_t *pen, cairo_spline_t *spline, cairo_direction_t dir, cairo_polygon_t *polygon);
 
 cairo_status_t
@@ -245,7 +245,7 @@ Note that this also equation works for M == m (a circle) as it
 doesn't matter where on the circle the error is computed.
 */
 
-static int
+cairo_static int
 _cairo_pen_vertices_needed (double	    tolerance,
 			    double	    radius,
 			    cairo_matrix_t  *matrix)
@@ -282,7 +282,7 @@ _cairo_pen_vertices_needed (double	    tolerance,
     return num_vertices;
 }
 
-static void
+cairo_static void
 _cairo_pen_compute_slopes (cairo_pen_t *pen)
 {
     int i, i_prev;
@@ -358,7 +358,7 @@ _cairo_pen_find_active_ccw_vertex_index (cairo_pen_t *pen,
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_status_t
+cairo_static cairo_status_t
 _cairo_pen_stroke_spline_half (cairo_pen_t *pen,
 			       cairo_spline_t *spline,
 			       cairo_direction_t dir,
@@ -461,5 +461,5 @@ _cairo_pen_stroke_spline (cairo_pen_t		*pen,
 BAIL:
     _cairo_polygon_fini (&polygon);
 
-    return CAIRO_STATUS_SUCCESS;
+    return status;
 }
-- 
1.4.4.2

-------------- next part --------------
>From f44b5107e1ca34e8aa33037eef95bcd4414c0de4 Mon Sep 17 00:00:00 2001
From: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu, 29 Mar 2007 19:50:06 +0100
Subject: [PATCH] Convert to cairo_static and fixup.

Nothing of consequence, but future-proofing.
---
 src/cairo-path-bounds.c |   49 ++++++++++++++++++++++++----------------------
 1 files changed, 26 insertions(+), 23 deletions(-)

diff --git a/src/cairo-path-bounds.c b/src/cairo-path-bounds.c
index 48b4393..f4be744 100644
--- a/src/cairo-path-bounds.c
+++ b/src/cairo-path-bounds.c
@@ -45,43 +45,43 @@ typedef struct cairo_path_bounder {
     cairo_fixed_t max_y;
 } cairo_path_bounder_t;
 
-static void
+cairo_static void
 _cairo_path_bounder_init (cairo_path_bounder_t *bounder);
 
-static void
+cairo_static void
 _cairo_path_bounder_fini (cairo_path_bounder_t *bounder);
 
-static cairo_status_t
+cairo_static cairo_status_t
 _cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, cairo_point_t *point);
 
-static cairo_status_t
+cairo_static cairo_status_t
 _cairo_path_bounder_move_to (void *closure, cairo_point_t *point);
 
-static cairo_status_t
+cairo_static cairo_status_t
 _cairo_path_bounder_line_to (void *closure, cairo_point_t *point);
 
-static cairo_status_t
+cairo_static cairo_status_t
 _cairo_path_bounder_curve_to (void *closure,
 			      cairo_point_t *b,
 			      cairo_point_t *c,
 			      cairo_point_t *d);
 
-static cairo_status_t
+cairo_static cairo_status_t
 _cairo_path_bounder_close_path (void *closure);
 
-static void
+cairo_static void
 _cairo_path_bounder_init (cairo_path_bounder_t *bounder)
 {
     bounder->has_point = 0;
 }
 
-static void
+cairo_static void
 _cairo_path_bounder_fini (cairo_path_bounder_t *bounder)
 {
     bounder->has_point = 0;
 }
 
-static cairo_status_t
+cairo_static cairo_status_t
 _cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, cairo_point_t *point)
 {
     if (bounder->has_point) {
@@ -108,42 +108,45 @@ _cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, cairo_point_t *poi
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_status_t
+cairo_static cairo_status_t
 _cairo_path_bounder_move_to (void *closure, cairo_point_t *point)
 {
     cairo_path_bounder_t *bounder = closure;
 
-    _cairo_path_bounder_add_point (bounder, point);
-
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_path_bounder_add_point (bounder, point);
 }
 
-static cairo_status_t
+cairo_static cairo_status_t
 _cairo_path_bounder_line_to (void *closure, cairo_point_t *point)
 {
     cairo_path_bounder_t *bounder = closure;
 
-    _cairo_path_bounder_add_point (bounder, point);
-
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_path_bounder_add_point (bounder, point);
 }
 
-static cairo_status_t
+cairo_static cairo_status_t
 _cairo_path_bounder_curve_to (void *closure,
 			      cairo_point_t *b,
 			      cairo_point_t *c,
 			      cairo_point_t *d)
 {
     cairo_path_bounder_t *bounder = closure;
+    cairo_status_t status;
 
-    _cairo_path_bounder_add_point (bounder, b);
-    _cairo_path_bounder_add_point (bounder, c);
-    _cairo_path_bounder_add_point (bounder, d);
+    status = _cairo_path_bounder_add_point (bounder, b);
+    if (status)
+	return status;
+    status = _cairo_path_bounder_add_point (bounder, c);
+    if (status)
+	return status;
+    status = _cairo_path_bounder_add_point (bounder, d);
+    if (status)
+	return status;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_status_t
+cairo_static cairo_status_t
 _cairo_path_bounder_close_path (void *closure)
 {
     return CAIRO_STATUS_SUCCESS;
-- 
1.4.4.2

-------------- next part --------------
>From 47ee2c33f4f970fe6dd8aa6fc284260c41989e88 Mon Sep 17 00:00:00 2001
From: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu, 29 Mar 2007 20:44:19 +0100
Subject: [PATCH] Don't return scaled fonts in the error state from the cache.

It is possible for a scaled_font to be flagged as in error, though only
through a "true error" e.g. a malloc failure. However, when returning a font
from the cache it should not be in error. So if we find a error font in the
cache we remove it and return a new font.
---
 src/cairo-gstate.c      |    2 +-
 src/cairo-scaled-font.c |   13 ++++++++-----
 src/cairo.c             |   25 +++++++++++++------------
 3 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 82f5402..364fd09 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -1513,7 +1513,7 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
     status = _cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y,
 						utf8, glyphs, num_glyphs);
 
-    if (status || !glyphs || !num_glyphs || !(*glyphs) || !(num_glyphs))
+    if (status || !glyphs || !num_glyphs || !(*glyphs))
 	return status;
 
     return CAIRO_STATUS_SUCCESS;
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index ab7007e..b904b85 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -508,6 +508,12 @@ cairo_scaled_font_create (cairo_font_face_t          *font_face,
 	    memmove (&font_map->holdovers[i],
 		     &font_map->holdovers[i+1],
 		     (font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*));
+
+	    scaled_font->status = CAIRO_STATUS_SUCCESS;
+	} else if (scaled_font->status != CAIRO_STATUS_SUCCESS) {
+	    /* the font has been put into an error state - abandon the cache */
+	    _cairo_hash_table_remove (font_map->hash_table, &key.hash_entry);
+	    goto create_font;
 	}
 
 	/* We increment the reference count manually here, (rather
@@ -517,6 +523,7 @@ cairo_scaled_font_create (cairo_font_face_t          *font_face,
 	scaled_font->ref_count++;
 	_cairo_scaled_font_map_unlock ();
     } else {
+create_font:
 	/* Otherwise create it and insert it into the hash table. */
 	status = font_face->backend->scaled_font_create (font_face, font_matrix,
 							 ctm, options, &scaled_font);
@@ -969,10 +976,8 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t	 *scaled_font,
 					     glyphs[i].index,
 					     CAIRO_SCALED_GLYPH_INFO_METRICS,
 					     &scaled_glyph);
-	if (status) {
-	    _cairo_scaled_font_set_error (scaled_font, status);
+	if (status)
 	    return status;
-	}
 
 	/* glyph images are snapped to pixel locations */
 	x = _cairo_lround (glyphs[i].x);
@@ -1531,8 +1536,6 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
   CLEANUP:
     if (status) {
 	/* It's not an error for the backend to not support the info we want. */
-	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-	    _cairo_scaled_font_set_error (scaled_font, status);
 	*scaled_glyph_ret = NULL;
     } else {
 	*scaled_glyph_ret = scaled_glyph;
diff --git a/src/cairo.c b/src/cairo.c
index 64b2b0b..56b799e 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -2810,6 +2810,7 @@ cairo_glyph_extents (cairo_t                *cr,
 void
 cairo_show_text (cairo_t *cr, const char *utf8)
 {
+    cairo_status_t status;
     cairo_text_extents_t extents;
     cairo_glyph_t *glyphs = NULL, *last_glyph;
     int num_glyphs;
@@ -2823,24 +2824,24 @@ cairo_show_text (cairo_t *cr, const char *utf8)
 
     cairo_get_current_point (cr, &x, &y);
 
-    cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8,
-					       x, y,
-					       &glyphs, &num_glyphs);
-    if (cr->status)
+    status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8,
+					   x, y,
+					   &glyphs, &num_glyphs);
+    if (status)
 	goto BAIL;
 
     if (num_glyphs == 0)
 	return;
 
-    cr->status = _cairo_gstate_show_glyphs (cr->gstate, glyphs, num_glyphs);
-    if (cr->status)
+    status = _cairo_gstate_show_glyphs (cr->gstate, glyphs, num_glyphs);
+    if (status)
 	goto BAIL;
 
     last_glyph = &glyphs[num_glyphs - 1];
-    cr->status = _cairo_gstate_glyph_extents (cr->gstate,
-					      last_glyph, 1,
-					      &extents);
-    if (cr->status)
+    status = _cairo_gstate_glyph_extents (cr->gstate,
+					  last_glyph, 1,
+					  &extents);
+    if (status)
 	goto BAIL;
 
     x = last_glyph->x + extents.x_advance;
@@ -2851,8 +2852,8 @@ cairo_show_text (cairo_t *cr, const char *utf8)
     if (glyphs)
 	free (glyphs);
 
-    if (cr->status)
-	_cairo_set_error (cr, cr->status);
+    if (status)
+	_cairo_set_error (cr, status);
 }
 
 /**
-- 
1.4.4.2

-------------- next part --------------
>From 664905cc03e61039d9d06ee6c27201a6d61151e0 Mon Sep 17 00:00:00 2001
From: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu, 29 Mar 2007 21:20:50 +0100
Subject: [PATCH] Use cairo-perf for malloc failure testing

By changing cairo-perf to repeat a perf-case if it returns
CAIRO_STATUS_NO_MEMORY we can use cairo-perf, in conjuction with a fault
injector, to test a large swathe of failure handling throughout the entire
library.
---
 boilerplate/cairo-boilerplate.c |   27 ++++++++++++++++
 perf/Makefile.am                |    7 ++--
 perf/box-outline.c              |    8 +++-
 perf/cairo-perf-cover.c         |   26 ++++++++++-----
 perf/cairo-perf.c               |   65 +++++++++++++++++++++++++++------------
 perf/cairo-perf.h               |   17 ++++++++--
 perf/long-lines.c               |    8 +++-
 perf/mosaic.c                   |   12 +++++--
 perf/pattern_create_radial.c    |    4 +-
 perf/rectangles.c               |    2 +-
 perf/subimage_copy.c            |    2 +-
 perf/tessellate.c               |   10 ++++--
 perf/unaligned-clip.c           |    2 +-
 perf/world-map.c                |    2 +-
 perf/zrusin.c                   |    8 +++-
 15 files changed, 146 insertions(+), 54 deletions(-)

diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c
index cbfb2d4..dbca77c 100644
--- a/boilerplate/cairo-boilerplate.c
+++ b/boilerplate/cairo-boilerplate.c
@@ -985,6 +985,28 @@ create_xlib_perf_surface (Display		*dpy,
 							  width, height);
 }
 
+static int xlib_error_handler (Display *dpy, XErrorEvent *ev)
+{
+    char buf[1024];
+    char msg[1024];
+
+    XGetErrorText (dpy, ev->error_code, buf, sizeof (buf));
+    XGetErrorDatabaseText (dpy, "XlibMessage",
+	    "XError", "X Error", msg, sizeof (msg));
+    fprintf(stderr, "%s:  %s\n  ", msg, buf);
+
+    XGetErrorDatabaseText (dpy, "XlibMessage",
+	    "MajorCode", "Request Major code %d", 
+	    msg, sizeof (msg));
+    fprintf (stderr, msg, ev->request_code);
+    fprintf (stderr, "\n");
+
+    if (!getenv ("CAIRO_TEST_XLIB_NO_ERRORS"))
+	abort();
+
+    return 0;
+}
+
 static cairo_surface_t *
 create_xlib_surface (const char			 *name,
 		     cairo_content_t		  content,
@@ -1009,6 +1031,11 @@ create_xlib_surface (const char			 *name,
 	return NULL;
     }
 
+    /* install an eror handler that aborts rather than simply exits... */
+    XSetErrorHandler (xlib_error_handler);
+    if (getenv ("CAIRO_TEST_XLIB_SYNC"))
+	XSynchronize (dpy, TRUE);
+
     if (mode == CAIRO_BOILERPLATE_MODE_TEST)
 	return create_xlib_test_surface (dpy, content, width, height, xtc);
     else /* mode == CAIRO_BOILERPLATE_MODE_PERF */
diff --git a/perf/Makefile.am b/perf/Makefile.am
index 8fd6e64..c8585ce 100644
--- a/perf/Makefile.am
+++ b/perf/Makefile.am
@@ -42,14 +42,15 @@ cairo_perf_SOURCES += cairo-perf-win32.c
 else
 cairo_perf_SOURCES += cairo-perf-posix.c
 endif
+cairo_perf_LDADD = $(top_builddir)/boilerplate/libcairoboilerplate.la \
+	$(top_builddir)/src/libcairo.la
+
 
 cairo_perf_diff_files_SOURCES =	\
 	cairo-perf-diff-files.c \
 	cairo-stats.c		\
 	cairo-stats.h
-
-LDADD = $(top_builddir)/boilerplate/libcairoboilerplate.la \
-	$(top_builddir)/src/libcairo.la
+cairo_perf_diff_files_LDADD = $(top_builddir)/boilerplate/libcairoboilerplate.la
 
 $(top_builddir)/boilerplate/libcairoboilerplate.la:
 	cd $(top_builddir)/boilerplate && $(MAKE) $(AM_MAKEFLAGS) libcairoboilerplate.la
diff --git a/perf/box-outline.c b/perf/box-outline.c
index 74dd19a..ccba0aa 100644
--- a/perf/box-outline.c
+++ b/perf/box-outline.c
@@ -88,6 +88,10 @@ box_outline_fill (cairo_t *cr, int width, int height)
 void
 box_outline (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
-    cairo_perf_run (perf, "box-outline-stroke", box_outline_stroke);
-    cairo_perf_run (perf, "box-outline-fill", box_outline_fill);
+    static const cairo_perf_functions_t funcs[] = {
+	{ "box-outline-stroke", box_outline_stroke },
+	{ "box-outline-fill", box_outline_fill },
+	{ NULL, NULL }
+    };
+    cairo_perf_run (funcs, perf);
 }
diff --git a/perf/cairo-perf-cover.c b/perf/cairo-perf-cover.c
index 53dc7b7..5251a51 100644
--- a/perf/cairo-perf-cover.c
+++ b/perf/cairo-perf-cover.c
@@ -200,10 +200,8 @@ cairo_perf_cover_sources_and_operators (cairo_perf_t		*perf,
 					const char		*name,
 					cairo_perf_func_t	 perf_func)
 {
-    unsigned int i, j;
-    char *expanded_name;
-
-    struct { set_source_func_t set_source; const char *name; } sources[] = {
+    static unsigned int i, j;
+    const struct { set_source_func_t set_source; const char *name; } sources[] = {
 	{ set_source_solid_rgb, "solid_rgb" },
 	{ set_source_solid_rgba, "solid_rgba" },
 	{ set_source_image_surface_rgb, "image_rgb" },
@@ -215,22 +213,32 @@ cairo_perf_cover_sources_and_operators (cairo_perf_t		*perf,
 	{ set_source_radial_rgb, "radial_rgb" },
 	{ set_source_radial_rgba, "radial_rgba" }
     };
-
-    struct { cairo_operator_t op; const char *name; } operators[] = {
+    const struct { cairo_operator_t op; const char *name; } operators[] = {
 	{ CAIRO_OPERATOR_OVER, "over" },
 	{ CAIRO_OPERATOR_SOURCE, "source" }
     };
 
-    for (i = 0; i < ARRAY_SIZE (sources); i++) {
+    /* We assume we will be called in a tight loop, for example when we are
+     * performing malloc failure testing and we don't want to have to repeat
+     * tests already completed. */
+
+    for (; i < ARRAY_SIZE (sources); i++) {
 	(sources[i].set_source) (perf->cr, perf->size, perf->size);
 
-	for (j = 0; j < ARRAY_SIZE (operators); j++) {
+	for (; j < ARRAY_SIZE (operators); j++) {
+	    cairo_status_t status;
+	    char *expanded_name;
 	    cairo_set_operator (perf->cr, operators[j].op);
 
 	    xasprintf (&expanded_name, "%s_%s_%s",
 		       name, sources[i].name, operators[j].name);
-	    cairo_perf_run (perf, expanded_name, perf_func);
+	    status = cairo_perf_run_one (perf, expanded_name, perf_func);
 	    free (expanded_name);
+
+	    if (status)
+		return;
 	}
+	j = 0;
     }
+    i = 0;
 }
diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index 5657a38..b904bdd 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -103,10 +103,10 @@ _content_to_string (cairo_content_t content)
     }
 }
 
-void
-cairo_perf_run (cairo_perf_t		*perf,
-		const char		*name,
-		cairo_perf_func_t	 perf_func)
+cairo_status_t
+cairo_perf_run_one (cairo_perf_t		*perf,
+		    const char			*name,
+		    cairo_perf_func_t		 perf_func)
 {
     static cairo_bool_t first_run = TRUE;
     unsigned int i;
@@ -118,13 +118,13 @@ cairo_perf_run (cairo_perf_t		*perf,
 	for (i = 0; i < perf->num_names; i++)
 	    if (strstr (name, perf->names[i]))
 		goto NAME_FOUND;
-	return;
+	return CAIRO_STATUS_SUCCESS;
     }
   NAME_FOUND:
 
     if (perf->list_only) {
 	printf ("%s\n", name);
-	return;
+	return CAIRO_STATUS_SUCCESS;
     }
 
     if (first_run) {
@@ -148,6 +148,8 @@ cairo_perf_run (cairo_perf_t		*perf,
     for (i =0; i < perf->iterations; i++) {
 	cairo_perf_yield ();
 	times[i] = (perf_func) (perf->cr, perf->size, perf->size);
+	if (cairo_status (perf->cr))
+	    goto bail;
 
 	if (perf->raw) {
 	    if (i == 0)
@@ -190,7 +192,21 @@ cairo_perf_run (cairo_perf_t		*perf,
     }
 
     perf->test_number++;
+bail:
     free (times);
+    return cairo_status (perf->cr);
+}
+
+void
+cairo_perf_run (const cairo_perf_functions_t *funcs, cairo_perf_t *perf)
+{
+    static unsigned int n;
+    while (funcs[n].name != NULL) {
+	if (cairo_perf_run_one (perf, funcs[n].name, funcs[n].func))
+	    return;
+	n++;
+    }
+    n = 0;
 }
 
 static void
@@ -301,15 +317,16 @@ check_cpu_affinity(void)
 int
 main (int argc, char *argv[])
 {
-    int i, j;
-    cairo_perf_case_t *perf_case;
-    cairo_perf_t perf;
+    cairo_bool_t testing_malloc_failures = FALSE;
     const char *cairo_test_target = getenv ("CAIRO_TEST_TARGET");
-    cairo_boilerplate_target_t *target;
-    cairo_surface_t *surface;
+    cairo_perf_t perf;
+    int i, j;
 
     parse_options (&perf, argc, argv);
 
+    if (getenv ("CAIRO_TEST_MALLOC_FAILURE") != NULL)
+	testing_malloc_failures = TRUE;
+
     if (check_cpu_affinity()) {
         fputs(
             "NOTICE: cairo-perf and the X server should be bound to CPUs (either the same\n"
@@ -324,7 +341,8 @@ main (int argc, char *argv[])
     }
 
     for (i = 0; targets[i].name; i++) {
-	perf.target = target = &targets[i];
+	cairo_boilerplate_target_t *target = &targets[i];
+	perf.target = target;
 	perf.test_number = 0;
 
 	if (! target_is_measurable (target))
@@ -333,13 +351,15 @@ main (int argc, char *argv[])
 	    continue;
 
 	for (j = 0; perf_cases[j].run; j++) {
-
-	    perf_case = &perf_cases[j];
+	    cairo_perf_case_t *perf_case = &perf_cases[j];
 
 	    for (perf.size = perf_case->min_size;
 		 perf.size <= perf_case->max_size;
 		 perf.size *= 2)
 	    {
+		cairo_status_t status;
+		cairo_surface_t *surface;
+retest:
 		surface = (target->create_surface) (NULL,
 						    target->content,
 						    perf.size, perf.size,
@@ -351,18 +371,23 @@ main (int argc, char *argv[])
 		perf.cr = cairo_create (surface);
 
 		perf_case->run (&perf, perf.cr, perf.size, perf.size);
-
-		if (cairo_status (perf.cr)) {
-		    fprintf (stderr, "Error: Test left cairo in an error state: %s\n",
-			     cairo_status_to_string (cairo_status (perf.cr)));
-		    //exit (1);
-		}
+		status = cairo_status (perf.cr);
 
 		cairo_destroy (perf.cr);
 		cairo_surface_destroy (surface);
 
 		if (target->cleanup)
 		    target->cleanup (target->closure);
+
+		if (testing_malloc_failures &&
+			status == CAIRO_STATUS_NO_MEMORY)
+		    goto retest;
+
+		if (status) {
+		    fprintf (stderr, "Error: Test left cairo in an error state: %s\n",
+			    cairo_status_to_string (status));
+		    exit (1);
+		}
 	    }
 	}
     }
diff --git a/perf/cairo-perf.h b/perf/cairo-perf.h
index 1fef997..cf6f884 100644
--- a/perf/cairo-perf.h
+++ b/perf/cairo-perf.h
@@ -80,10 +80,21 @@ typedef struct _cairo_perf {
 typedef cairo_perf_ticks_t
 (*cairo_perf_func_t) (cairo_t *cr, int width, int height);
 
+typedef struct _cairo_perf_functions {
+    const char        *name;
+    cairo_perf_func_t  func;
+} cairo_perf_functions_t;
+
 void
-cairo_perf_run (cairo_perf_t		*perf,
-		const char		*name,
-		cairo_perf_func_t	 perf_func);
+cairo_perf_run (const cairo_perf_functions_t		*funcs,
+       	        cairo_perf_t				*perf);
+
+cairo_status_t
+cairo_perf_run_one (cairo_perf_t			*perf,
+		    const char				*name,
+		    cairo_perf_func_t			 perf_func);
+
+
 
 void
 cairo_perf_cover_sources_and_operators (cairo_perf_t		*perf,
diff --git a/perf/long-lines.c b/perf/long-lines.c
index 62e8e16..06df09a 100644
--- a/perf/long-lines.c
+++ b/perf/long-lines.c
@@ -112,6 +112,10 @@ long_lines_cropped (cairo_t *cr, int width, int height)
 void
 long_lines (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
-    cairo_perf_run (perf, "long-lines-uncropped", long_lines_uncropped);
-    cairo_perf_run (perf, "long-lines-cropped", long_lines_cropped);
+    static const cairo_perf_functions_t funcs[] = {
+	{ "long-lines-uncropped", long_lines_uncropped },
+	{ "long-lines-cropped", long_lines_cropped },
+	{ NULL, NULL }
+    };
+    cairo_perf_run (funcs, perf);
 }
diff --git a/perf/mosaic.c b/perf/mosaic.c
index 7172a9d..1c781b0 100644
--- a/perf/mosaic.c
+++ b/perf/mosaic.c
@@ -161,8 +161,12 @@ mosaic_tessellate_curves (cairo_t *cr, int width, int height)
 void
 mosaic (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
-    cairo_perf_run (perf, "mosaic_fill_curves", mosaic_fill_curves);
-    cairo_perf_run (perf, "mosaic_fill_lines", mosaic_fill_lines);
-    cairo_perf_run (perf, "mosaic_tessellate_curves", mosaic_tessellate_curves);
-    cairo_perf_run (perf, "mosaic_tessellate_lines", mosaic_tessellate_lines);
+    static cairo_perf_functions_t funcs[] = {
+	{ "mosaic_fill_curves", mosaic_fill_curves },
+	{ "mosaic_fill_lines", mosaic_fill_lines },
+	{ "mosaic_tessellate_curves", mosaic_tessellate_curves },
+	{ "mosaic_tessellate_lines", mosaic_tessellate_lines },
+	{ NULL, NULL }
+    };
+    cairo_perf_run (funcs, perf);
 }
diff --git a/perf/pattern_create_radial.c b/perf/pattern_create_radial.c
index 09f15a8..9de43a9 100644
--- a/perf/pattern_create_radial.c
+++ b/perf/pattern_create_radial.c
@@ -93,6 +93,6 @@ pattern_create_radial (cairo_perf_t *perf, cairo_t *cr, int width, int height)
         radials[i].radius1 = generate_double_in_range (0.0, 1000.0);
     }
 
-    cairo_perf_run (perf, "pattern_create_radial",
-                          do_pattern_create_radial);
+    cairo_perf_run_one (perf, "pattern_create_radial",
+                              do_pattern_create_radial);
 }
diff --git a/perf/rectangles.c b/perf/rectangles.c
index 9fa89f5..c7ae881 100644
--- a/perf/rectangles.c
+++ b/perf/rectangles.c
@@ -67,5 +67,5 @@ rectangles (cairo_perf_t *perf, cairo_t *cr, int width, int height)
         rects[i].height = (rand () % (height / 10)) + 1;
     }
 
-    cairo_perf_run (perf, "rectangles", do_rectangles);
+    cairo_perf_run_one (perf, "rectangles", do_rectangles);
 }
diff --git a/perf/subimage_copy.c b/perf/subimage_copy.c
index 54f596f..896f8d8 100644
--- a/perf/subimage_copy.c
+++ b/perf/subimage_copy.c
@@ -67,5 +67,5 @@ subimage_copy (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     cairo_set_source_surface (cr, image, 0, 0);
     cairo_surface_destroy (image);
 
-    cairo_perf_run (perf, "subimage_copy", do_subimage_copy);
+    cairo_perf_run_one (perf, "subimage_copy", do_subimage_copy);
 }
diff --git a/perf/tessellate.c b/perf/tessellate.c
index fc97db7..c81e53a 100644
--- a/perf/tessellate.c
+++ b/perf/tessellate.c
@@ -143,9 +143,13 @@ tessellate_256 (cairo_t *cr, int width, int height)
 void
 tessellate (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
-    cairo_perf_run (perf, "tessellate-16", tessellate_16);
-    cairo_perf_run (perf, "tessellate-64", tessellate_64);
-    cairo_perf_run (perf, "tessellate-256", tessellate_256);
+    static const cairo_perf_functions_t funcs[] = {
+	{ "tessellate-16", tessellate_16 },
+	{ "tessellate-64", tessellate_64 },
+	{ "tessellate-256", tessellate_256 },
+	{ NULL, NULL }
+    };
+    cairo_perf_run (funcs, perf);
 }
 
 #if 0
diff --git a/perf/unaligned-clip.c b/perf/unaligned-clip.c
index c7b9d21..60ea01a 100644
--- a/perf/unaligned-clip.c
+++ b/perf/unaligned-clip.c
@@ -62,5 +62,5 @@ do_unaligned_clip (cairo_t *cr, int width, int height)
 void
 unaligned_clip (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
-    cairo_perf_run (perf, "unaligned_clip", do_unaligned_clip);
+    cairo_perf_run_one (perf, "unaligned_clip", do_unaligned_clip);
 }
diff --git a/perf/world-map.c b/perf/world-map.c
index eef3619..f52dc6e 100644
--- a/perf/world-map.c
+++ b/perf/world-map.c
@@ -103,5 +103,5 @@ do_world_map (cairo_t *cr, int width, int height)
 void
 world_map (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
-    cairo_perf_run (perf, "world_map", do_world_map);
+    cairo_perf_run_one (perf, "world_map", do_world_map);
 }
diff --git a/perf/zrusin.c b/perf/zrusin.c
index 6840775..8171b16 100644
--- a/perf/zrusin.c
+++ b/perf/zrusin.c
@@ -85,6 +85,10 @@ zrusin_another_fill (cairo_t *cr, int width, int height)
 void
 zrusin (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
-    cairo_perf_run (perf, "zrusin_another_tessellate", zrusin_another_tessellate);
-    cairo_perf_run (perf, "zrusin_another_fill", zrusin_another_fill);
+    static const cairo_perf_functions_t funcs[] = {
+	{ "zrusin_another_tessellate", zrusin_another_tessellate },
+	{ "zrusin_another_fill", zrusin_another_fill },
+	{ NULL, NULL }
+    };
+    cairo_perf_run (funcs, perf);
 }
-- 
1.4.4.2



More information about the cairo mailing list