[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