]> git.sesse.net Git - vlc/blobdiff - src/misc/threads.c
* ./src/libvlc.c, ./include/main.h: the root of all objects is now
[vlc] / src / misc / threads.c
index 31ba463b8014738e2669967010f08e54464f10b6..aba753da7a64062bee8faf2cef1ce708cd9913d7 100644 (file)
@@ -2,7 +2,7 @@
  * 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
 
 /*****************************************************************************
@@ -97,79 +54,102 @@ static volatile int i_initializations = 0;
 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;
 }
 
 /*****************************************************************************
@@ -186,33 +166,66 @@ int __vlc_threads_end( vlc_object_t *p_this )
     {
         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
  *****************************************************************************/
@@ -224,8 +237,8 @@ int __vlc_mutex_init( vlc_object_t *p_this, vlc_mutex_t *p_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
@@ -254,7 +267,7 @@ int __vlc_mutex_init( vlc_object_t *p_this, vlc_mutex_t *p_mutex )
 
         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 );
     }
@@ -303,7 +316,7 @@ int __vlc_mutex_destroy( char * psz_file, int i_line, vlc_mutex_t *p_mutex )
     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 )
@@ -320,7 +333,7 @@ int __vlc_mutex_destroy( char * psz_file, int i_line, vlc_mutex_t *p_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);
     }
 
@@ -357,8 +370,8 @@ int __vlc_cond_init( vlc_object_t *p_this, vlc_cond_t *p_condvar )
     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 */
@@ -441,7 +454,7 @@ int __vlc_cond_destroy( char * psz_file, int i_line, vlc_cond_t *p_condvar )
     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 )
@@ -454,7 +467,7 @@ int __vlc_cond_destroy( char * psz_file, int i_line, vlc_cond_t *p_condvar )
     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);
     }