mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-27 02:30:35 +00:00
Changes made to the DEBUG system. New header file gstdebug.h holds the stuff to keep it out of gst.h's hair. DEBUG ...
Original commit message from CVS: Changes made to the DEBUG system. New header file gstdebug.h holds the stuff to keep it out of gst.h's hair. DEBUG prints out the process id, cothread id, source filename and line number. Two new macros DEBUG_ENTER and DEBUG_LEAVE are used to show the entry and exit of a given function. This eventually might be used to construct call trace graphs, even taking cothreads into account. This would be quite useful in visualizing the scheduling mechanism. Minor changes to various debug messages. Also sitting in gstdebug.h is a prototypical DEBUG_ENTER that's capable of performing DEBUG_LEAVE automatically. It does this by utilizing a little-known GCC extension that allows one to call a function with the same parameters as the current function. The macro uses this to basically call itself. A boolean is used to ensure that when it calls itself it actually runs the body of the function. In the meantime it prints stuff out before and after the real function, as well as constructing a debugging string. This can be used eventually to provide call-wide data on the DEBUG lines, instead of having to replicate data on each call to DEBUG. More research is needed into how this would most cleanly be fit into some other chunk of code, like GStreamer (I think of this DEBUG trick as a separate project, sorta). Unfortunately, the aforementioned DEBUG trick interacts quite poorly with cothreads. Almost any time it's used in a function that has anything remotely to do with a cothread context (as in, it runs in one), a segfault results from the __builtin_apply call, which is the heart of the whole thing. If someone who really knows assembly could analyze the resulting code to see what's really going on, we might find a way to fix either the macro or the cothreads (I'm thinking that there's something we missed in constructing the cothreads themselves) so this works in all cases. In the meantime, please insert both DEBUG_ENTER and DEBUG_LEAVE in your functions. Be sure to put DEBUG_ENTER after your variable declarations and before any functional code, not to put the function name in any DEBUG strings (it's already there, trust me), and put a DEBUG_LEAVE if you care enough. Changes are going to happen in the way DEBUGs and other printouts occur, so stay tuned.
This commit is contained in:
parent
47bd1b0545
commit
29d567ba23
7 changed files with 143 additions and 36 deletions
|
@ -16,4 +16,4 @@
|
|||
|
||||
#undef HAVE_ATOMIC_H
|
||||
|
||||
#undef DEBUG_ENABLED
|
||||
#undef GST_DEBUG_ENABLED
|
||||
|
|
|
@ -350,13 +350,15 @@ if test "x$PLUGINS_USE_SRCDIR" = xyes; then
|
|||
fi
|
||||
|
||||
if test "x$USE_DEBUG" = xyes; then
|
||||
AC_DEFINE(DEBUG_ENABLED)
|
||||
CFLAGS="$CFLAGS -g"
|
||||
AC_DEFINE(GST_DEBUG_ENABLED)
|
||||
fi
|
||||
|
||||
if test "x$USE_PROFILING" = xyes; then
|
||||
CFLAGS="$CFLAGS -pg"
|
||||
fi
|
||||
|
||||
CFLAGS="$CFLAGS -O6"
|
||||
|
||||
dnl #############################
|
||||
dnl # Set automake conditionals #
|
||||
|
|
|
@ -73,6 +73,7 @@ libgstinclude_HEADERS = \
|
|||
gstmeta.h \
|
||||
gsttee.h \
|
||||
gstxml.h \
|
||||
gstdebug.h \
|
||||
cothreads.h
|
||||
|
||||
noinst_HEADERS = \
|
||||
|
@ -80,7 +81,7 @@ noinst_HEADERS = \
|
|||
gsti386.h \
|
||||
gstppc.h
|
||||
|
||||
CFLAGS += -g -O6 -Wall
|
||||
#CFLAGS += -O2 -Wall
|
||||
|
||||
libgst_la_LIBADD = $(GLIB_LIBS) $(GTK_LIBS) $(XML_LIBS)
|
||||
libgst_la_LDFLAGS = -version-info $(STREAMER_CURRENT):$(STREAMER_REVISION):$(STREAMER_AGE)
|
||||
|
|
|
@ -27,10 +27,12 @@
|
|||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
//#define DEBUG_ENABLED
|
||||
#include "gst/gst.h"
|
||||
#include "cothreads.h"
|
||||
#include "gst/gstarch.h"
|
||||
/* we make too much noise for normal debugging... */
|
||||
#define GST_DEBUG_FORCE_DISABLE
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/cothreads.h>
|
||||
#include <gst/gstarch.h>
|
||||
|
||||
pthread_key_t _cothread_key = -1;
|
||||
|
||||
|
@ -51,11 +53,11 @@ cothread_create (cothread_context *ctx)
|
|||
{
|
||||
cothread_state *s;
|
||||
|
||||
DEBUG("cothread: pthread_self() %ld\n",pthread_self());
|
||||
DEBUG("pthread_self() %ld\n",pthread_self());
|
||||
//if (0) {
|
||||
if (pthread_self() == 0) {
|
||||
s = (cothread_state *)malloc(sizeof(int) * COTHREAD_STACKSIZE);
|
||||
DEBUG("cothread: new stack at %p\n",s);
|
||||
DEBUG("new stack at %p\n",s);
|
||||
} else {
|
||||
char *sp = CURRENT_STACK_FRAME;
|
||||
unsigned long *stack_end = (unsigned long *)((unsigned long)sp &
|
||||
|
@ -78,7 +80,7 @@ cothread_create (cothread_context *ctx)
|
|||
|
||||
ctx->threads[ctx->nthreads++] = s;
|
||||
|
||||
DEBUG("cothread: created cothread at %p %p\n",s, s->sp);
|
||||
DEBUG("created cothread at %p %p\n",s, s->sp);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -136,7 +138,7 @@ cothread_init (void)
|
|||
ctx->threads[0]->sp = (int *)CURRENT_STACK_FRAME;
|
||||
ctx->threads[0]->pc = 0;
|
||||
|
||||
DEBUG("cothread: 0th thread is at %p %p\n",ctx->threads[0], ctx->threads[0]->sp);
|
||||
DEBUG("0th thread is at %p %p\n",ctx->threads[0], ctx->threads[0]->sp);
|
||||
|
||||
// we consider the initiating process to be cothread 0
|
||||
ctx->nthreads = 1;
|
||||
|
@ -165,14 +167,14 @@ cothread_stub (void)
|
|||
cothread_context *ctx = pthread_getspecific(_cothread_key);
|
||||
register cothread_state *thread = ctx->threads[ctx->current];
|
||||
|
||||
DEBUG("cothread: cothread_stub() entered\n");
|
||||
DEBUG_ENTER("");
|
||||
thread->flags |= COTHREAD_STARTED;
|
||||
if (thread->func)
|
||||
thread->func(thread->argc,thread->argv);
|
||||
thread->flags &= ~COTHREAD_STARTED;
|
||||
thread->pc = 0;
|
||||
thread->sp = thread->top_sp;
|
||||
DEBUG("cothread: cothread_stub() exit\n");
|
||||
DEBUG_LEAVE("");
|
||||
// printf("uh, yeah, we shouldn't be here, but we should deal anyway\n");
|
||||
}
|
||||
|
||||
|
@ -252,24 +254,24 @@ cothread_switch (cothread_state *thread)
|
|||
|
||||
// find the number of the thread to switch to
|
||||
ctx->current = thread->threadnum;
|
||||
DEBUG("cothread: about to switch to thread #%d\n",ctx->current);
|
||||
DEBUG("about to switch to thread #%d\n",ctx->current);
|
||||
|
||||
/* save the current stack pointer, frame pointer, and pc */
|
||||
GET_SP(current->sp);
|
||||
enter = setjmp(current->jmp);
|
||||
if (enter != 0) {
|
||||
DEBUG("cothread: enter thread #%d %d %p<->%p (%d)\n",current->threadnum, enter,
|
||||
DEBUG("enter thread #%d %d %p<->%p (%d)\n",current->threadnum, enter,
|
||||
current->sp, current->top_sp, current->top_sp-current->sp);
|
||||
return;
|
||||
}
|
||||
DEBUG("cothread: exit thread #%d %d %p<->%p (%d)\n",current->threadnum, enter,
|
||||
DEBUG("exit thread #%d %d %p<->%p (%d)\n",current->threadnum, enter,
|
||||
current->sp, current->top_sp, current->top_sp-current->sp);
|
||||
enter = 1;
|
||||
|
||||
DEBUG("cothread: set stack to %p\n", thread->sp);
|
||||
DEBUG("set stack to %p\n", thread->sp);
|
||||
/* restore stack pointer and other stuff of new cothread */
|
||||
if (thread->flags & COTHREAD_STARTED) {
|
||||
DEBUG("cothread: in thread \n");
|
||||
DEBUG("in thread \n");
|
||||
SET_SP(thread->sp);
|
||||
// switch to it
|
||||
longjmp(thread->jmp,1);
|
||||
|
@ -278,7 +280,7 @@ cothread_switch (cothread_state *thread)
|
|||
SET_SP(thread->sp);
|
||||
// start it
|
||||
cothread_stub();
|
||||
DEBUG("cothread: exit thread \n");
|
||||
DEBUG("exit thread \n");
|
||||
ctx->current = 0;
|
||||
}
|
||||
|
||||
|
|
17
gst/gst.h
17
gst/gst.h
|
@ -21,9 +21,16 @@
|
|||
#ifndef __GST_H__
|
||||
#define __GST_H__
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gmodule.h>
|
||||
|
||||
#include <gst/gstdebug.h>
|
||||
|
||||
#include <gst/gstlog.h>
|
||||
|
||||
|
@ -46,7 +53,6 @@
|
|||
#include <gst/gstutils.h>
|
||||
#include <gst/gsttrace.h>
|
||||
#include <gst/gstxml.h>
|
||||
|
||||
#include <gst/gsttee.h>
|
||||
|
||||
#include <gst/cothreads.h>
|
||||
|
@ -57,13 +63,4 @@ void gst_init(int *argc,char **argv[]);
|
|||
void gst_main (void);
|
||||
void gst_main_quit (void);
|
||||
|
||||
/* debugging */
|
||||
#ifndef DEBUG
|
||||
#ifdef DEBUG_ENABLED
|
||||
#define DEBUG(format, args...) g_print("DEBUG:(%d:%d) " format, getpid() , cothread_getcurrent() , ##args)
|
||||
#else
|
||||
#define DEBUG(format, args...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* __GST_H__ */
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
*/
|
||||
|
||||
|
||||
//#define DEBUG_ENABLED
|
||||
/* this file makes too much noise for most debugging sessions */
|
||||
#define GST_DEBUG_FORCE_DISABLE
|
||||
#include <gst/gst.h>
|
||||
#include <gst/gstbuffer.h>
|
||||
|
||||
|
@ -45,7 +46,7 @@ gst_buffer_new(void)
|
|||
GstBuffer *buffer;
|
||||
|
||||
buffer = g_mem_chunk_alloc (_gst_buffer_chunk);
|
||||
DEBUG("BUF: allocating new buffer %p\n",buffer);
|
||||
DEBUG("allocating new buffer %p\n",buffer);
|
||||
|
||||
// g_print("allocating new mutex\n");
|
||||
buffer->lock = g_mutex_new ();
|
||||
|
@ -104,7 +105,7 @@ gst_buffer_create_sub (GstBuffer *parent,
|
|||
g_return_val_if_fail ((offset+size) <= parent->size, NULL);
|
||||
|
||||
buffer = g_mem_chunk_alloc (_gst_buffer_chunk);
|
||||
DEBUG("BUF: allocating new subbuffer %p, parent %p\n", buffer, parent);
|
||||
DEBUG("allocating new subbuffer %p, parent %p\n", buffer, parent);
|
||||
|
||||
buffer->lock = g_mutex_new ();
|
||||
#ifdef HAVE_ATOMIC_H
|
||||
|
@ -196,10 +197,10 @@ void gst_buffer_destroy (GstBuffer *buffer)
|
|||
g_return_if_fail (buffer != NULL);
|
||||
|
||||
if (buffer->parent != NULL) {
|
||||
DEBUG("BUF: freeing subbuffer %p\n", buffer);
|
||||
DEBUG("freeing subbuffer %p\n", buffer);
|
||||
}
|
||||
else {
|
||||
DEBUG("BUF: freeing buffer %p\n", buffer);
|
||||
DEBUG("freeing buffer %p\n", buffer);
|
||||
}
|
||||
|
||||
// free the data only if there is some, DONTFREE isn't set, and not sub
|
||||
|
@ -240,7 +241,7 @@ gst_buffer_ref (GstBuffer *buffer)
|
|||
{
|
||||
g_return_if_fail (buffer != NULL);
|
||||
|
||||
DEBUG("BUF: referencing buffer %p\n", buffer);
|
||||
DEBUG("referencing buffer %p\n", buffer);
|
||||
|
||||
#ifdef HAVE_ATOMIC_H
|
||||
//g_return_if_fail(atomic_read(&(buffer->refcount)) > 0);
|
||||
|
@ -291,7 +292,7 @@ gst_buffer_unref (GstBuffer *buffer)
|
|||
|
||||
g_return_if_fail (buffer != NULL);
|
||||
|
||||
DEBUG("BUF: unreferencing buffer %p\n", buffer);
|
||||
DEBUG("unreferencing buffer %p\n", buffer);
|
||||
|
||||
#ifdef HAVE_ATOMIC_H
|
||||
g_return_if_fail (atomic_read (&(buffer->refcount)) > 0);
|
||||
|
|
104
gst/gstdebug.h
Normal file
104
gst/gstdebug.h
Normal file
|
@ -0,0 +1,104 @@
|
|||
/* Gnome-Streamer
|
||||
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GSTDEBUG_H__
|
||||
#define __GSTDEBUG_H__
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
/* for include files that make too much noise normally */
|
||||
#ifdef GST_DEBUG_FORCE_DISABLE
|
||||
#undef GST_DEBUG_ENABLED
|
||||
#endif
|
||||
|
||||
/* for applications that really really want all the noise */
|
||||
#ifdef GST_DEBUG_FORCE_ENABLE
|
||||
#define GST_DEBUG_ENABLED
|
||||
#endif
|
||||
|
||||
|
||||
#define GST_DEBUG_PREFIX(format,args...) \
|
||||
"DEBUG(%d:%d)" __PRETTY_FUNCTION__ ":%d" format , getpid() , cothread_getcurrent() , __LINE__ , ## args
|
||||
|
||||
|
||||
/* fallback, this should probably be a 'weak' symbol or something */
|
||||
G_GNUC_UNUSED static gchar *_debug_string = NULL;
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* The following is a DEBUG_ENTER implementation that will wrap the
|
||||
* function it sits at the head of. It removes the need for a
|
||||
* DEBUG_LEAVE call. However, it segfaults whenever it gets anywhere
|
||||
* near cothreads. We will not use it for the moment.
|
||||
*/
|
||||
typedef void (*_debug_function_f)();
|
||||
G_GNUC_UNUSED static gchar *_debug_string_pointer = NULL;
|
||||
G_GNUC_UNUSED static GModule *_debug_self_module = NULL;
|
||||
|
||||
#define _DEBUG_ENTER_BUILTIN(format,args...) \
|
||||
static int _debug_in_wrapper = 0; \
|
||||
gchar *_debug_string = ({ \
|
||||
if (!_debug_in_wrapper) { \
|
||||
void *_return_value; \
|
||||
gchar *_debug_string; \
|
||||
_debug_function_f function; \
|
||||
void *_function_args = __builtin_apply_args(); \
|
||||
_debug_in_wrapper = 1; \
|
||||
_debug_string = g_strdup_printf(GST_DEBUG_PREFIX("")); \
|
||||
_debug_string_pointer = _debug_string; \
|
||||
fprintf(stderr,"%s: entered " __PRETTY_FUNCTION__ format "\n" , _debug_string , ## args ); \
|
||||
if (_debug_self_module == NULL) _debug_self_module = g_module_open(NULL,0); \
|
||||
g_module_symbol(_debug_self_module,__FUNCTION__,(gpointer *)&function); \
|
||||
_return_value = __builtin_apply(function,_function_args,64); \
|
||||
fprintf(stderr,"%s: left " __PRETTY_FUNCTION__ format "\n" , _debug_string , ## args ); \
|
||||
g_free(_debug_string); \
|
||||
__builtin_return(_return_value); \
|
||||
} else { \
|
||||
_debug_in_wrapper = 0; \
|
||||
} \
|
||||
_debug_string_pointer; \
|
||||
});
|
||||
|
||||
/* WARNING: there's a gcc CPP bug lurking in here. The extra space before the ##args *
|
||||
* somehow make the preprocessor leave the _debug_string. If it's removed, the *
|
||||
* _debug_string somehow gets stripped along with the ##args, and that's all she wrote. */
|
||||
#define _DEBUG_BUILTIN(format,args...) \
|
||||
if (_debug_string != (void *)-1) { \
|
||||
if (_debug_string) \
|
||||
fprintf(stderr,"%s: " format , _debug_string , ## args); \
|
||||
else \
|
||||
fprintf(stderr,GST_DEBUG_PREFIX(": " format , ## args)); \
|
||||
}
|
||||
|
||||
#ifdef GST_DEBUG_ENABLED
|
||||
#define DEBUG(format,args...) fprintf(stderr,GST_DEBUG_PREFIX(": "format , ## args ))
|
||||
#define DEBUG_ENTER(format, args...) fprintf(stderr,GST_DEBUG_PREFIX(format": entering\n" , ## args ))
|
||||
#define DEBUG_LEAVE(format, args...) fprintf(stderr,GST_DEBUG_PREFIX(format": leaving\n" , ## args ))
|
||||
#else
|
||||
#define DEBUG(format, args...)
|
||||
#define DEBUG_ENTER(format, args...)
|
||||
#define DEBUG_LEAVE(format, args...)
|
||||
#endif
|
||||
|
||||
#endif /* __GST_H__ */
|
Loading…
Reference in a new issue