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:
Erik Walthinsen 2000-12-04 09:35:08 +00:00
parent 47bd1b0545
commit 29d567ba23
7 changed files with 143 additions and 36 deletions

View file

@ -16,4 +16,4 @@
#undef HAVE_ATOMIC_H
#undef DEBUG_ENABLED
#undef GST_DEBUG_ENABLED

View file

@ -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 #

View file

@ -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)

View file

@ -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;
}

View file

@ -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__ */

View file

@ -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
View 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__ */