From 35a15f02634a31c1517363d91aaef8f190e24687 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Thu, 3 Dec 2009 23:15:38 +0100 Subject: gallium: fix reference counting functions to be strict-aliasing compliant Historically, parts of mesa code are not strict-aliasing safe, hence -fno-strict-aliasing is needed to compile (this got forgotten for scons builds for gallium, which indeed not only caused compiler warnings but also unexplicable crashes in non-debug builds). However, we should try to eliminate code not complying with strict-aliasing code at least for gallium. Hence change pipe_reference functions to make them strict-aliasing compliant. This adds a bit more complexity (especially for derived classes) but is the right thing to do, and it does in fact fix a segfault. --- src/gallium/include/pipe/p_refcnt.h | 18 ++++++++---------- src/gallium/include/pipe/p_state.h | 9 ++++++--- src/gallium/include/pipe/p_video_state.h | 3 ++- 3 files changed, 16 insertions(+), 14 deletions(-) (limited to 'src/gallium/include') diff --git a/src/gallium/include/pipe/p_refcnt.h b/src/gallium/include/pipe/p_refcnt.h index 1f9088b3e9c..f1875b6b822 100644 --- a/src/gallium/include/pipe/p_refcnt.h +++ b/src/gallium/include/pipe/p_refcnt.h @@ -59,30 +59,28 @@ pipe_is_referenced(struct pipe_reference *reference) /** - * Set 'ptr' to point to 'reference' and update reference counting. - * The old thing pointed to, if any, will be unreferenced first. - * 'reference' may be NULL. + * Update reference counting. + * The old thing pointed to, if any, will be unreferenced. + * Both 'ptr' and 'reference' may be NULL. */ static INLINE bool -pipe_reference(struct pipe_reference **ptr, struct pipe_reference *reference) +pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference) { bool destroy = FALSE; - if(*ptr != reference) { + if(ptr != reference) { /* bump the reference.count first */ if (reference) { assert(pipe_is_referenced(reference)); p_atomic_inc(&reference->count); } - if (*ptr) { - assert(pipe_is_referenced(*ptr)); - if (p_atomic_dec_zero(&(*ptr)->count)) { + if (ptr) { + assert(pipe_is_referenced(ptr)); + if (p_atomic_dec_zero(&ptr->count)) { destroy = TRUE; } } - - *ptr = reference; } return destroy; diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h index 6de7af6a81c..b9dfa1c7d3c 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -400,8 +400,9 @@ pipe_buffer_reference(struct pipe_buffer **ptr, struct pipe_buffer *buf) { struct pipe_buffer *old_buf = *ptr; - if (pipe_reference((struct pipe_reference **)ptr, &buf->reference)) + if (pipe_reference(&(*ptr)->reference, &buf->reference)) old_buf->screen->buffer_destroy(old_buf); + *ptr = buf; } static INLINE void @@ -409,8 +410,9 @@ pipe_surface_reference(struct pipe_surface **ptr, struct pipe_surface *surf) { struct pipe_surface *old_surf = *ptr; - if (pipe_reference((struct pipe_reference **)ptr, &surf->reference)) + if (pipe_reference(&(*ptr)->reference, &surf->reference)) old_surf->texture->screen->tex_surface_destroy(old_surf); + *ptr = surf; } static INLINE void @@ -418,8 +420,9 @@ pipe_texture_reference(struct pipe_texture **ptr, struct pipe_texture *tex) { struct pipe_texture *old_tex = *ptr; - if (pipe_reference((struct pipe_reference **)ptr, &tex->reference)) + if (pipe_reference(&(*ptr)->reference, &tex->reference)) old_tex->screen->texture_destroy(old_tex); + *ptr = tex; } diff --git a/src/gallium/include/pipe/p_video_state.h b/src/gallium/include/pipe/p_video_state.h index 4da26d608cf..b85f01c2b02 100644 --- a/src/gallium/include/pipe/p_video_state.h +++ b/src/gallium/include/pipe/p_video_state.h @@ -56,8 +56,9 @@ pipe_video_surface_reference(struct pipe_video_surface **ptr, struct pipe_video_ { struct pipe_video_surface *old_surf = *ptr; - if (pipe_reference((struct pipe_reference **)ptr, &surf->reference)) + if (pipe_reference(&(*ptr)->reference, &surf->reference)) old_surf->screen->video_surface_destroy(old_surf); + *ptr = surf; } struct pipe_video_rect -- cgit v1.2.3