[gst-devel] -finstrument-functions
vishnu at pobox.com
vishnu at pobox.com
Sun Sep 30 15:51:02 CEST 2001
Here is what i have for -finstrument-functions. i'm not really
satisfed, but i don't know how to improve it much more.
--
Victory to the Divine Mother!!
http://sahajayoga.org
-------------- next part --------------
Index: ././gst/gstinfo.c
--- ././gst/gstinfo.c Sun Sep 30 09:44:19 2001
+++ ././gst/gstinfo.c Sun Sep 30 13:14:27 2001
@@ -21,6 +21,7 @@
*/
#include <dlfcn.h>
+#include <string.h>
#include "gst_private.h"
#include "gstelement.h"
#include "gstpad.h"
@@ -460,8 +461,6 @@ gst_default_error_handler (gchar *file,
/***** DEBUG system *****/
GHashTable *__gst_function_pointers = NULL;
-gchar *_gst_debug_nameof_funcptr (void *ptr) __attribute__ ((no_instrument_function));
-
gchar *
_gst_debug_nameof_funcptr (void *ptr)
{
@@ -478,16 +477,183 @@ _gst_debug_nameof_funcptr (void *ptr)
}
-#ifdef GST_ENABLE_FUNC_INSTRUMENTATION
-void __cyg_profile_func_enter(void *this_fn,void *call_site) __attribute__ ((no_instrument_function));
-void __cyg_profile_func_enter(void *this_fn,void *call_site) {
- GST_DEBUG(GST_CAT_CALL_TRACE, "entering function %s\n", _gst_debug_nameof_funcptr (this_fn));
+//
+// Don't allocate memory so we can call this inside of malloc.
+//
+
+static void
+db_nameof_funcptr (void *ptr, gchar *dst, gsize maxlen)
+ __attribute__ ((no_instrument_function));
+
+static void
+db_nameof_funcptr (void *ptr, gchar *dst, gsize maxlen)
+{
+ gchar *ptrname;
+ Dl_info dlinfo;
+ if (__gst_function_pointers &&
+ (ptrname = g_hash_table_lookup(__gst_function_pointers,ptr))) {
+ g_strlcpy (dst, ptrname, maxlen);
+ } else if (dladdr(ptr,&dlinfo) && dlinfo.dli_sname) {
+ g_strlcpy (dst, dlinfo.dli_sname, maxlen);
+ } else
+ g_snprintf (dst, maxlen, "%p", ptr);
+}
+
+#define MAX_STACK_FRAMES 50
+struct _DbStackTrace {
+ gint pthread_id;
+ gint cothread_id;
+ gint num_frames;
+ gint age;
+ gchar hint[4];
+ void *func[MAX_STACK_FRAMES];
+ void *call_site[MAX_STACK_FRAMES];
+};
+
+static gboolean DbStackTraceEnable = 1;
+
+#define MAX_THREADS 16
+static gint DbNumThreads = 0;
+static DbStackTrace DbThreads[MAX_THREADS];
+
+static GString *DbBuffer;
+
+static DbStackTrace *db_get_stack_trace ()
+ __attribute__ ((no_instrument_function));
+
+static DbStackTrace *db_get_stack_trace ()
+{
+ gint pid = getpid();
+ gint cothread_id = cothread_getcurrent();
+ gint xx;
+ DbStackTrace *dst;
+ static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
+
+ for (xx=0; xx < DbNumThreads; xx++) {
+ if (DbThreads[xx].pthread_id == pid &&
+ DbThreads[xx].cothread_id == cothread_id)
+ return DbThreads + xx;
+ }
+
+ g_static_mutex_lock (&mutex);
+
+ if (DbNumThreads == 0) {
+ DbBuffer = g_string_new_len (NULL, 2048); // try to avoid realloc
+ }
+
+ g_assert (DbNumThreads < MAX_THREADS);
+
+ dst = &DbThreads[DbNumThreads++];
+ dst->pthread_id = pid;
+ dst->cothread_id = cothread_id;
+ dst->num_frames = 0;
+ dst->age = 0;
+ dst->hint[0] = 0;
+
+ g_static_mutex_unlock (&mutex);
+
+ return dst;
}
-void __cyg_profile_func_exit(void *this_fn,void *call_site) __attribute__ ((no_instrument_function));
-void __cyg_profile_func_exit(void *this_fn,void *call_site) {
- GST_DEBUG(GST_CAT_CALL_TRACE, "leavinging function %s\n", _gst_debug_nameof_funcptr (this_fn));
+#define STACK_TRACE_LOG_SIZE 6
+static gint DbLogHead = 0;
+static DbStackTrace DbLog[STACK_TRACE_LOG_SIZE];
+
+void
+db_log_stack_trace (gchar *hint)
+{
+ DbStackTrace *dst;
+
+ if (!DbStackTraceEnable)
+ return;
+
+ dst = db_get_stack_trace ();
+
+ DbLogHead = (DbLogHead+1) % STACK_TRACE_LOG_SIZE;
+ memcpy (DbLog + DbLogHead, dst, sizeof (DbStackTrace));
+
+ if (hint)
+ g_strlcpy (dst->hint, hint, 4);
}
-#endif /* GST_ENABLE_FUNC_INTSTRUMENTATION */
+void __cyg_profile_func_enter (void *this_fn,
+ void *call_site)
+ __attribute__ ((no_instrument_function));
+
+void __cyg_profile_func_exit (void *this_fn,
+ void *call_site)
+ __attribute__ ((no_instrument_function));
+
+
+void __cyg_profile_func_enter (void *this_fn,
+ void *call_site)
+{
+ DbStackTrace *dst;
+
+ if (!DbStackTraceEnable)
+ return;
+
+ dst = db_get_stack_trace ();
+
+ g_assert (dst->num_frames < MAX_STACK_FRAMES);
+
+ ++ dst->age;
+ dst->func[dst->num_frames] = this_fn;
+ dst->call_site[dst->num_frames] = call_site;
+
+ ++dst->num_frames;
+}
+
+void __cyg_profile_func_exit (void *this_fn,
+ void *call_site)
+{
+ DbStackTrace *dst;
+
+ if (!DbStackTraceEnable)
+ return;
+
+ dst = db_get_stack_trace ();
+
+ ++ dst->age;
+
+ if (dst->num_frames > 0)
+ {
+ -- dst->num_frames;
+
+ g_assert (dst->func[dst->num_frames] == this_fn);
+ g_assert (dst->call_site[dst->num_frames] == call_site);
+ }
+ else
+ write (2, "warning: stack trace underflow\n", 31);
+}
+
+void
+db_print_stack_trace (DbStackTrace *dst)
+{
+ gboolean enable = DbStackTraceEnable;
+ gint xx;
+
+ DbStackTraceEnable = 0;
+
+ g_string_printf (DbBuffer, "Stack Trace pid=%d cothread=%d frames=%d age=%d hint='%s'\n",
+ dst->pthread_id, dst->cothread_id, dst->num_frames, dst->age, dst->hint);
+
+ for (xx = dst->num_frames - 1; xx >= 0; xx--)
+ {
+ static const gint maxsize=64;
+ gchar name1[maxsize];
+ gchar name2[maxsize];
+
+ db_nameof_funcptr (dst->func[xx], name1, maxsize);
+ db_nameof_funcptr (dst->call_site[xx], name2, maxsize);
+
+ g_string_printfa (DbBuffer, "%p in %s from\n\t%p in %s\n",
+ dst->func[xx], name1? name1:"?",
+ dst->call_site[xx], name2? name2:"?");
+ }
+
+ write (2, DbBuffer->str, DbBuffer->len);
+
+ DbStackTraceEnable = enable;
+}
diff -up 'joshua/gst/gstinfo.h' 'current/gst/gstinfo.h'
Index: ././gst/gstinfo.h
--- ././gst/gstinfo.h Sun Sep 30 09:44:19 2001
+++ ././gst/gstinfo.h Sun Sep 30 11:55:12 2001
@@ -333,14 +333,28 @@ extern GHashTable *__gst_function_pointe
static inline void *
_gst_debug_register_funcptr (void *ptr, gchar *ptrname)
{
- if (!__gst_function_pointers) __gst_function_pointers = g_hash_table_new(g_direct_hash,g_direct_equal);
- if (!g_hash_table_lookup(__gst_function_pointers,ptr))
- g_hash_table_insert(__gst_function_pointers,ptr,ptrname);
+ if (!__gst_function_pointers)
+ __gst_function_pointers = g_hash_table_new(g_direct_hash,g_direct_equal);
+
+ if (!g_hash_table_lookup (__gst_function_pointers, ptr))
+ g_hash_table_insert (__gst_function_pointers, ptr, ptrname);
+
return ptr;
}
-gchar *_gst_debug_nameof_funcptr (void *ptr);
+gchar *
+_gst_debug_nameof_funcptr (void *ptr)
+ __attribute__ ((no_instrument_function));
+
+typedef struct _DbStackTrace DbStackTrace;
+
+void
+db_log_stack_trace (gchar *hint)
+ __attribute__ ((no_instrument_function));
+void
+db_print_stack_trace (DbStackTrace *dst)
+ __attribute__ ((no_instrument_function));
#endif /* __GSTINFO_H__ */
More information about the gstreamer-devel
mailing list