* threads.c : threads implementation for the VideoLAN client
*****************************************************************************
* Copyright (C) 1999, 2000, 2001, 2002 VideoLAN
- * $Id: threads.c,v 1.17 2002/09/29 18:16:04 sam Exp $
+ * $Id: threads.c,v 1.18 2002/10/03 13:21:55 sam Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
#define VLC_THREADS_READY 3
/*****************************************************************************
- * Prototype for GPROF wrapper
- *****************************************************************************/
-#ifdef GPROF
-/* Wrapper function for profiling */
-static void * vlc_thread_wrapper ( void *p_wrapper );
-
-# ifdef WIN32
-
-# define ITIMER_REAL 1
-# define ITIMER_PROF 2
-
-struct itimerval
-{
- struct timeval it_value;
- struct timeval it_interval;
-};
-
-int setitimer(int kind, const struct itimerval* itnew, struct itimerval* itold);
-# endif /* WIN32 */
-
-typedef struct wrapper_t
-{
- /* Data lock access */
- vlc_mutex_t lock;
- vlc_cond_t wait;
-
- /* Data used to spawn the real thread */
- vlc_thread_func_t func;
- void *p_data;
-
- /* Profiling timer passed to the thread */
- struct itimerval itimer;
-
-} wrapper_t;
-
-#endif /* GPROF */
-
-/*****************************************************************************
- * Global mutexes for lazy initialization of the threads system
+ * Global mutex 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
/*****************************************************************************
int __vlc_threads_init( vlc_object_t *p_this )
{
static volatile int i_status = VLC_THREADS_UNINITIALIZED;
- int i_ret = 0;
+ libvlc_t *p_libvlc = (libvlc_t *)p_this;
+ int i_ret = VLC_SUCCESS;
+
+ /* If we have lazy mutex initialization, use it. Otherwise, we just
+ * hope nothing wrong happens. */
#if defined( PTH_INIT_IN_PTH_H )
- /* Unimplemented */
#elif defined( ST_INIT_IN_ST_H )
- /* Unimplemented */
#elif defined( WIN32 )
HINSTANCE hInstLib;
#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 )
{
i_status = VLC_THREADS_PENDING;
+ /* We should be safe now. Do all the initialization stuff we want. */
+ vlc_object_create( p_libvlc, VLC_OBJECT_ROOT );
+ p_libvlc->b_ready = VLC_FALSE;
+
#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 )
- /* dynamically get the address of SignalObjectAndWait */
+ /* Dynamically get the address of SignalObjectAndWait */
if( GetVersion() < 0x80000000 )
{
/* We are running on NT/2K/XP, we can use SignalObjectAndWait */
hInstLib = LoadLibrary( "kernel32" );
if( hInstLib )
{
- p_this->p_vlc->SignalObjectAndWait =
+ p_libvlc->SignalObjectAndWait =
(SIGNALOBJECTANDWAIT)GetProcAddress( hInstLib,
"SignalObjectAndWait" );
}
}
else
{
- p_this->p_vlc->SignalObjectAndWait = NULL;
+ p_libvlc->SignalObjectAndWait = NULL;
}
- p_this->p_vlc->b_fast_mutex = 0;
- p_this->p_vlc->i_win9x_cv = 0;
+ p_libvlc->b_fast_mutex = 0;
+ p_libvlc->i_win9x_cv = 0;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
- /* Unimplemented */
#elif defined( HAVE_CTHREADS_H )
- /* Unimplemented */
#elif defined( HAVE_KERNEL_SCHEDULER_H )
- /* Unimplemented */
#endif
+ vlc_mutex_init( p_libvlc, &p_libvlc->global_lock );
+
if( i_ret )
{
i_status = VLC_THREADS_ERROR;
}
else
{
- vlc_mutex_init( p_this, p_this->p_vlc->p_global_lock );
+ i_initializations++;
i_status = VLC_THREADS_READY;
}
}
else
{
- i_ret = ( i_status == VLC_THREADS_READY );
+ /* Just increment the initialization count */
+ i_initializations++;
}
- i_initializations++;
-
+ /* If we have lazy mutex initialization support, unlock the mutex;
+ * otherwize, do a naive wait loop. */
#if defined( PTH_INIT_IN_PTH_H )
- /* Unimplemented */
+ while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
#elif defined( ST_INIT_IN_ST_H )
- /* Unimplemented */
+ while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
#elif defined( WIN32 )
- /* Unimplemented */
+ while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
pthread_mutex_unlock( &once_mutex );
- return i_ret;
#elif defined( HAVE_CTHREADS_H )
- /* Unimplemented */
+ while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
#elif defined( HAVE_KERNEL_SCHEDULER_H )
- /* Unimplemented */
+ while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
#endif
- /* Wait until the other thread has initialized the thread library */
- while( i_status == VLC_THREADS_PENDING )
+ if( i_status != VLC_THREADS_READY )
{
- msleep( THREAD_SLEEP );
+ return VLC_ETHREAD;
}
- return i_status == VLC_THREADS_READY;
+ return i_ret;
}
/*****************************************************************************
{
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
+ return VLC_SUCCESS;
}
+/*****************************************************************************
+ * Prototype for GPROF wrapper
+ *****************************************************************************/
+#ifdef GPROF
+/* Wrapper function for profiling */
+static void * vlc_thread_wrapper ( void *p_wrapper );
+
+# ifdef WIN32
+
+# define ITIMER_REAL 1
+# define ITIMER_PROF 2
+
+struct itimerval
+{
+ struct timeval it_value;
+ struct timeval it_interval;
+};
+
+int setitimer(int kind, const struct itimerval* itnew, struct itimerval* itold);
+# endif /* WIN32 */
+
+typedef struct wrapper_t
+{
+ /* Data lock access */
+ vlc_mutex_t lock;
+ vlc_cond_t wait;
+
+ /* Data used to spawn the real thread */
+ vlc_thread_func_t func;
+ void *p_data;
+
+ /* Profiling timer passed to the thread */
+ struct itimerval itimer;
+
+} wrapper_t;
+
+#endif /* GPROF */
+
/*****************************************************************************
* vlc_mutex_init: initialize a mutex
*****************************************************************************/