summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuca Barbieri <[email protected]>2010-08-18 00:41:10 +0200
committerLuca Barbieri <[email protected]>2010-08-20 18:18:28 +0200
commitc806a40277bb5d2dab07908ef79078b0fcc56336 (patch)
tree6c870219c09990a53eeac7d39ae34abbc65f9afa
parent2ff13fe89e8f0b372512f16bb64d5a703e9bf891 (diff)
gallium: hook up reference count debugging code
This commit adds the ability to produce a log file containing all reference count changes, and object creation/destruction, on Gallium objects. The data allows to answer these crucial questions: 1. This app is exhausting all my memory due to a resource leak: where is the bug? 2. Which resources is this app using at a given moment? Which parts of the code created them? 3. What kinds of resources does this app use? 4. How fast does this app create and destroy resources? Which parts of the code create resources fast? The output is compatible with the one produced by the similar facility in Mozilla Firefox, allowing to use Mozilla's tools to analyze the data. To get the log file: export GALLIUM_REFCNT_LOG=<file> To get function names and source lines in the log file: tools/addr2line.sh <file> To process the log file, see: http://www.mozilla.org/performance/refcnt-balancer.html
-rw-r--r--src/gallium/auxiliary/util/u_inlines.h19
1 files changed, 13 insertions, 6 deletions
diff --git a/src/gallium/auxiliary/util/u_inlines.h b/src/gallium/auxiliary/util/u_inlines.h
index 540305c1465..90b0903e3f0 100644
--- a/src/gallium/auxiliary/util/u_inlines.h
+++ b/src/gallium/auxiliary/util/u_inlines.h
@@ -33,6 +33,8 @@
#include "pipe/p_state.h"
#include "pipe/p_screen.h"
#include "util/u_debug.h"
+#include "util/u_debug_describe.h"
+#include "util/u_debug_refcnt.h"
#include "util/u_atomic.h"
#include "util/u_box.h"
#include "util/u_math.h"
@@ -67,7 +69,7 @@ pipe_is_referenced(struct pipe_reference *reference)
* \return TRUE if the object's refcount hits zero and should be destroyed.
*/
static INLINE boolean
-pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference)
+pipe_reference_described(struct pipe_reference *ptr, struct pipe_reference *reference, void* get_desc)
{
boolean destroy = FALSE;
@@ -76,6 +78,7 @@ pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference)
if (reference) {
assert(pipe_is_referenced(reference));
p_atomic_inc(&reference->count);
+ debug_reference(reference, get_desc, 1);
}
if (ptr) {
@@ -83,41 +86,45 @@ pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference)
if (p_atomic_dec_zero(&ptr->count)) {
destroy = TRUE;
}
+ debug_reference(ptr, get_desc, -1);
}
}
return destroy;
}
+static INLINE boolean
+pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference)
+{
+ return pipe_reference_described(ptr, reference, debug_describe_reference);
+}
static INLINE void
pipe_surface_reference(struct pipe_surface **ptr, struct pipe_surface *surf)
{
struct pipe_surface *old_surf = *ptr;
- if (pipe_reference(&(*ptr)->reference, &surf->reference))
+ if (pipe_reference_described(&(*ptr)->reference, &surf->reference, debug_describe_surface))
old_surf->texture->screen->tex_surface_destroy(old_surf);
*ptr = surf;
}
-
static INLINE void
pipe_resource_reference(struct pipe_resource **ptr, struct pipe_resource *tex)
{
struct pipe_resource *old_tex = *ptr;
- if (pipe_reference(&(*ptr)->reference, &tex->reference))
+ if (pipe_reference_described(&(*ptr)->reference, &tex->reference, debug_describe_resource))
old_tex->screen->resource_destroy(old_tex->screen, old_tex);
*ptr = tex;
}
-
static INLINE void
pipe_sampler_view_reference(struct pipe_sampler_view **ptr, struct pipe_sampler_view *view)
{
struct pipe_sampler_view *old_view = *ptr;
- if (pipe_reference(&(*ptr)->reference, &view->reference))
+ if (pipe_reference_described(&(*ptr)->reference, &view->reference, debug_describe_sampler_view))
old_view->context->sampler_view_destroy(old_view->context, old_view);
*ptr = view;
}