Commit 4ad9a186 authored by Sam Hocevar's avatar Sam Hocevar

* ./src/misc/threads.c: improved lazy initialization of the global lock.

parent 33f60028
......@@ -31,6 +31,7 @@ struct module_symbols_s
int (* __vlc_mutex_destroy_inner) ( char *, int, vlc_mutex_t * ) ;
int (* __vlc_mutex_init_inner) ( vlc_object_t *, vlc_mutex_t * ) ;
int (* __vlc_thread_create_inner) ( vlc_object_t *, char *, int, char *, void * ( * ) ( void * ), vlc_bool_t ) ;
int (* __vlc_threads_end_inner) ( vlc_object_t * ) ;
int (* __vlc_threads_init_inner) ( vlc_object_t * ) ;
int (* input_AccessInit_inner) ( input_thread_t * ) ;
int (* input_ChangeArea_inner) ( input_thread_t *, input_area_t * ) ;
......@@ -44,7 +45,6 @@ struct module_symbols_s
int (* input_UnselectES_inner) ( input_thread_t *, es_descriptor_t * ) ;
int (* playlist_Add_inner) ( playlist_t *, const char *, int, int ) ;
int (* playlist_Delete_inner) ( playlist_t *, int ) ;
int (* vlc_threads_end_inner) ( void ) ;
int (* vout_ChromaCmp_inner) ( u32, u32 ) ;
module_config_t * (* config_FindConfig_inner) ( vlc_object_t *, const char *psz_name ) ;
module_t * (* __module_Need_inner) ( vlc_object_t *, int, const char *, void * ) ;
......@@ -188,6 +188,7 @@ struct module_symbols_s
# define __vlc_thread_create p_symbols->__vlc_thread_create_inner
# define __vlc_thread_join p_symbols->__vlc_thread_join_inner
# define __vlc_thread_ready p_symbols->__vlc_thread_ready_inner
# define __vlc_threads_end p_symbols->__vlc_threads_end_inner
# define __vlc_threads_init p_symbols->__vlc_threads_init_inner
# define __vout_CreateThread p_symbols->__vout_CreateThread_inner
# define aout_DestroyFifo p_symbols->aout_DestroyFifo_inner
......@@ -253,7 +254,6 @@ struct module_symbols_s
# define playlist_Add p_symbols->playlist_Add_inner
# define playlist_Command p_symbols->playlist_Command_inner
# define playlist_Delete p_symbols->playlist_Delete_inner
# define vlc_threads_end p_symbols->vlc_threads_end_inner
# define vout_AllocatePicture p_symbols->vout_AllocatePicture_inner
# define vout_ChromaCmp p_symbols->vout_ChromaCmp_inner
# define vout_CreatePicture p_symbols->vout_CreatePicture_inner
......
......@@ -3,7 +3,7 @@
* This header provides a portable threads implementation.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: vlc_threads.h,v 1.4 2002/07/05 11:18:56 sam Exp $
* $Id: vlc_threads.h,v 1.5 2002/07/16 21:29:10 sam Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr>
......@@ -178,7 +178,7 @@ typedef struct
* Function definitions
*****************************************************************************/
VLC_EXPORT( int, __vlc_threads_init, ( vlc_object_t * ) );
VLC_EXPORT( int, vlc_threads_end, ( void ) );
VLC_EXPORT( int, __vlc_threads_end, ( vlc_object_t * ) );
VLC_EXPORT( int, __vlc_mutex_init, ( vlc_object_t *, vlc_mutex_t * ) );
VLC_EXPORT( int, __vlc_mutex_destroy, ( char *, int, vlc_mutex_t * ) );
VLC_EXPORT( int, __vlc_cond_init, ( vlc_object_t *, vlc_cond_t * ) );
......@@ -193,6 +193,12 @@ VLC_EXPORT( void, __vlc_thread_join, ( vlc_object_t *, char *, int ) );
#define vlc_threads_init( P_THIS ) \
__vlc_threads_init( CAST_TO_VLC_OBJECT(P_THIS) )
/*****************************************************************************
* vlc_threads_end: deinitialize threads system
*****************************************************************************/
#define vlc_threads_end( P_THIS ) \
__vlc_threads_end( CAST_TO_VLC_OBJECT(P_THIS) )
/*****************************************************************************
* vlc_mutex_init: initialize a mutex
*****************************************************************************/
......
......@@ -4,7 +4,7 @@
* and spawns threads.
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: libvlc.c,v 1.14 2002/07/15 19:15:05 sam Exp $
* $Id: libvlc.c,v 1.15 2002/07/16 21:29:10 sam Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
......@@ -771,8 +771,8 @@ vlc_error_t vlc_destroy( vlc_t *p_vlc )
}
vlc_mutex_unlock( p_vlc->p_global_lock );
/* Stop thread system FIXME: last one out please shut the door! */
//vlc_threads_end( );
/* Stop thread system: last one out please shut the door! */
vlc_threads_end( p_vlc );
/* Destroy mutexes */
vlc_mutex_destroy( &p_vlc->structure_lock );
......
......@@ -302,7 +302,7 @@ static inline const char * module_error( char *psz_buffer )
(p_symbols)->playlist_Add_inner = playlist_Add; \
(p_symbols)->playlist_Delete_inner = playlist_Delete; \
(p_symbols)->__vlc_threads_init_inner = __vlc_threads_init; \
(p_symbols)->vlc_threads_end_inner = vlc_threads_end; \
(p_symbols)->__vlc_threads_end_inner = __vlc_threads_end; \
(p_symbols)->__vlc_mutex_init_inner = __vlc_mutex_init; \
(p_symbols)->__vlc_mutex_destroy_inner = __vlc_mutex_destroy; \
(p_symbols)->__vlc_cond_init_inner = __vlc_cond_init; \
......
......@@ -2,7 +2,7 @@
* threads.c : threads implementation for the VideoLAN client
*****************************************************************************
* Copyright (C) 1999, 2000, 2001, 2002 VideoLAN
* $Id: threads.c,v 1.8 2002/07/05 11:18:56 sam Exp $
* $Id: threads.c,v 1.9 2002/07/16 21:29:10 sam Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
......@@ -68,21 +68,50 @@ typedef struct wrapper_s
#endif /* GPROF */
/*****************************************************************************
* Global mutexes for lazy initialization of the threads system
*****************************************************************************/
static volatile int i_initializations = 0;
#if defined( PTH_INIT_IN_PTH_H )
/* Unimplemented */
#elif defined( ST_INIT_IN_ST_H )
/* Unimplemented */
#elif defined( WIN32 )
/* Unimplemented */
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
static pthread_mutex_t once_mutex = PTHREAD_MUTEX_INITIALIZER;
#elif defined( HAVE_CTHREADS_H )
/* Unimplemented */
#elif defined( HAVE_KERNEL_SCHEDULER_H )
/* Unimplemented */
#endif
/*****************************************************************************
* vlc_threads_init: initialize threads system
*****************************************************************************
* This function requires lazy initialization of a global lock in order to
* keep the library really thread-safe. Some architectures don't support this
* and thus do not guarantee the complete reentrancy.
*****************************************************************************/
int __vlc_threads_init( vlc_object_t *p_this )
{
/* FIXME: this is definitely _not_ threadsafe, but at least it works
* under all implementations. We should for instance use pthread_once
* for lazy initialization of the global lock. */
static int i_status = VLC_THREADS_UNINITIALIZED;
int i_ret;
static volatile int i_status = VLC_THREADS_UNINITIALIZED;
int i_ret = 0;
if( i_status == VLC_THREADS_READY )
{
return 0;
}
#if defined( PTH_INIT_IN_PTH_H )
/* Unimplemented */
#elif defined( ST_INIT_IN_ST_H )
/* Unimplemented */
#elif defined( WIN32 )
/* Unimplemented */
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
pthread_mutex_lock( &once_mutex );
#elif defined( HAVE_CTHREADS_H )
/* Unimplemented */
#elif defined( HAVE_KERNEL_SCHEDULER_H )
/* Unimplemented */
#endif
if( i_status == VLC_THREADS_UNINITIALIZED )
{
......@@ -90,35 +119,49 @@ int __vlc_threads_init( vlc_object_t *p_this )
#if defined( PTH_INIT_IN_PTH_H )
i_ret = pth_init();
#elif defined( ST_INIT_IN_ST_H )
i_ret = st_init();
#elif defined( WIN32 )
i_ret = 0;
/* Unimplemented */
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
i_ret = 0;
/* Unimplemented */
#elif defined( HAVE_CTHREADS_H )
i_ret = 0;
/* Unimplemented */
#elif defined( HAVE_KERNEL_SCHEDULER_H )
i_ret = 0;
/* Unimplemented */
#endif
if( i_ret )
{
i_status = VLC_THREADS_ERROR;
return i_ret;
}
else
{
vlc_mutex_init( p_this, p_this->p_vlc->p_global_lock );
i_status = VLC_THREADS_READY;
}
}
else
{
i_ret = ( i_status == VLC_THREADS_READY );
}
vlc_mutex_init( p_this, p_this->p_vlc->p_global_lock );
i_status = VLC_THREADS_READY;
i_initializations++;
return i_ret;
}
#if defined( PTH_INIT_IN_PTH_H )
/* Unimplemented */
#elif defined( ST_INIT_IN_ST_H )
/* Unimplemented */
#elif defined( WIN32 )
/* Unimplemented */
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
pthread_mutex_unlock( &once_mutex );
return i_ret;
#elif defined( HAVE_CTHREADS_H )
/* Unimplemented */
#elif defined( HAVE_KERNEL_SCHEDULER_H )
/* Unimplemented */
#endif
/* Wait until the other thread has initialized the thread library */
while( i_status == VLC_THREADS_PENDING )
......@@ -126,30 +169,45 @@ int __vlc_threads_init( vlc_object_t *p_this )
msleep( THREAD_SLEEP );
}
return( i_status == VLC_THREADS_READY );
return i_status == VLC_THREADS_READY;
}
/*****************************************************************************
* vlc_threads_end: stop threads system
*****************************************************************************
* FIXME: This function is far from being threadsafe. We should undo exactly
* what we did above in vlc_threads_init.
*****************************************************************************/
int vlc_threads_end( void )
int __vlc_threads_end( vlc_object_t *p_this )
{
#if defined( PTH_INIT_IN_PTH_H )
return pth_kill();
i_initializations--;
if( i_initializations == 0 )
{
return pth_kill();
}
return 0;
#elif defined( ST_INIT_IN_ST_H )
i_initializations--;
return 0;
#elif defined( WIN32 )
i_initializations--;
return 0;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
pthread_mutex_lock( &once_mutex );
i_initializations--;
pthread_mutex_unlock( &once_mutex );
return 0;
#elif defined( HAVE_CTHREADS_H )
i_initializations--;
return 0;
#elif defined( HAVE_KERNEL_SCHEDULER_H )
i_initializations--;
return 0;
#endif
......
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