Commit 44abaa7c authored by Sam Hocevar's avatar Sam Hocevar

  * Added gprof profiling support with --enable-profiling.

    It works at last! configure with --enable-profiling, build, run
 vlc (you may want to add --noaudio, it currently segfaults with sound
 here) and launch "gprof vlc" when finished.

    To make gprof work with multithreaded programs, one needs to set the
 internal ITIMER_PROF timer for each new thread launched. I did this
 through a wrapper in vlc_thread_create (see include/threads.h).
parent cff6378d
......@@ -4,6 +4,7 @@
HEAD
* Added gprof profiling support with --enable-profiling.
* Fully working Windows DVD ioctl support by Jon Lech Johansen.
* DirectX enhancements by Gildas Bazin, such as software rendering.
* Merged dvdcss_init and dvdcss_open into dvdcss_open, and dvdcss_close
......
......@@ -35,6 +35,7 @@ ARCH = @ARCH@
DEBUG = @DEBUG@
STATS = @STATS@
TRACE = @TRACE@
PROFILING = @PROFILING@
OPTIMS = @OPTIMS@
GETOPT = @GETOPT@
......@@ -107,6 +108,10 @@ ifeq ($(TRACE),1)
PROGRAM_OPTIONS += TRACE
DEFINE += -DTRACE
endif
ifeq ($(PROFILING),1)
PROGRAM_OPTIONS += PROFILING
DEFINE += -DPROFILING
endif
ifeq ($(STATS),1)
PROGRAM_OPTIONS += STATS
DEFINE += -DSTATS
......@@ -196,8 +201,10 @@ ifeq ($(OPTIMS),1)
CFLAGS += -O3
CFLAGS += -ffast-math -funroll-loops
ifneq ($(DEBUG),1)
ifneq ($(PROFILING),1)
CFLAGS += -fomit-frame-pointer
endif
endif
# Optimizations for x86 familiy
ifneq (,$(findstring 86,$(ARCH)))
......@@ -259,3 +266,7 @@ ifeq ($(DEBUG),1)
CFLAGS += -g
endif
ifeq ($(PROFILING),1)
CFLAGS += -pg
endif
This diff is collapsed.
......@@ -217,22 +217,6 @@ AC_CHECK_HEADERS(sys/ioctl.h,[
])
])
dnl
dnl GNU portable threads
dnl
AC_ARG_ENABLE(pth,
[ --enable-pth Enable GNU Pth support (default disabled)],
[ if test x$enableval = xyes; then
AC_CHECK_LIB(pth,pth_init)
AC_EGREP_HEADER(pth_init,pth.h,[
AC_DEFINE(PTH_INIT_IN_PTH_H, 1,
Define if <pth.h> defines pth_init)
THREAD_LIB="-lpth"
fi])
])
LIB="${LIB} ${THREAD_LIB}"
dnl
dnl PentiumPro acceleration
dnl
......@@ -262,14 +246,6 @@ AC_ARG_ENABLE(altivec,
fi ])
#[ if test -d /System/Library/Frameworks/vecLib.framework; then ARCH="${ARCH} altivec"; PLUGINS="${PLUGINS} idctaltivec"; fi ])
dnl
dnl CSS DVD decryption
dnl
AC_ARG_ENABLE(css,
[ --disable-css Disable DVD CSS decryption (default enabled)],
[ if test x$enableval = xyes; then CSS=1; else CSS=0; fi ], [ CSS=1; ])
if test x${CSS} = x1; then AC_DEFINE(HAVE_CSS, 1, Define if you want DVD CSS decryption.) fi
dnl
dnl Debugging mode
dnl
......@@ -291,6 +267,13 @@ AC_ARG_ENABLE(trace,
[ --enable-trace Enable trace mode (default disabled)],
[ if test x$enableval = xyes; then TRACE=1; fi ])
dnl
dnl Trace mode
dnl
AC_ARG_ENABLE(profiling,
[ --enable-profiling Enable gprof profiling (default disabled)],
[ if test x$enableval = xyes; then PROFILING=1; fi ])
dnl
dnl Enable/disable optimizations
dnl
......@@ -299,6 +282,30 @@ AC_ARG_ENABLE(optimizations,
[ if test x$enableval = xno; then OPTIMS=0; fi ],
[ OPTIMS=1 ])
dnl
dnl GNU portable threads
dnl
AC_ARG_ENABLE(pth,
[ --enable-pth Enable GNU Pth support (default disabled)],
[ if test x$enableval = xyes; then
AC_CHECK_LIB(pth,pth_init)
AC_EGREP_HEADER(pth_init,pth.h,[
AC_DEFINE(PTH_INIT_IN_PTH_H, 1,
Define if <pth.h> defines pth_init)
THREAD_LIB="-lpth"
fi])
])
LIB="${LIB} ${THREAD_LIB}"
dnl
dnl CSS DVD decryption
dnl
AC_ARG_ENABLE(css,
[ --disable-css Disable DVD CSS decryption (default enabled)],
[ if test x$enableval = xyes; then CSS=1; else CSS=0; fi ], [ CSS=1; ])
if test x${CSS} = x1; then AC_DEFINE(HAVE_CSS, 1, Define if you want DVD CSS decryption.) fi
dnl
dnl DVD module: check for installed libdvdcss or local libdvdcss
dnl TODO: use user-provided --with-dvdcss flag
......@@ -619,6 +626,7 @@ AC_SUBST(DEBUG)
AC_SUBST(STATS)
AC_SUBST(ASM)
AC_SUBST(TRACE)
AC_SUBST(PROFILING)
AC_SUBST(OPTIMS)
AC_SUBST(CSS)
AC_SUBST(MOC)
......@@ -671,6 +679,7 @@ vlc version : ${VLC_VERSION}
debug mode : ${DEBUG}
statistics : ${STATS}
trace mode : ${TRACE}
profiling : ${PROFILING}
need builtin getopt : ${GETOPT}
built-in modules :${BUILTINS}
plugin modules :${PLUGINS}
......
......@@ -3,7 +3,7 @@
* This header provides a portable threads implementation.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: threads.h,v 1.18 2001/06/14 01:49:44 sam Exp $
* $Id: threads.h,v 1.19 2001/06/14 20:21:04 sam Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr>
......@@ -25,6 +25,10 @@
#include <stdio.h>
#ifdef PROFILING
# include <sys/time.h>
#endif
#if defined( PTH_INIT_IN_PTH_H ) /* GNU Pth */
# include <pth.h>
......@@ -143,10 +147,8 @@ typedef void *(*vlc_thread_func_t)(void *p_data);
* Prototypes
*****************************************************************************/
static __inline__ int vlc_thread_create ( vlc_thread_t *, char *,
vlc_thread_func_t, void * );
static __inline__ void vlc_thread_exit ( void );
static __inline__ void vlc_thread_join ( vlc_thread_t );
static __inline__ int vlc_threads_init ( void );
static __inline__ int vlc_threads_end ( void );
static __inline__ int vlc_mutex_init ( vlc_mutex_t * );
static __inline__ int vlc_mutex_lock ( vlc_mutex_t * );
......@@ -158,103 +160,78 @@ static __inline__ int vlc_cond_signal ( vlc_cond_t * );
static __inline__ int vlc_cond_wait ( vlc_cond_t *, vlc_mutex_t * );
static __inline__ int vlc_cond_destroy ( vlc_cond_t * );
static __inline__ int vlc_thread_create ( vlc_thread_t *, char *,
vlc_thread_func_t, void * );
static __inline__ void vlc_thread_exit ( void );
static __inline__ void vlc_thread_join ( vlc_thread_t );
#if 0
static __inline__ int vlc_cond_timedwait( vlc_cond_t *, vlc_mutex_t *,
mtime_t );
#endif
/*****************************************************************************
* vlc_thread_create: create a thread
*****************************************************************************/
static __inline__ int vlc_thread_create( vlc_thread_t *p_thread,
char *psz_name, vlc_thread_func_t func,
void *p_data )
{
#if defined( PTH_INIT_IN_PTH_H )
*p_thread = pth_spawn( PTH_ATTR_DEFAULT, func, p_data );
return ( p_thread == NULL );
#ifdef PROFILING
/* Wrapper function for profiling */
static void * vlc_thread_wrapper ( void *p_wrapper );
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
return pthread_create( p_thread, NULL, func, p_data );
#elif defined( HAVE_CTHREADS_H )
*p_thread = cthread_fork( (cthread_fn_t)func, (any_t)p_data );
return 0;
typedef struct wrapper_s
{
/* Data lock access */
vlc_mutex_t lock;
vlc_cond_t wait;
#elif defined( HAVE_KERNEL_SCHEDULER_H )
*p_thread = spawn_thread( (thread_func)func, psz_name,
B_NORMAL_PRIORITY, p_data );
return resume_thread( *p_thread );
/* Data used to spawn the real thread */
vlc_thread_func_t func;
void *p_data;
#elif defined( WIN32 )
#if 0
DWORD threadID;
/* This method is not recommended when using the MSVCRT C library,
* so we'll have to use _beginthreadex instead */
*p_thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) func,
p_data, 0, &threadID);
#endif
unsigned threadID;
/* When using the MSVCRT C library you have to use the _beginthreadex
* function instead of CreateThread, otherwise you'll end up with memory
* leaks and the signal function not working */
*p_thread = (HANDLE)_beginthreadex(NULL, 0, (PTHREAD_START) func,
p_data, 0, &threadID);
return( *p_thread ? 0 : 1 );
/* Profiling timer passed to the thread */
struct itimerval itimer;
} wrapper_t;
#endif
}
/*****************************************************************************
* vlc_thread_exit: terminate a thread
* vlc_threads_init: initialize threads system
*****************************************************************************/
static __inline__ void vlc_thread_exit( void )
static __inline__ int vlc_threads_init( void )
{
#if defined( PTH_INIT_IN_PTH_H )
pth_exit( 0 );
return pth_init();
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
pthread_exit( 0 );
return 0;
#elif defined( HAVE_CTHREADS_H )
int result;
cthread_exit( &result );
return 0;
#elif defined( HAVE_KERNEL_SCHEDULER_H )
exit_thread( 0 );
return 0;
#elif defined( WIN32 )
#if 0
ExitThread( 0 );
#endif
/* For now we don't close the thread handles (because of race conditions).
* Need to be looked at. */
_endthreadex(0);
return 0;
#endif
}
/*****************************************************************************
* vlc_thread_join: wait until a thread exits
* vlc_threads_end: stop threads system
*****************************************************************************/
static __inline__ void vlc_thread_join( vlc_thread_t thread )
static __inline__ int vlc_threads_end( void )
{
#if defined( PTH_INIT_IN_PTH_H )
pth_join( thread, NULL );
return pth_kill();
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
pthread_join( thread, NULL );
return 0;
#elif defined( HAVE_CTHREADS_H )
cthread_join( thread );
return 0;
#elif defined( HAVE_KERNEL_SCHEDULER_H )
int32 exit_value;
wait_for_thread( thread, &exit_value );
return 0;
#elif defined( WIN32 )
WaitForSingleObject( thread, INFINITE);
return 0;
#endif
}
......@@ -593,3 +570,151 @@ static __inline__ int vlc_cond_destroy( vlc_cond_t *p_condvar )
#endif
}
/*****************************************************************************
* vlc_thread_create: create a thread
*****************************************************************************/
static __inline__ int vlc_thread_create( vlc_thread_t *p_thread,
char *psz_name, vlc_thread_func_t func,
void *p_data )
{
int i_ret;
#ifdef PROFILING
wrapper_t wrapper;
/* Initialize the wrapper structure */
wrapper.func = func;
wrapper.p_data = p_data;
getitimer( ITIMER_PROF, &wrapper.itimer );
vlc_mutex_init( &wrapper.lock );
vlc_cond_init( &wrapper.wait );
vlc_mutex_lock( &wrapper.lock );
/* Alter user-passed data so that we call the wrapper instead
* of the real function */
p_data = &wrapper;
func = vlc_thread_wrapper;
#endif
#if defined( PTH_INIT_IN_PTH_H )
*p_thread = pth_spawn( PTH_ATTR_DEFAULT, func, p_data );
i_ret = ( p_thread == NULL );
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
i_ret = pthread_create( p_thread, NULL, func, p_data );
#elif defined( HAVE_CTHREADS_H )
*p_thread = cthread_fork( (cthread_fn_t)func, (any_t)p_data );
i_ret = 0;
#elif defined( HAVE_KERNEL_SCHEDULER_H )
*p_thread = spawn_thread( (thread_func)func, psz_name,
B_NORMAL_PRIORITY, p_data );
i_ret = resume_thread( *p_thread );
#elif defined( WIN32 )
#if 0
DWORD threadID;
/* This method is not recommended when using the MSVCRT C library,
* so we'll have to use _beginthreadex instead */
*p_thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) func,
p_data, 0, &threadID);
#endif
unsigned threadID;
/* When using the MSVCRT C library you have to use the _beginthreadex
* function instead of CreateThread, otherwise you'll end up with memory
* leaks and the signal function not working */
*p_thread = (HANDLE)_beginthreadex(NULL, 0, (PTHREAD_START) func,
p_data, 0, &threadID);
i_ret = ( *p_thread ? 0 : 1 );
#endif
#ifdef PROFILING
if( i_ret == 0 )
{
vlc_cond_wait( &wrapper.wait, &wrapper.lock );
}
vlc_mutex_unlock( &wrapper.lock );
vlc_mutex_destroy( &wrapper.lock );
vlc_cond_destroy( &wrapper.wait );
#endif
return i_ret;
}
/*****************************************************************************
* vlc_thread_exit: terminate a thread
*****************************************************************************/
static __inline__ void vlc_thread_exit( void )
{
#if defined( PTH_INIT_IN_PTH_H )
pth_exit( 0 );
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
pthread_exit( 0 );
#elif defined( HAVE_CTHREADS_H )
int result;
cthread_exit( &result );
#elif defined( HAVE_KERNEL_SCHEDULER_H )
exit_thread( 0 );
#elif defined( WIN32 )
#if 0
ExitThread( 0 );
#endif
/* For now we don't close the thread handles (because of race conditions).
* Need to be looked at. */
_endthreadex(0);
#endif
}
/*****************************************************************************
* vlc_thread_join: wait until a thread exits
*****************************************************************************/
static __inline__ void vlc_thread_join( vlc_thread_t thread )
{
#if defined( PTH_INIT_IN_PTH_H )
pth_join( thread, NULL );
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
pthread_join( thread, NULL );
#elif defined( HAVE_CTHREADS_H )
cthread_join( thread );
#elif defined( HAVE_KERNEL_SCHEDULER_H )
int32 exit_value;
wait_for_thread( thread, &exit_value );
#elif defined( WIN32 )
WaitForSingleObject( thread, INFINITE);
#endif
}
#ifdef PROFILING
static void *vlc_thread_wrapper( void *p_wrapper )
{
/* Put user data in thread-local variables */
void * p_data = ((wrapper_t*)p_wrapper)->p_data;
vlc_thread_func_t func = ((wrapper_t*)p_wrapper)->func;
/* Set the profile timer value */
setitimer( ITIMER_PROF, &((wrapper_t*)p_wrapper)->itimer, NULL );
/* Tell the calling thread that we don't need its data anymore */
vlc_mutex_lock( &((wrapper_t*)p_wrapper)->lock );
vlc_cond_signal( &((wrapper_t*)p_wrapper)->wait );
vlc_mutex_unlock( &((wrapper_t*)p_wrapper)->lock );
/* Call the real function */
return func( p_data );
}
#endif
......@@ -4,7 +4,7 @@
* and spawn threads.
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: main.c,v 1.103 2001/06/14 01:49:44 sam Exp $
* $Id: main.c,v 1.104 2001/06/14 20:21:04 sam Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
......@@ -252,11 +252,9 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
p_vout_bank = &vout_bank;
/*
* Initialize threads
* Initialize threads system
*/
#if defined( PTH_INIT_IN_PTH_H )
pth_init( );
#endif
vlc_threads_init( );
/*
* Test if our code is likely to run on this CPU
......@@ -399,9 +397,10 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
intf_Msg( "intf: program terminated" );
intf_MsgDestroy();
#if defined( PTH_INIT_IN_PTH_H )
pth_kill( );
#endif
/*
* Stop threads system
*/
vlc_threads_end( );
return 0;
}
......
......@@ -3,7 +3,7 @@
* Functions are prototyped in mtime.h.
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: mtime.c,v 1.22 2001/06/14 01:49:44 sam Exp $
* $Id: mtime.c,v 1.23 2001/06/14 20:21:04 sam Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
*
......@@ -229,15 +229,15 @@ void msleep( mtime_t delay )
#if defined( HAVE_KERNEL_OS_H )
snooze( delay );
#elif defined( HAVE_USLEEP ) || defined( WIN32 )
usleep( delay );
#elif defined( PTH_INIT_IN_PTH_H )
struct timeval tv_delay;
tv_delay.tv_sec = delay / 1000000;
tv_delay.tv_usec = delay % 1000000;
pth_select( 0, NULL, NULL, NULL, &tv_delay );
#elif defined( HAVE_USLEEP ) || defined( WIN32 )
usleep( delay );
#else
struct timeval tv_delay;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment