diff options
Diffstat (limited to 'gst/gsttrace.c')
-rw-r--r-- | gst/gsttrace.c | 450 |
1 files changed, 68 insertions, 382 deletions
diff --git a/gst/gsttrace.c b/gst/gsttrace.c index b857458..a6e4d95 100644 --- a/gst/gsttrace.c +++ b/gst/gsttrace.c @@ -20,31 +20,6 @@ * Boston, MA 02111-1307, USA. */ -/** - * SECTION:gsttrace - * @short_description: Tracing functionality - * - * Traces allows to track object allocation. They provide a instance counter per - * #GType. The counter is incremented for each object allocated and decremented - * it when it's freed. - * - * <example> - * <title>Tracing object instances</title> - * <programlisting> - * // trace un-freed object instances - * gst_alloc_trace_set_flags_all (GST_ALLOC_TRACE_LIVE); - * if (!gst_alloc_trace_available ()) { - * g_warning ("Trace not available (recompile with trace enabled)."); - * } - * gst_alloc_trace_print_live (); - * // do something here - * gst_alloc_trace_print_live (); - * </programlisting> - * </example> - * - * Last reviewed on 2005-11-21 (0.9.5) - */ - #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -66,228 +41,46 @@ #include "gsttrace.h" -GStaticMutex _gst_trace_mutex = G_STATIC_MUTEX_INIT; - -static -#ifdef __inline__ - __inline__ -#endif - void -read_tsc (gint64 * dst) -{ -#if defined(HAVE_RDTSC) && defined(__GNUC__) - guint64 tsc; - __asm__ __volatile__ ("rdtsc":"=A" (tsc)); - - *dst = tsc; -#else - *dst = 0; -#endif -} - -/** - * gst_trace_read_tsc: - * @dst: (out) pointer to hold the result. - * - * Read a platform independent timer value that can be used in - * benchmarks. - */ -void -gst_trace_read_tsc (gint64 * dst) -{ - read_tsc (dst); -} - -static GstTrace *_gst_trace_default = NULL; -gint _gst_trace_on = 1; +GMutex _gst_trace_mutex; -/** - * gst_trace_new: - * @filename: a filename - * @size: the max size of the file - * - * Create a ringbuffer of @size in the file with @filename to - * store trace results in. - * - * Free-function: gst_trace_destroy - * - * Returns: (transfer full): a new #GstTrace. - */ -GstTrace * -gst_trace_new (const gchar * filename, gint size) -{ - GstTrace *trace = g_slice_new (GstTrace); - - g_return_val_if_fail (trace != NULL, NULL); - trace->filename = g_strdup (filename); - GST_DEBUG ("opening '%s'", trace->filename); -#ifndef S_IWUSR -#define S_IWUSR S_IWRITE -#endif -#ifndef S_IRUSR -#define S_IRUSR S_IREAD -#endif - trace->fd = - open (trace->filename, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); - perror ("opening trace file"); - g_return_val_if_fail (trace->fd > 0, NULL); - trace->buf = g_malloc (size * sizeof (GstTraceEntry)); - g_return_val_if_fail (trace->buf != NULL, NULL); - trace->bufsize = size; - trace->bufoffset = 0; +/* global flags */ +static GstAllocTraceFlags _gst_trace_flags = GST_ALLOC_TRACE_NONE; - return trace; -} +/* list of registered tracers */ +static GList *_gst_alloc_tracers = NULL; -/** - * gst_trace_destroy: - * @trace: (in) (transfer full): the #GstTrace to destroy - * - * Flush an close the previously allocated @trace. - */ -void -gst_trace_destroy (GstTrace * trace) +static void +_at_exit (void) { - g_return_if_fail (trace != NULL); - g_return_if_fail (trace->buf != NULL); - - if (gst_trace_get_remaining (trace) > 0) - gst_trace_flush (trace); - close (trace->fd); - g_free (trace->buf); - g_slice_free (GstTrace, trace); + if (_gst_trace_flags) + _priv_gst_alloc_trace_dump (); } -/** - * gst_trace_flush: - * @trace: the #GstTrace to flush. - * - * Flush any pending trace entries in @trace to the trace file. - * @trace can be NULL in which case the default #GstTrace will be - * flushed. - */ void -gst_trace_flush (GstTrace * trace) +_priv_gst_alloc_trace_initialize (void) { - int res, buf_len; + const gchar *trace; - if (!trace) { - trace = _gst_trace_default; - if (!trace) - return; + trace = g_getenv ("GST_TRACE"); + if (trace != NULL) { + _gst_trace_flags = atoi (trace); + atexit (_at_exit); } - buf_len = trace->bufoffset * sizeof (GstTraceEntry); - res = write (trace->fd, trace->buf, buf_len); - if (res < 0) { - g_warning ("Failed to write trace: %s", g_strerror (errno)); - return; - } else if (res < buf_len) { - g_warning ("Failed to write trace: only wrote %d/%d bytes", res, buf_len); - return; - } - trace->bufoffset = 0; + g_mutex_init (&_gst_trace_mutex); } -/** - * gst_trace_text_flush: - * @trace: the #GstTrace to flush. - * - * Flush any pending trace entries in @trace to the trace file, - * formatted as a text line with timestamp and sequence numbers. - * @trace can be NULL in which case the default #GstTrace will be - * flushed. - */ void -gst_trace_text_flush (GstTrace * trace) +_priv_gst_alloc_trace_deinit (void) { - int i; - -#define STRSIZE (20 + 1 + 10 + 1 + 10 + 1 + 112 + 1 + 1) - char str[STRSIZE]; - - if (!trace) { - trace = _gst_trace_default; - if (!trace) - return; - } - - for (i = 0; i < trace->bufoffset; i++) { - g_snprintf (str, STRSIZE, "%20" G_GINT64_FORMAT " %10d %10d %s\n", - trace->buf[i].timestamp, - trace->buf[i].sequence, trace->buf[i].data, trace->buf[i].message); - if (write (trace->fd, str, strlen (str)) < 0) { - g_warning ("Failed to write trace %d: %s", i, g_strerror (errno)); - return; - } - } - trace->bufoffset = 0; -#undef STRSIZE -} - -/** - * gst_trace_set_default: - * @trace: the #GstTrace to set as the default. - * - * Set the default #GstTrace to @trace. - */ -void -gst_trace_set_default (GstTrace * trace) -{ - g_return_if_fail (trace != NULL); - _gst_trace_default = trace; -} - -void -_gst_trace_add_entry (GstTrace * trace, guint32 seq, guint32 data, gchar * msg) -{ - GstTraceEntry *entry; - - if (!trace) { - trace = _gst_trace_default; - if (!trace) - return; - } - - entry = trace->buf + trace->bufoffset; - read_tsc (&(entry->timestamp)); - entry->sequence = seq; - entry->data = data; - strncpy (entry->message, msg, 112); - entry->message[111] = '\0'; - trace->bufoffset++; - - gst_trace_flush (trace); -} - - -/* global flags */ -static GstAllocTraceFlags _gst_trace_flags = GST_ALLOC_TRACE_NONE; - -/* list of registered tracers */ -static GList *_gst_alloc_tracers = NULL; - -/** - * gst_alloc_trace_available: - * - * Check if alloc tracing was compiled into the core - * - * Returns: TRUE if the core was compiled with alloc - * tracing enabled. - */ -gboolean -gst_alloc_trace_available (void) -{ -#ifdef GST_DISABLE_ALLOC_TRACE - return FALSE; -#else - return TRUE; -#endif + g_mutex_clear (&_gst_trace_mutex); } /** - * _gst_alloc_trace_register: + * _priv_gst_alloc_trace_register: * @name: the name of the new alloc trace object. + * @offset: the offset in the object where a GType an be found. -1 when the + * object has no gtype. * * Register an get a handle to a GstAllocTrace object that * can be used to trace memory allocations. @@ -295,7 +88,7 @@ gst_alloc_trace_available (void) * Returns: A handle to a GstAllocTrace. */ GstAllocTrace * -_gst_alloc_trace_register (const gchar * name) +_priv_gst_alloc_trace_register (const gchar * name, goffset offset) { GstAllocTrace *trace; @@ -306,49 +99,13 @@ _gst_alloc_trace_register (const gchar * name) trace->live = 0; trace->mem_live = NULL; trace->flags = _gst_trace_flags; + trace->offset = offset; _gst_alloc_tracers = g_list_prepend (_gst_alloc_tracers, trace); return trace; } -/** - * gst_alloc_trace_list: - * - * Get a list of all registered alloc trace objects. - * - * Returns: a GList of GstAllocTrace objects. - */ -const GList * -gst_alloc_trace_list (void) -{ - return _gst_alloc_tracers; -} - -/** - * gst_alloc_trace_live_all: - * - * Get the total number of live registered alloc trace objects. - * - * Returns: the total number of live registered alloc trace objects. - */ -int -gst_alloc_trace_live_all (void) -{ - GList *walk = _gst_alloc_tracers; - int num = 0; - - while (walk) { - GstAllocTrace *trace = (GstAllocTrace *) walk->data; - - num += trace->live; - - walk = g_list_next (walk); - } - - return num; -} - static gint compare_func (GstAllocTrace * a, GstAllocTrace * b) { @@ -366,111 +123,7 @@ gst_alloc_trace_list_sorted (void) return ret; } -/** - * gst_alloc_trace_print_all: - * - * Print the status of all registered alloc trace objects. - */ -void -gst_alloc_trace_print_all (void) -{ - GList *orig, *walk; - - orig = walk = gst_alloc_trace_list_sorted (); - - while (walk) { - GstAllocTrace *trace = (GstAllocTrace *) walk->data; - - gst_alloc_trace_print (trace); - - walk = g_list_next (walk); - } - - g_list_free (orig); -} - -/** - * gst_alloc_trace_print_live: - * - * Print the status of all registered alloc trace objects, ignoring those - * without live objects. - */ -void -gst_alloc_trace_print_live (void) -{ - GList *orig, *walk; - - orig = walk = gst_alloc_trace_list_sorted (); - - while (walk) { - GstAllocTrace *trace = (GstAllocTrace *) walk->data; - - if (trace->live) - gst_alloc_trace_print (trace); - - walk = g_list_next (walk); - } - - g_list_free (orig); -} - -/** - * gst_alloc_trace_set_flags_all: - * @flags: the options to enable - * - * Enable the specified options on all registered alloc trace - * objects. - */ -void -gst_alloc_trace_set_flags_all (GstAllocTraceFlags flags) -{ - GList *walk = _gst_alloc_tracers; - - while (walk) { - GstAllocTrace *trace = (GstAllocTrace *) walk->data; - - GST_DEBUG ("setting flags %d on %p", (gint) flags, trace); - gst_alloc_trace_set_flags (trace, flags); - - walk = g_list_next (walk); - } - _gst_trace_flags = flags; -} - -/** - * gst_alloc_trace_get: - * @name: the name of the alloc trace object - * - * Get the named alloc trace object. - * - * Returns: a GstAllocTrace with the given name or NULL when - * no alloc tracer was registered with that name. - */ -GstAllocTrace * -gst_alloc_trace_get (const gchar * name) -{ - GList *walk = _gst_alloc_tracers; - - g_return_val_if_fail (name, NULL); - - while (walk) { - GstAllocTrace *trace = (GstAllocTrace *) walk->data; - - if (!strcmp (trace->name, name)) - return trace; - - walk = g_list_next (walk); - } - return NULL; -} - -/** - * gst_alloc_trace_print: - * @trace: the GstAllocTrace to print - * - * Print the status of the given GstAllocTrace. - */ -void +static void gst_alloc_trace_print (const GstAllocTrace * trace) { GSList *mem_live; @@ -488,28 +141,61 @@ gst_alloc_trace_print (const GstAllocTrace * trace) while (mem_live) { gpointer data = mem_live->data; - - if (G_IS_OBJECT (data)) { - g_print ("%-22.22s : %p\n", g_type_name (G_OBJECT_TYPE (data)), data); + const gchar *type_name; + gchar *extra = NULL; + gint refcount = -1; + + if (trace->offset == -2) { + if (G_IS_OBJECT (data)) { + type_name = G_OBJECT_TYPE_NAME (data); + refcount = G_OBJECT (data)->ref_count; + } else + type_name = "<invalid>"; + } else if (trace->offset == -1) { + type_name = "<unknown>"; } else { - g_print ("%-22.22s : %p\n", "", data); + GType type; + + type = G_STRUCT_MEMBER (GType, data, trace->offset); + type_name = g_type_name (type); + + if (type == GST_TYPE_CAPS) { + extra = gst_caps_to_string (data); + refcount = GST_MINI_OBJECT_REFCOUNT_VALUE (data); + } } + + if (extra) { + g_print (" %-20.20s : (%d) %p (\"%s\")\n", type_name, refcount, data, + extra); + g_free (extra); + } else + g_print (" %-20.20s : (%d) %p\n", type_name, refcount, data); + mem_live = mem_live->next; } } } /** - * gst_alloc_trace_set_flags: - * @trace: the GstAllocTrace - * @flags: flags to set + * _priv_gst_alloc_trace_dump: * - * Enable the given features on the given GstAllocTrace object. + * Print the status of all registered alloc trace objects. */ void -gst_alloc_trace_set_flags (GstAllocTrace * trace, GstAllocTraceFlags flags) +_priv_gst_alloc_trace_dump (void) { - g_return_if_fail (trace != NULL); + GList *orig, *walk; + + orig = walk = gst_alloc_trace_list_sorted (); + + while (walk) { + GstAllocTrace *trace = (GstAllocTrace *) walk->data; - trace->flags = flags; + gst_alloc_trace_print (trace); + + walk = g_list_next (walk); + } + + g_list_free (orig); } |