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 ...@@ -31,6 +31,7 @@ struct module_symbols_s
int (* __vlc_mutex_destroy_inner) ( char *, int, vlc_mutex_t * ) ; int (* __vlc_mutex_destroy_inner) ( char *, int, vlc_mutex_t * ) ;
int (* __vlc_mutex_init_inner) ( vlc_object_t *, 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_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 (* __vlc_threads_init_inner) ( vlc_object_t * ) ;
int (* input_AccessInit_inner) ( input_thread_t * ) ; int (* input_AccessInit_inner) ( input_thread_t * ) ;
int (* input_ChangeArea_inner) ( input_thread_t *, input_area_t * ) ; int (* input_ChangeArea_inner) ( input_thread_t *, input_area_t * ) ;
...@@ -44,7 +45,6 @@ struct module_symbols_s ...@@ -44,7 +45,6 @@ struct module_symbols_s
int (* input_UnselectES_inner) ( input_thread_t *, es_descriptor_t * ) ; int (* input_UnselectES_inner) ( input_thread_t *, es_descriptor_t * ) ;
int (* playlist_Add_inner) ( playlist_t *, const char *, int, int ) ; int (* playlist_Add_inner) ( playlist_t *, const char *, int, int ) ;
int (* playlist_Delete_inner) ( playlist_t *, int ) ; int (* playlist_Delete_inner) ( playlist_t *, int ) ;
int (* vlc_threads_end_inner) ( void ) ;
int (* vout_ChromaCmp_inner) ( u32, u32 ) ; int (* vout_ChromaCmp_inner) ( u32, u32 ) ;
module_config_t * (* config_FindConfig_inner) ( vlc_object_t *, const char *psz_name ) ; 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 * ) ; module_t * (* __module_Need_inner) ( vlc_object_t *, int, const char *, void * ) ;
...@@ -188,6 +188,7 @@ struct module_symbols_s ...@@ -188,6 +188,7 @@ struct module_symbols_s
# define __vlc_thread_create p_symbols->__vlc_thread_create_inner # define __vlc_thread_create p_symbols->__vlc_thread_create_inner
# define __vlc_thread_join p_symbols->__vlc_thread_join_inner # define __vlc_thread_join p_symbols->__vlc_thread_join_inner
# define __vlc_thread_ready p_symbols->__vlc_thread_ready_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 __vlc_threads_init p_symbols->__vlc_threads_init_inner
# define __vout_CreateThread p_symbols->__vout_CreateThread_inner # define __vout_CreateThread p_symbols->__vout_CreateThread_inner
# define aout_DestroyFifo p_symbols->aout_DestroyFifo_inner # define aout_DestroyFifo p_symbols->aout_DestroyFifo_inner
...@@ -253,7 +254,6 @@ struct module_symbols_s ...@@ -253,7 +254,6 @@ struct module_symbols_s
# define playlist_Add p_symbols->playlist_Add_inner # define playlist_Add p_symbols->playlist_Add_inner
# define playlist_Command p_symbols->playlist_Command_inner # define playlist_Command p_symbols->playlist_Command_inner
# define playlist_Delete p_symbols->playlist_Delete_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_AllocatePicture p_symbols->vout_AllocatePicture_inner
# define vout_ChromaCmp p_symbols->vout_ChromaCmp_inner # define vout_ChromaCmp p_symbols->vout_ChromaCmp_inner
# define vout_CreatePicture p_symbols->vout_CreatePicture_inner # define vout_CreatePicture p_symbols->vout_CreatePicture_inner
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* This header provides a portable threads implementation. * This header provides a portable threads implementation.
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * 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> * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr> * Samuel Hocevar <sam@via.ecp.fr>
...@@ -178,7 +178,7 @@ typedef struct ...@@ -178,7 +178,7 @@ typedef struct
* Function definitions * Function definitions
*****************************************************************************/ *****************************************************************************/
VLC_EXPORT( int, __vlc_threads_init, ( vlc_object_t * ) ); 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_init, ( vlc_object_t *, vlc_mutex_t * ) );
VLC_EXPORT( int, __vlc_mutex_destroy, ( char *, int, 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 * ) ); 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 ) ); ...@@ -193,6 +193,12 @@ VLC_EXPORT( void, __vlc_thread_join, ( vlc_object_t *, char *, int ) );
#define vlc_threads_init( P_THIS ) \ #define vlc_threads_init( P_THIS ) \
__vlc_threads_init( CAST_TO_VLC_OBJECT(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 * vlc_mutex_init: initialize a mutex
*****************************************************************************/ *****************************************************************************/
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* and spawns threads. * and spawns threads.
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * 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> * Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org> * Samuel Hocevar <sam@zoy.org>
...@@ -771,8 +771,8 @@ vlc_error_t vlc_destroy( vlc_t *p_vlc ) ...@@ -771,8 +771,8 @@ vlc_error_t vlc_destroy( vlc_t *p_vlc )
} }
vlc_mutex_unlock( p_vlc->p_global_lock ); vlc_mutex_unlock( p_vlc->p_global_lock );
/* Stop thread system FIXME: last one out please shut the door! */ /* Stop thread system: last one out please shut the door! */
//vlc_threads_end( ); vlc_threads_end( p_vlc );
/* Destroy mutexes */ /* Destroy mutexes */
vlc_mutex_destroy( &p_vlc->structure_lock ); vlc_mutex_destroy( &p_vlc->structure_lock );
......
...@@ -302,7 +302,7 @@ static inline const char * module_error( char *psz_buffer ) ...@@ -302,7 +302,7 @@ static inline const char * module_error( char *psz_buffer )
(p_symbols)->playlist_Add_inner = playlist_Add; \ (p_symbols)->playlist_Add_inner = playlist_Add; \
(p_symbols)->playlist_Delete_inner = playlist_Delete; \ (p_symbols)->playlist_Delete_inner = playlist_Delete; \
(p_symbols)->__vlc_threads_init_inner = __vlc_threads_init; \ (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_init_inner = __vlc_mutex_init; \
(p_symbols)->__vlc_mutex_destroy_inner = __vlc_mutex_destroy; \ (p_symbols)->__vlc_mutex_destroy_inner = __vlc_mutex_destroy; \
(p_symbols)->__vlc_cond_init_inner = __vlc_cond_init; \ (p_symbols)->__vlc_cond_init_inner = __vlc_cond_init; \
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* threads.c : threads implementation for the VideoLAN client * threads.c : threads implementation for the VideoLAN client
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000, 2001, 2002 VideoLAN * 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> * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org> * Samuel Hocevar <sam@zoy.org>
...@@ -68,21 +68,50 @@ typedef struct wrapper_s ...@@ -68,21 +68,50 @@ typedef struct wrapper_s
#endif /* GPROF */ #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 * 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 ) int __vlc_threads_init( vlc_object_t *p_this )
{ {
/* FIXME: this is definitely _not_ threadsafe, but at least it works static volatile int i_status = VLC_THREADS_UNINITIALIZED;
* under all implementations. We should for instance use pthread_once int i_ret = 0;
* for lazy initialization of the global lock. */
static int i_status = VLC_THREADS_UNINITIALIZED;
int i_ret;
if( i_status == VLC_THREADS_READY ) #if defined( PTH_INIT_IN_PTH_H )
{ /* Unimplemented */
return 0; #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 ) if( i_status == VLC_THREADS_UNINITIALIZED )
{ {
...@@ -90,35 +119,49 @@ int __vlc_threads_init( vlc_object_t *p_this ) ...@@ -90,35 +119,49 @@ int __vlc_threads_init( vlc_object_t *p_this )
#if defined( PTH_INIT_IN_PTH_H ) #if defined( PTH_INIT_IN_PTH_H )
i_ret = pth_init(); i_ret = pth_init();
#elif defined( ST_INIT_IN_ST_H ) #elif defined( ST_INIT_IN_ST_H )
i_ret = st_init(); i_ret = st_init();
#elif defined( WIN32 ) #elif defined( WIN32 )
i_ret = 0; /* Unimplemented */
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
i_ret = 0; /* Unimplemented */
#elif defined( HAVE_CTHREADS_H ) #elif defined( HAVE_CTHREADS_H )
i_ret = 0; /* Unimplemented */
#elif defined( HAVE_KERNEL_SCHEDULER_H ) #elif defined( HAVE_KERNEL_SCHEDULER_H )
i_ret = 0; /* Unimplemented */
#endif #endif
if( i_ret ) if( i_ret )
{ {
i_status = VLC_THREADS_ERROR; i_status = VLC_THREADS_ERROR;
return i_ret;
} }
else
{
vlc_mutex_init( p_this, p_this->p_vlc->p_global_lock ); vlc_mutex_init( p_this, p_this->p_vlc->p_global_lock );
i_status = VLC_THREADS_READY; i_status = VLC_THREADS_READY;
}
}
else
{
i_ret = ( i_status == VLC_THREADS_READY );
}
i_initializations++;
#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; 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 */ /* Wait until the other thread has initialized the thread library */
while( i_status == VLC_THREADS_PENDING ) while( i_status == VLC_THREADS_PENDING )
...@@ -126,30 +169,45 @@ int __vlc_threads_init( vlc_object_t *p_this ) ...@@ -126,30 +169,45 @@ int __vlc_threads_init( vlc_object_t *p_this )
msleep( THREAD_SLEEP ); msleep( THREAD_SLEEP );
} }
return( i_status == VLC_THREADS_READY ); return i_status == VLC_THREADS_READY;
} }
/***************************************************************************** /*****************************************************************************
* vlc_threads_end: stop threads system * 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 ) #if defined( PTH_INIT_IN_PTH_H )
i_initializations--;
if( i_initializations == 0 )
{
return pth_kill(); return pth_kill();
}
return 0;
#elif defined( ST_INIT_IN_ST_H ) #elif defined( ST_INIT_IN_ST_H )
i_initializations--;
return 0; return 0;
#elif defined( WIN32 ) #elif defined( WIN32 )
i_initializations--;
return 0; return 0;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
pthread_mutex_lock( &once_mutex );
i_initializations--;
pthread_mutex_unlock( &once_mutex );
return 0; return 0;
#elif defined( HAVE_CTHREADS_H ) #elif defined( HAVE_CTHREADS_H )
i_initializations--;
return 0; return 0;
#elif defined( HAVE_KERNEL_SCHEDULER_H ) #elif defined( HAVE_KERNEL_SCHEDULER_H )
i_initializations--;
return 0; return 0;
#endif #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