gallium: fix reference counting functions to be strict-aliasing compliant
authorRoland Scheidegger <sroland@vmware.com>
Thu, 3 Dec 2009 22:15:38 +0000 (23:15 +0100)
committerRoland Scheidegger <sroland@vmware.com>
Thu, 3 Dec 2009 22:15:38 +0000 (23:15 +0100)
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/auxiliary/pipebuffer/pb_buffer.h
src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c
src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c
src/gallium/drivers/svga/svga_screen_texture.h
src/gallium/include/pipe/p_refcnt.h
src/gallium/include/pipe/p_state.h
src/gallium/include/pipe/p_video_state.h

index 4ef372233f0dbd50db920959aa042f293833a1b6..eb7e84be84863c1a3336ccde8dacd92bde9cd294 100644 (file)
@@ -237,8 +237,9 @@ pb_reference(struct pb_buffer **dst,
 {
    struct pb_buffer *old = *dst;
 
-   if (pipe_reference((struct pipe_reference**)dst, &src->base.reference))
+   if (pipe_reference(&(*dst)->base.reference, &src->base.reference))
       pb_destroy( old );
+   *dst = src;
 }
 
 
index 2f973684f67b28c2d88a9f5af3cbb158fa019b1a..a9375abd21880e52fef1cec4910ee8f38adfc578 100644 (file)
@@ -243,6 +243,7 @@ fenced_buffer_list_check_free_locked(struct fenced_buffer_list *fenced_list,
    struct pb_fence_ops *ops = fenced_list->ops;
    struct list_head *curr, *next;
    struct fenced_buffer *fenced_buf;
+   struct pb_buffer *pb_buf;
    struct pipe_fence_handle *prev_fence = NULL;
 
    curr = fenced_list->delayed.next;
@@ -271,7 +272,9 @@ fenced_buffer_list_check_free_locked(struct fenced_buffer_list *fenced_list,
       fenced_buffer_remove_locked(fenced_list, fenced_buf);
       pipe_mutex_unlock(fenced_buf->mutex);
 
-      pb_reference((struct pb_buffer **)&fenced_buf, NULL);
+      pb_buf = &fenced_buf->base;
+      pb_reference(&pb_buf, NULL);
+      
 
       curr = next; 
       next = curr->next;
index 57d1ede45a44d90a98692286abb3ccdcefa7d63e..f0c88a0ccbf718e315ef10bc5019c530888b377f 100644 (file)
@@ -293,8 +293,11 @@ pb_cache_manager_create_buffer(struct pb_manager *_mgr,
    if(buf) {
       LIST_DEL(&buf->head);
       pipe_mutex_unlock(mgr->mutex);
+#if 0
+      /* XXX this didn't do anything right??? */
       /* Increase refcount */
       pb_reference((struct pb_buffer**)&buf, &buf->base);
+#endif
       return &buf->base;
    }
    
index 1cc4063e6536d31c98d1ab2a1a13cde58da4e492..727f2c51d284bc3bff887746f05567d798264af2 100644 (file)
@@ -164,8 +164,9 @@ svga_sampler_view_reference(struct svga_sampler_view **ptr, struct svga_sampler_
 {
    struct svga_sampler_view *old = *ptr;
 
-   if (pipe_reference((struct pipe_reference **)ptr, &v->reference))
+   if (pipe_reference(&(*ptr)->reference, &v->reference))
       svga_destroy_sampler_view_priv(old);
+   *ptr = v;
 }
 
 extern void
index 1f9088b3e9c87f4b5efc26731cae3933aa89697e..f1875b6b822f9847fe748d8573bcbc7c9ae4ffae 100644 (file)
@@ -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;
index 6de7af6a81c602b41dea0fd6c6163e485565e17a..b9dfa1c7d3c173052dfac1862955a0895c9b2aea 100644 (file)
@@ -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;
 }
 
 
index 4da26d608cf23326ed4c3412125368d2aeba7516..b85f01c2b02c66fb4843ca895f0b8dc733980949 100644 (file)
@@ -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