mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-25 23:50:11 +01:00
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.
This commit is contained in:
parent
cdb6849fc1
commit
35a15f0263
7 changed files with 27 additions and 17 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue