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 * ) ;
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 * ) ;
# 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
# 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
* 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>
* 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 * ) );
#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
*****************************************************************************/
* 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>
}
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 );
(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; \
* 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>
#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 )
{
#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 )
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