* threads.c : threads implementation for the VideoLAN client
*****************************************************************************
* Copyright (C) 1999, 2000, 2001, 2002 VideoLAN
- * $Id: threads.c,v 1.13 2002/08/29 23:53:22 massiot 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 )
- /* Unimplemented */
+ 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 )
- /* Unimplemented */
+ /* 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_libvlc->SignalObjectAndWait =
+ (SIGNALOBJECTANDWAIT)GetProcAddress( hInstLib,
+ "SignalObjectAndWait" );
+ }
+ }
+ else
+ {
+ p_libvlc->SignalObjectAndWait = NULL;
+ }
+
+ 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
*****************************************************************************/
return pth_mutex_init( &p_mutex->mutex );
#elif defined( ST_INIT_IN_ST_H )
- *p_mutex->mutex = st_mutex_new();
- return ( *p_mutex == NULL ) ? errno : 0;
+ p_mutex->mutex = st_mutex_new();
+ return ( p_mutex->mutex == NULL ) ? errno : 0;
#elif defined( WIN32 )
/* We use mutexes on WinNT/2K/XP because we can use the SignalObjectAndWait
pthread_mutexattr_init( &attr );
pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_ERRORCHECK_NP );
- i_result = pthread_mutex_init( p_mutex, &attr );
+ i_result = pthread_mutex_init( &p_mutex->mutex, &attr );
pthread_mutexattr_destroy( &attr );
return( i_result );
}
return 0;
#elif defined( ST_INIT_IN_ST_H )
- i_result = st_mutex_destroy( *p_mutex );
+ i_result = st_mutex_destroy( p_mutex->mutex );
#elif defined( WIN32 )
if( p_mutex->mutex )
i_result = pthread_mutex_destroy( &p_mutex->mutex );
if ( i_result )
{
- i_thread = pthread_self();
+ i_thread = (int)pthread_self();
psz_error = strerror(i_result);
}
return pth_cond_init( &p_condvar->cond );
#elif defined( ST_INIT_IN_ST_H )
- *p_condvar->cond = st_cond_new();
- return ( *p_condvar->cond == NULL ) ? errno : 0;
+ p_condvar->cond = st_cond_new();
+ return ( p_condvar->cond == NULL ) ? errno : 0;
#elif defined( WIN32 )
/* Initialize counter */
return 0;
#elif defined( ST_INIT_IN_ST_H )
- i_result = st_cond_destroy( *p_condvar->cond );
+ i_result = st_cond_destroy( p_condvar->cond );
#elif defined( WIN32 )
if( !p_condvar->semaphore )
i_result = pthread_cond_destroy( &p_condvar->cond );
if ( i_result )
{
- i_thread = pthread_self();
+ i_thread = (int)pthread_self();
psz_error = strerror(i_result);
}