X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Finclude%2Fpipe%2Fp_refcnt.h;h=1f9088b3e9c87f4b5efc26731cae3933aa89697e;hb=6fd8b9b550713302566bb4c28e49c219870ccfec;hp=50b7aa90ef898af3d5f77f556a7d30d28b326e8b;hpb=5b04939b16eb6e13858b070315dee1d0fc09d94f;p=mesa.git diff --git a/src/gallium/include/pipe/p_refcnt.h b/src/gallium/include/pipe/p_refcnt.h index 50b7aa90ef8..1f9088b3e9c 100644 --- a/src/gallium/include/pipe/p_refcnt.h +++ b/src/gallium/include/pipe/p_refcnt.h @@ -30,6 +30,7 @@ #include "p_defines.h" +#include "p_atomic.h" #ifdef __cplusplus @@ -39,14 +40,21 @@ extern "C" { struct pipe_reference { - unsigned count; + struct pipe_atomic count; }; static INLINE void pipe_reference_init(struct pipe_reference *reference, unsigned count) { - reference->count = count; + p_atomic_set(&reference->count, count); +} + + +static INLINE bool +pipe_is_referenced(struct pipe_reference *reference) +{ + return p_atomic_read(&reference->count) != 0; } @@ -54,31 +62,35 @@ pipe_reference_init(struct pipe_reference *reference, unsigned count) * 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. - * - * XXX: thread safety issues! */ static INLINE bool pipe_reference(struct pipe_reference **ptr, struct pipe_reference *reference) { bool destroy = FALSE; - /* bump the reference.count first */ - if (reference) { - assert(reference->count); - reference->count++; - } - - if (*ptr) { - assert((*ptr)->count); - if (--(*ptr)->count == 0) { - destroy = TRUE; + 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)) { + destroy = TRUE; + } + } + + *ptr = reference; } - *ptr = reference; - return destroy; } +#ifdef __cplusplus +} +#endif + #endif /* P_REFCNT_H */