Mesa (debug-refcnt): auxiliary: add reference count debugging code
Luca Barbieri
lb at kemper.freedesktop.org
Tue Aug 17 23:10:41 UTC 2010
Module: Mesa
Branch: debug-refcnt
Commit: 9c2e8179b2048d277902adf62c0219851e25884d
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=9c2e8179b2048d277902adf62c0219851e25884d
Author: Luca Barbieri <luca at luca-barbieri.com>
Date: Wed Aug 18 00:40:33 2010 +0200
auxiliary: add reference count debugging code
---
src/gallium/auxiliary/Makefile | 1 +
src/gallium/auxiliary/SConscript | 1 +
src/gallium/auxiliary/util/u_debug_refcnt.c | 151 +++++++++++++++++++++++++++
src/gallium/auxiliary/util/u_debug_refcnt.h | 29 +++++
4 files changed, 182 insertions(+), 0 deletions(-)
diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile
index 2dae479..e9b96aa 100644
--- a/src/gallium/auxiliary/Makefile
+++ b/src/gallium/auxiliary/Makefile
@@ -93,6 +93,7 @@ C_SOURCES = \
translate/translate_cache.c \
util/u_debug.c \
util/u_debug_describe.c \
+ util/u_debug_refcnt.c \
util/u_debug_symbol.c \
util/u_debug_stack.c \
util/u_dump_defines.c \
diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript
index 43774e3..992732f 100644
--- a/src/gallium/auxiliary/SConscript
+++ b/src/gallium/auxiliary/SConscript
@@ -148,6 +148,7 @@ source = [
'util/u_debug.c',
'util/u_debug_describe.c',
'util/u_debug_memory.c',
+ 'util/u_debug_refcnt.c',
'util/u_debug_stack.c',
'util/u_debug_symbol.c',
'util/u_dump_defines.c',
diff --git a/src/gallium/auxiliary/util/u_debug_refcnt.c b/src/gallium/auxiliary/util/u_debug_refcnt.c
new file mode 100644
index 0000000..5b9c0f0
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug_refcnt.c
@@ -0,0 +1,151 @@
+#if defined(DEBUG) && (!defined(PIPE_OS_WINDOWS) || defined(PIPE_SUBSYSTEM_WINDOWS_USER))
+
+/* see http://www.mozilla.org/performance/refcnt-balancer.html for what do with the output
+ * on Linux, use tools/addr2line.sh to postprocess it before anything else
+ **/
+#include <util/u_debug.h>
+#include <util/u_debug_refcnt.h>
+#include <util/u_debug_stack.h>
+#include <util/u_debug_symbol.h>
+#include <stdio.h>
+#include <util/u_hash_table.h>
+#include <os/os_thread.h>
+
+int util_debug_refcnt_state;
+
+static FILE* fp;
+
+/* TODO: maybe move this serial machinery to a stand-alone module and expose it? */
+static pipe_mutex serials_mutex;
+static struct util_hash_table* serials_hash;
+static unsigned serials_last;
+
+static unsigned hash_ptr(void* p)
+{
+ return (unsigned)(uintptr_t)p;
+}
+
+static int compare_ptr(void* a, void* b)
+{
+ if(a == b)
+ return 0;
+ else if(a < b)
+ return -1;
+ else
+ return 1;
+}
+
+static boolean util_debug_serial(void* p, unsigned* pserial)
+{
+ unsigned serial;
+ boolean found = TRUE;
+ pipe_mutex_lock(serials_mutex);
+ if(!serials_hash)
+ serials_hash = util_hash_table_create(hash_ptr, compare_ptr);
+ serial = (unsigned)(uintptr_t)util_hash_table_get(serials_hash, p);
+ if(!serial)
+ {
+ /* time to stop logging... (you'll have a 100 GB logfile at least at this point)
+ * TODO: avoid this
+ */
+ serial = ++serials_last;
+ if(!serial)
+ {
+ fprintf(stderr, "More than 2^32 objects detected, aborting.\n");
+ abort();
+ }
+
+ util_hash_table_set(serials_hash, p, (void*)(uintptr_t)serial);
+ found = FALSE;
+ }
+ pipe_mutex_unlock(serials_mutex);
+ *pserial = serial;
+ return found;
+}
+
+static void util_debug_serial_delete(void* p)
+{
+ pipe_mutex_lock(serials_mutex);
+ util_hash_table_remove(serials_hash, p);
+ pipe_mutex_unlock(serials_mutex);
+}
+
+#define STACK_LEN 64
+
+static void dump_stack(char symbols[STACK_LEN][1024])
+{
+ unsigned i;
+ for(i = 0; i < STACK_LEN; ++i)
+ {
+ if(symbols[i][0])
+ fprintf(fp, "%s\n", symbols[i]);
+ }
+ fprintf(fp, "\n");
+}
+
+void util_debug_reference_slowpath(const struct pipe_reference* p, void* pget_desc, const char* op)
+{
+ if(util_debug_refcnt_state < 0)
+ return;
+
+ if(!util_debug_refcnt_state)
+ {
+ const char* filename = debug_get_option("GALLIUM_REFCNT_LOG", NULL);
+ if(filename && filename[0])
+ fp = fopen(filename, "w");
+
+ if(fp)
+ util_debug_refcnt_state = 1;
+ else
+ util_debug_refcnt_state = -1;
+ }
+
+ if(util_debug_refcnt_state > 0)
+ {
+ struct debug_stack_frame frames[STACK_LEN];
+ char symbols[STACK_LEN][1024];
+ char buf[1024];
+
+ void (*get_desc)(char*, const struct pipe_reference*) = pget_desc;
+ unsigned i;
+ unsigned refcnt = p->count;
+ unsigned serial;
+ boolean existing = util_debug_serial((void*)p, &serial);
+
+ debug_backtrace_capture(frames, 1, STACK_LEN);
+ for(i = 0; i < STACK_LEN; ++i)
+ {
+ if(frames[i].function)
+ debug_symbol_name(frames[i].function, symbols[i], sizeof(symbols[i]));
+ else
+ symbols[i][0] = 0;
+ }
+
+ get_desc(buf, p);
+
+ if(!existing)
+ {
+ fprintf(fp, "<%s> %p %u Create\n", buf, p, serial);
+ dump_stack(symbols);
+
+ for(i = 1; i < refcnt; ++i)
+ {
+ fprintf(fp, "<%s> %p %u AddRef %u\n", buf, p, serial, i);
+ dump_stack(symbols);
+ }
+ }
+
+ fprintf(fp, "<%s> %p %u %s %u\n", buf, p, serial, op, refcnt);
+ dump_stack(symbols);
+
+ if(!refcnt)
+ {
+ util_debug_serial_delete((void*)p);
+ fprintf(fp, "<%s> %p %u Destroy\n", buf, p, serial);
+ dump_stack(symbols);
+ }
+
+ fflush(fp);
+ }
+}
+#endif
diff --git a/src/gallium/auxiliary/util/u_debug_refcnt.h b/src/gallium/auxiliary/util/u_debug_refcnt.h
new file mode 100644
index 0000000..9728fe6
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug_refcnt.h
@@ -0,0 +1,29 @@
+/*
+ * u_debug_refcnt.h
+ *
+ * Created on: Aug 17, 2010
+ * Author: lb
+ */
+
+#ifndef U_DEBUG_REFCNT_H_
+#define U_DEBUG_REFCNT_H_
+
+#include <pipe/p_config.h>
+#include <pipe/p_state.h>
+
+#if defined(DEBUG) && (!defined(PIPE_OS_WINDOWS) || defined(PIPE_SUBSYSTEM_WINDOWS_USER))
+extern int util_debug_refcnt_state;
+
+void util_debug_reference_slowpath(const struct pipe_reference* p, void* get_desc, const char* op);
+
+static INLINE void util_debug_reference(const struct pipe_reference* p, void* get_desc, const char* op)
+{
+ if(util_debug_refcnt_state >= 0)
+ util_debug_reference_slowpath(p, get_desc, op);
+}
+#else
+static INLINE void util_debug_reference(const struct pipe_reference* p, void* get_desc, const char* op)
+{}
+#endif
+
+#endif /* U_DEBUG_REFCNT_H_ */
More information about the mesa-commit
mailing list