diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2008-04-10 14:49:47 +0100 |
---|---|---|
committer | Carl Worth <cworth@cworth.org> | 2008-04-11 09:07:24 -0700 |
commit | 9cfd82e87b60c0d65e9cafda026cb9a498874575 (patch) | |
tree | 6a29b41ea8bb94e51bdaab3cb2544898c3e44536 | |
parent | cf057c1e8603014033c079189369e91aecac2adf (diff) | |
download | cairo-9cfd82e87b60c0d65e9cafda026cb9a498874575.tar.gz |
[xlib] Add locking around GC cache.
The per-screen cached of most-recently freed GCs lacks suitable locking
for it to be threadsafe.
(cherry picked from commit dc714106e156cb7901e376c0935922446ae9bcdf)
-rw-r--r-- | src/cairo-xlib-private.h | 1 | ||||
-rw-r--r-- | src/cairo-xlib-screen.c | 31 |
2 files changed, 22 insertions, 10 deletions
diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h index 5bfc2ec56..2d9737d93 100644 --- a/src/cairo-xlib-private.h +++ b/src/cairo-xlib-private.h @@ -79,6 +79,7 @@ typedef struct _cairo_xlib_visual_info { struct _cairo_xlib_screen_info { cairo_xlib_screen_info_t *next; cairo_reference_count_t ref_count; + cairo_mutex_t mutex; cairo_xlib_display_t *display; Screen *screen; diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c index 8a3da6675..fc07fda22 100644 --- a/src/cairo-xlib-screen.c +++ b/src/cairo-xlib-screen.c @@ -256,12 +256,14 @@ _cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info) { int i; + CAIRO_MUTEX_LOCK (info->mutex); for (i = 0; i < ARRAY_LENGTH (info->gc); i++) { if (info->gc[i] != NULL) { XFreeGC (info->display->display, info->gc[i]); info->gc[i] = NULL; } } + CAIRO_MUTEX_UNLOCK (info->mutex); } void @@ -295,6 +297,8 @@ _cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info) _cairo_array_fini (&info->visuals); + CAIRO_MUTEX_FINI (info->mutex); + free (info); } @@ -335,6 +339,7 @@ _cairo_xlib_screen_info_get (Display *dpy, Screen *screen) info = malloc (sizeof (cairo_xlib_screen_info_t)); if (info != NULL) { CAIRO_REFERENCE_COUNT_INIT (&info->ref_count, 2); /* Add one for display cache */ + CAIRO_MUTEX_INIT (info->mutex); info->display = _cairo_xlib_display_reference (display); info->screen = screen; info->has_render = FALSE; @@ -385,16 +390,18 @@ GC _cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth) { GC gc; + cairo_bool_t needs_reset; depth = depth_to_index (depth); + CAIRO_MUTEX_LOCK (info->mutex); gc = info->gc[depth]; info->gc[depth] = NULL; + needs_reset = info->gc_needs_clip_reset & (1 << depth); + CAIRO_MUTEX_UNLOCK (info->mutex); - if (info->gc_needs_clip_reset & (1 << depth)) { + if (needs_reset) XSetClipMask(info->display->display, gc, None); - info->gc_needs_clip_reset &= ~(1 << depth); - } return gc; } @@ -403,21 +410,25 @@ cairo_status_t _cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip) { cairo_status_t status = CAIRO_STATUS_SUCCESS; + GC oldgc; depth = depth_to_index (depth); - if (info->gc[depth] != NULL) { - status = _cairo_xlib_display_queue_work (info->display, - (cairo_xlib_notify_func) XFreeGC, - info->gc[depth], - NULL); - } - + CAIRO_MUTEX_LOCK (info->mutex); + oldgc = info->gc[depth]; info->gc[depth] = gc; if (reset_clip) info->gc_needs_clip_reset |= 1 << depth; else info->gc_needs_clip_reset &= ~(1 << depth); + CAIRO_MUTEX_UNLOCK (info->mutex); + + if (oldgc != NULL) { + status = _cairo_xlib_display_queue_work (info->display, + (cairo_xlib_notify_func) XFreeGC, + oldgc, + NULL); + } return status; } |