diff -r 000000000000 -r 0e761a78d257 gstreamer_core/gst/gsttrace.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gstreamer_core/gst/gsttrace.c Thu Dec 17 08:53:32 2009 +0200 @@ -0,0 +1,559 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gsttrace.c: Tracing functions (deprecated) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * 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. + * + * + * Tracing object instances + * + * // 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 (); + * + * + * + * Last reviewed on 2005-11-21 (0.9.5) + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include + +#if defined (_MSC_VER) && _MSC_VER >= 1400 +# include +#endif + +#include "gst_private.h" +#include "gstinfo.h" + +#include "gsttrace.h" + +static +#ifdef __inline__ + __inline__ +#endif + void +read_tsc (gint64 * dst) +{ +#ifdef HAVE_RDTSC + guint64 tsc; + __asm__ __volatile__ ("rdtsc":"=A" (tsc)); + + *dst = tsc; +#else + *dst = 0; +#endif +} + +/** + * gst_trace_read_tsc: + * @dst: pointer to hold the result. + * + * Read a platform independent timer value that can be used in + * benchmarks. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +void +gst_trace_read_tsc (gint64 * dst) +{ + read_tsc (dst); +} + +static GstTrace *_gst_trace_default = NULL; +gint _gst_trace_on = 1; + +/** + * 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. + * + * Returns: a new #GstTrace. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +GstTrace * +gst_trace_new (gchar * filename, gint size) +{ + GstTrace *trace = g_malloc (sizeof (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; + + return trace; +} + +/** + * gst_trace_destroy: + * @trace: the #GstTrace to destroy + * + * Flush an close the previously allocated @trace. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +void +gst_trace_destroy (GstTrace * trace) +{ + 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_free (trace); +} + +/** + * 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. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +void +gst_trace_flush (GstTrace * trace) +{ + if (!trace) { + trace = _gst_trace_default; + if (!trace) + return; + } + + g_return_if_fail (write (trace->fd, trace->buf, + trace->bufoffset * sizeof (GstTraceEntry)) != -1); + trace->bufoffset = 0; +} + +/** + * 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. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +void +gst_trace_text_flush (GstTrace * trace) +{ + 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); + g_return_if_fail (write (trace->fd, str, strlen (str)) != -1); + } + trace->bufoffset = 0; +#undef STRSIZE +} + +/** + * gst_trace_set_default: + * @trace: the #GstTrace to set as the default. + * + * Set the default #GstTrace to @trace. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +void +gst_trace_set_default (GstTrace * trace) +{ + g_return_if_fail (trace != NULL); + _gst_trace_default = trace; +} +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + + +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); + trace->bufoffset++; + + gst_trace_flush (trace); +} + + +/* global flags */ +static GstAllocTraceFlags _gst_trace_flags = 0; + +/* 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. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +gboolean +gst_alloc_trace_available (void) +{ +#ifdef GST_DISABLE_ALLOC_TRACE + return FALSE; +#else + return TRUE; +#endif +} + +/** + * _gst_alloc_trace_register: + * @name: the name of the new alloc trace object. + * + * Register an get a handle to a GstAllocTrace object that + * can be used to trace memory allocations. + * + * Returns: A handle to a GstAllocTrace. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +GstAllocTrace * +_gst_alloc_trace_register (const gchar * name) +{ + GstAllocTrace *trace; + + g_return_val_if_fail (name, NULL); + + trace = g_new0 (GstAllocTrace, 1); + trace->name = g_strdup (name); + trace->live = 0; + trace->mem_live = NULL; + trace->flags = _gst_trace_flags; + + _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. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +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. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +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) +{ + return strcmp (a->name, b->name); +} + +static GList * +gst_alloc_trace_list_sorted (void) +{ + GList *ret; + + ret = g_list_sort (g_list_copy (_gst_alloc_tracers), + (GCompareFunc) compare_func); + + return ret; +} + +/** + * gst_alloc_trace_print_all: + * + * Print the status of all registered alloc trace objects. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +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. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +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. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +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. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +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. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +void +gst_alloc_trace_print (const GstAllocTrace * trace) +{ + GSList *mem_live; + + g_return_if_fail (trace != NULL); + + if (trace->flags & GST_ALLOC_TRACE_LIVE) { + g_print ("%-22.22s : %d\n", trace->name, trace->live); + } else { + g_print ("%-22.22s : (no live count)\n", trace->name); + } + + if (trace->flags & GST_ALLOC_TRACE_MEM_LIVE) { + mem_live = trace->mem_live; + + while (mem_live) { + g_print ("%-22.22s : %p\n", "", mem_live->data); + mem_live = mem_live->next; + } + } +} + +/** + * gst_alloc_trace_set_flags: + * @trace: the GstAllocTrace + * @flags: flags to set + * + * Enable the given features on the given GstAllocTrace object. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +void +gst_alloc_trace_set_flags (GstAllocTrace * trace, GstAllocTraceFlags flags) +{ + g_return_if_fail (trace != NULL); + + trace->flags = flags; +}