Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

threads.c

00001 /*****************************************************************************
00002  * threads.c : threads implementation for the VideoLAN client
00003  *****************************************************************************
00004  * Copyright (C) 1999-2004 the VideoLAN team
00005  * $Id: threads.c 12854 2005-10-16 18:01:09Z hartman $
00006  *
00007  * Authors: Jean-Marc Dressler <[email protected]>
00008  *          Samuel Hocevar <[email protected]>
00009  *          Gildas Bazin <[email protected]>
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00024  *****************************************************************************/
00025 
00026 #include <vlc/vlc.h>
00027 
00028 #include <stdlib.h>
00029 
00030 #define VLC_THREADS_UNINITIALIZED  0
00031 #define VLC_THREADS_PENDING        1
00032 #define VLC_THREADS_ERROR          2
00033 #define VLC_THREADS_READY          3
00034 
00035 /*****************************************************************************
00036  * Global mutex for lazy initialization of the threads system
00037  *****************************************************************************/
00038 static volatile unsigned i_initializations = 0;
00039 static volatile int i_status = VLC_THREADS_UNINITIALIZED;
00040 static vlc_object_t *p_root;
00041 
00042 #if defined( PTH_INIT_IN_PTH_H )
00043 #elif defined( ST_INIT_IN_ST_H )
00044 #elif defined( UNDER_CE )
00045 #elif defined( WIN32 )
00046 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00047 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00048     static pthread_mutex_t once_mutex = PTHREAD_MUTEX_INITIALIZER;
00049 #elif defined( HAVE_CTHREADS_H )
00050 #endif
00051 
00052 /*****************************************************************************
00053  * Global variable for named mutexes
00054  *****************************************************************************/
00055 typedef struct vlc_namedmutex_t vlc_namedmutex_t;
00056 struct vlc_namedmutex_t
00057 {
00058     vlc_mutex_t lock;
00059 
00060     char *psz_name;
00061     int i_usage;
00062     vlc_namedmutex_t *p_next;
00063 };
00064 
00065 /*****************************************************************************
00066  * vlc_threads_init: initialize threads system
00067  *****************************************************************************
00068  * This function requires lazy initialization of a global lock in order to
00069  * keep the library really thread-safe. Some architectures don't support this
00070  * and thus do not guarantee the complete reentrancy.
00071  *****************************************************************************/
00072 int __vlc_threads_init( vlc_object_t *p_this )
00073 {
00074     libvlc_t *p_libvlc = (libvlc_t *)p_this;
00075     int i_ret = VLC_SUCCESS;
00076 
00077     /* If we have lazy mutex initialization, use it. Otherwise, we just
00078      * hope nothing wrong happens. */
00079 #if defined( PTH_INIT_IN_PTH_H )
00080 #elif defined( ST_INIT_IN_ST_H )
00081 #elif defined( UNDER_CE )
00082 #elif defined( WIN32 )
00083 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00084 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00085     pthread_mutex_lock( &once_mutex );
00086 #elif defined( HAVE_CTHREADS_H )
00087 #endif
00088 
00089     if( i_status == VLC_THREADS_UNINITIALIZED )
00090     {
00091         i_status = VLC_THREADS_PENDING;
00092 
00093         /* We should be safe now. Do all the initialization stuff we want. */
00094         p_libvlc->b_ready = VLC_FALSE;
00095 
00096 #if defined( PTH_INIT_IN_PTH_H )
00097         i_ret = ( pth_init() == FALSE );
00098 
00099 #elif defined( ST_INIT_IN_ST_H )
00100         i_ret = st_init();
00101 
00102 #elif defined( UNDER_CE )
00103         /* Nothing to initialize */
00104 
00105 #elif defined( WIN32 )
00106         /* Dynamically get the address of SignalObjectAndWait */
00107         if( GetVersion() < 0x80000000 )
00108         {
00109             HINSTANCE hInstLib;
00110 
00111             /* We are running on NT/2K/XP, we can use SignalObjectAndWait */
00112             hInstLib = LoadLibrary( "kernel32" );
00113             if( hInstLib )
00114             {
00115                 p_libvlc->SignalObjectAndWait =
00116                     (SIGNALOBJECTANDWAIT)GetProcAddress( hInstLib,
00117                                                      "SignalObjectAndWait" );
00118             }
00119         }
00120         else
00121         {
00122             p_libvlc->SignalObjectAndWait = NULL;
00123         }
00124 
00125         p_libvlc->b_fast_mutex = 0;
00126         p_libvlc->i_win9x_cv = 0;
00127 
00128 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00129 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00130 #elif defined( HAVE_CTHREADS_H )
00131 #endif
00132 
00133         p_root = vlc_object_create( p_libvlc, VLC_OBJECT_ROOT );
00134         if( p_root == NULL )
00135             i_ret = VLC_ENOMEM;
00136 
00137         if( i_ret )
00138         {
00139             i_status = VLC_THREADS_ERROR;
00140         }
00141         else
00142         {
00143             i_initializations++;
00144             i_status = VLC_THREADS_READY;
00145         }
00146     }
00147     else
00148     {
00149         /* Just increment the initialization count */
00150         i_initializations++;
00151     }
00152 
00153     /* If we have lazy mutex initialization support, unlock the mutex;
00154      * otherwize, do a naive wait loop. */
00155 #if defined( PTH_INIT_IN_PTH_H )
00156     while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
00157 #elif defined( ST_INIT_IN_ST_H )
00158     while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
00159 #elif defined( UNDER_CE )
00160     while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
00161 #elif defined( WIN32 )
00162     while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
00163 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00164     while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
00165 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00166     pthread_mutex_unlock( &once_mutex );
00167 #elif defined( HAVE_CTHREADS_H )
00168     while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
00169 #endif
00170 
00171     if( i_status != VLC_THREADS_READY )
00172     {
00173         return VLC_ETHREAD;
00174     }
00175 
00176     return i_ret;
00177 }
00178 
00179 /*****************************************************************************
00180  * vlc_threads_end: stop threads system
00181  *****************************************************************************
00182  * FIXME: This function is far from being threadsafe.
00183  *****************************************************************************/
00184 int __vlc_threads_end( vlc_object_t *p_this )
00185 {
00186 #if defined( PTH_INIT_IN_PTH_H )
00187 #elif defined( ST_INIT_IN_ST_H )
00188 #elif defined( UNDER_CE )
00189 #elif defined( WIN32 )
00190 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00191 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00192     pthread_mutex_lock( &once_mutex );
00193 #elif defined( HAVE_CTHREADS_H )
00194 #endif
00195 
00196     if( i_initializations == 0 )
00197         return VLC_EGENERIC;
00198 
00199     i_initializations--;
00200     if( i_initializations == 0 )
00201     {
00202         i_status = VLC_THREADS_UNINITIALIZED;
00203         vlc_object_destroy( p_root );
00204     }
00205 
00206 #if defined( PTH_INIT_IN_PTH_H )
00207     if( i_initializations == 0 )
00208     {
00209         return ( pth_kill() == FALSE );
00210     }
00211 
00212 #elif defined( ST_INIT_IN_ST_H )
00213 #elif defined( UNDER_CE )
00214 #elif defined( WIN32 )
00215 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00216 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00217     pthread_mutex_unlock( &once_mutex );
00218 #elif defined( HAVE_CTHREADS_H )
00219 #endif
00220     return VLC_SUCCESS;
00221 }
00222 
00223 /*****************************************************************************
00224  * vlc_mutex_init: initialize a mutex
00225  *****************************************************************************/
00226 int __vlc_mutex_init( vlc_object_t *p_this, vlc_mutex_t *p_mutex )
00227 {
00228     p_mutex->p_this = p_this;
00229 
00230 #if defined( PTH_INIT_IN_PTH_H )
00231     return ( pth_mutex_init( &p_mutex->mutex ) == FALSE );
00232 
00233 #elif defined( ST_INIT_IN_ST_H )
00234     p_mutex->mutex = st_mutex_new();
00235     return ( p_mutex->mutex == NULL ) ? errno : 0;
00236 
00237 #elif defined( UNDER_CE )
00238     InitializeCriticalSection( &p_mutex->csection );
00239     return 0;
00240 
00241 #elif defined( WIN32 )
00242     /* We use mutexes on WinNT/2K/XP because we can use the SignalObjectAndWait
00243      * function and have a 100% correct vlc_cond_wait() implementation.
00244      * As this function is not available on Win9x, we can use the faster
00245      * CriticalSections */
00246     if( p_this->p_libvlc->SignalObjectAndWait &&
00247         !p_this->p_libvlc->b_fast_mutex )
00248     {
00249         /* We are running on NT/2K/XP, we can use SignalObjectAndWait */
00250         p_mutex->mutex = CreateMutex( 0, FALSE, 0 );
00251         return ( p_mutex->mutex != NULL ? 0 : 1 );
00252     }
00253     else
00254     {
00255         p_mutex->mutex = NULL;
00256         InitializeCriticalSection( &p_mutex->csection );
00257         return 0;
00258     }
00259 
00260 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00261     /* check the arguments and whether it's already been initialized */
00262     if( p_mutex == NULL )
00263     {
00264         return B_BAD_VALUE;
00265     }
00266 
00267     if( p_mutex->init == 9999 )
00268     {
00269         return EALREADY;
00270     }
00271 
00272     p_mutex->lock = create_sem( 1, "BeMutex" );
00273     if( p_mutex->lock < B_NO_ERROR )
00274     {
00275         return( -1 );
00276     }
00277 
00278     p_mutex->init = 9999;
00279     return B_OK;
00280 
00281 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00282 #   if defined(DEBUG) && defined(SYS_LINUX)
00283     {
00284         /* Create error-checking mutex to detect problems more easily. */
00285         pthread_mutexattr_t attr;
00286         int                 i_result;
00287 
00288         pthread_mutexattr_init( &attr );
00289         pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_ERRORCHECK_NP );
00290         i_result = pthread_mutex_init( &p_mutex->mutex, &attr );
00291         pthread_mutexattr_destroy( &attr );
00292         return( i_result );
00293     }
00294 #   endif
00295     return pthread_mutex_init( &p_mutex->mutex, NULL );
00296 
00297 #elif defined( HAVE_CTHREADS_H )
00298     mutex_init( p_mutex );
00299     return 0;
00300 
00301 #endif
00302 }
00303 
00304 /*****************************************************************************
00305  * vlc_mutex_destroy: destroy a mutex, inner version
00306  *****************************************************************************/
00307 int __vlc_mutex_destroy( char * psz_file, int i_line, vlc_mutex_t *p_mutex )
00308 {
00309     int i_result;
00310     /* In case of error : */
00311     int i_thread = -1;
00312     const char * psz_error = "";
00313 
00314 #if defined( PTH_INIT_IN_PTH_H )
00315     return 0;
00316 
00317 #elif defined( ST_INIT_IN_ST_H )
00318     i_result = st_mutex_destroy( p_mutex->mutex );
00319 
00320 #elif defined( UNDER_CE )
00321     DeleteCriticalSection( &p_mutex->csection );
00322     return 0;
00323 
00324 #elif defined( WIN32 )
00325     if( p_mutex->mutex )
00326     {
00327         CloseHandle( p_mutex->mutex );
00328     }
00329     else
00330     {
00331         DeleteCriticalSection( &p_mutex->csection );
00332     }
00333     return 0;
00334 
00335 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00336     if( p_mutex->init == 9999 )
00337     {
00338         delete_sem( p_mutex->lock );
00339     }
00340 
00341     p_mutex->init = 0;
00342     return B_OK;
00343 
00344 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00345     i_result = pthread_mutex_destroy( &p_mutex->mutex );
00346     if( i_result )
00347     {
00348         i_thread = (int)pthread_self();
00349         psz_error = strerror(i_result);
00350     }
00351 
00352 #elif defined( HAVE_CTHREADS_H )
00353     return 0;
00354 
00355 #endif
00356 
00357     if( i_result )
00358     {
00359         msg_Err( p_mutex->p_this,
00360                  "thread %d: mutex_destroy failed at %s:%d (%d:%s)",
00361                  i_thread, psz_file, i_line, i_result, psz_error );
00362     }
00363     return i_result;
00364 }
00365 
00366 /*****************************************************************************
00367  * vlc_cond_init: initialize a condition
00368  *****************************************************************************/
00369 int __vlc_cond_init( vlc_object_t *p_this, vlc_cond_t *p_condvar )
00370 {
00371     p_condvar->p_this = p_this;
00372 
00373 #if defined( PTH_INIT_IN_PTH_H )
00374     return ( pth_cond_init( &p_condvar->cond ) == FALSE );
00375 
00376 #elif defined( ST_INIT_IN_ST_H )
00377     p_condvar->cond = st_cond_new();
00378     return ( p_condvar->cond == NULL ) ? errno : 0;
00379 
00380 #elif defined( UNDER_CE )
00381     /* Initialize counter */
00382     p_condvar->i_waiting_threads = 0;
00383 
00384     /* Create an auto-reset event. */
00385     p_condvar->event = CreateEvent( NULL,   /* no security */
00386                                     FALSE,  /* auto-reset event */
00387                                     FALSE,  /* start non-signaled */
00388                                     NULL ); /* unnamed */
00389     return !p_condvar->event;
00390 
00391 #elif defined( WIN32 )
00392     /* Initialize counter */
00393     p_condvar->i_waiting_threads = 0;
00394 
00395     /* Misc init */
00396     p_condvar->i_win9x_cv = p_this->p_libvlc->i_win9x_cv;
00397     p_condvar->SignalObjectAndWait = p_this->p_libvlc->SignalObjectAndWait;
00398 
00399     if( (p_condvar->SignalObjectAndWait && !p_this->p_libvlc->b_fast_mutex)
00400         || p_condvar->i_win9x_cv == 0 )
00401     {
00402         /* Create an auto-reset event. */
00403         p_condvar->event = CreateEvent( NULL,   /* no security */
00404                                         FALSE,  /* auto-reset event */
00405                                         FALSE,  /* start non-signaled */
00406                                         NULL ); /* unnamed */
00407 
00408         p_condvar->semaphore = NULL;
00409         return !p_condvar->event;
00410     }
00411     else
00412     {
00413         p_condvar->semaphore = CreateSemaphore( NULL,       /* no security */
00414                                                 0,          /* initial count */
00415                                                 0x7fffffff, /* max count */
00416                                                 NULL );     /* unnamed */
00417 
00418         if( p_condvar->i_win9x_cv == 1 )
00419             /* Create a manual-reset event initially signaled. */
00420             p_condvar->event = CreateEvent( NULL, TRUE, TRUE, NULL );
00421         else
00422             /* Create a auto-reset event. */
00423             p_condvar->event = CreateEvent( NULL, FALSE, FALSE, NULL );
00424 
00425         InitializeCriticalSection( &p_condvar->csection );
00426 
00427         return !p_condvar->semaphore || !p_condvar->event;
00428     }
00429 
00430 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00431     if( !p_condvar )
00432     {
00433         return B_BAD_VALUE;
00434     }
00435 
00436     if( p_condvar->init == 9999 )
00437     {
00438         return EALREADY;
00439     }
00440 
00441     p_condvar->thread = -1;
00442     p_condvar->init = 9999;
00443     return 0;
00444 
00445 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00446     return pthread_cond_init( &p_condvar->cond, NULL );
00447 
00448 #elif defined( HAVE_CTHREADS_H )
00449     /* condition_init() */
00450     spin_lock_init( &p_condvar->lock );
00451     cthread_queue_init( &p_condvar->queue );
00452     p_condvar->name = 0;
00453     p_condvar->implications = 0;
00454 
00455     return 0;
00456 
00457 #endif
00458 }
00459 
00460 /*****************************************************************************
00461  * vlc_cond_destroy: destroy a condition, inner version
00462  *****************************************************************************/
00463 int __vlc_cond_destroy( char * psz_file, int i_line, vlc_cond_t *p_condvar )
00464 {
00465     int i_result;
00466     /* In case of error : */
00467     int i_thread = -1;
00468     const char * psz_error = "";
00469 
00470 #if defined( PTH_INIT_IN_PTH_H )
00471     return 0;
00472 
00473 #elif defined( ST_INIT_IN_ST_H )
00474     i_result = st_cond_destroy( p_condvar->cond );
00475 
00476 #elif defined( UNDER_CE )
00477     i_result = !CloseHandle( p_condvar->event );
00478 
00479 #elif defined( WIN32 )
00480     if( !p_condvar->semaphore )
00481         i_result = !CloseHandle( p_condvar->event );
00482     else
00483         i_result = !CloseHandle( p_condvar->event )
00484           || !CloseHandle( p_condvar->semaphore );
00485 
00486     if( p_condvar->semaphore != NULL )
00487                 DeleteCriticalSection( &p_condvar->csection );
00488 
00489 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00490     p_condvar->init = 0;
00491     return 0;
00492 
00493 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00494     i_result = pthread_cond_destroy( &p_condvar->cond );
00495     if( i_result )
00496     {
00497         i_thread = (int)pthread_self();
00498         psz_error = strerror(i_result);
00499     }
00500 
00501 #elif defined( HAVE_CTHREADS_H )
00502     return 0;
00503 
00504 #endif
00505 
00506     if( i_result )
00507     {
00508         msg_Err( p_condvar->p_this,
00509                  "thread %d: cond_destroy failed at %s:%d (%d:%s)",
00510                  i_thread, psz_file, i_line, i_result, psz_error );
00511     }
00512     return i_result;
00513 }
00514 
00515 /*****************************************************************************
00516  * vlc_thread_create: create a thread, inner version
00517  *****************************************************************************
00518  * Note that i_priority is only taken into account on platforms supporting
00519  * userland real-time priority threads.
00520  *****************************************************************************/
00521 int __vlc_thread_create( vlc_object_t *p_this, char * psz_file, int i_line,
00522                          char *psz_name, void * ( *func ) ( void * ),
00523                          int i_priority, vlc_bool_t b_wait )
00524 {
00525     int i_ret;
00526     void *p_data = (void *)p_this;
00527 
00528     vlc_mutex_lock( &p_this->object_lock );
00529 
00530 #if defined( PTH_INIT_IN_PTH_H )
00531     p_this->thread_id = pth_spawn( PTH_ATTR_DEFAULT, func, p_data );
00532     i_ret = p_this->thread_id == NULL;
00533 
00534 #elif defined( ST_INIT_IN_ST_H )
00535     p_this->thread_id = st_thread_create( func, p_data, 1, 0 );
00536     i_ret = 0;
00537 
00538 #elif defined( WIN32 ) || defined( UNDER_CE )
00539     {
00540         unsigned threadID;
00541         /* When using the MSVCRT C library you have to use the _beginthreadex
00542          * function instead of CreateThread, otherwise you'll end up with
00543          * memory leaks and the signal functions not working (see Microsoft
00544          * Knowledge Base, article 104641) */
00545         p_this->thread_id =
00546 #if defined( UNDER_CE )
00547                 (HANDLE)CreateThread( NULL, 0, (PTHREAD_START) func,
00548                                       p_data, 0, &threadID );
00549 #else
00550                 (HANDLE)_beginthreadex( NULL, 0, (PTHREAD_START) func,
00551                                         p_data, 0, &threadID );
00552 #endif
00553     }
00554 
00555     if( p_this->thread_id && i_priority )
00556     {
00557         if( !SetThreadPriority(p_this->thread_id, i_priority) )
00558         {
00559             msg_Warn( p_this, "couldn't set a faster priority" );
00560             i_priority = 0;
00561         }
00562     }
00563 
00564     i_ret = ( p_this->thread_id ? 0 : 1 );
00565 
00566 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00567     p_this->thread_id = spawn_thread( (thread_func)func, psz_name,
00568                                       i_priority, p_data );
00569     i_ret = resume_thread( p_this->thread_id );
00570 
00571 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00572     i_ret = pthread_create( &p_this->thread_id, NULL, func, p_data );
00573 
00574 #ifndef SYS_DARWIN
00575     if( config_GetInt( p_this, "rt-priority" ) )
00576 #endif
00577     {
00578         int i_error, i_policy;
00579         struct sched_param param;
00580 
00581         memset( &param, 0, sizeof(struct sched_param) );
00582         if( config_GetType( p_this, "rt-offset" ) )
00583         {
00584             i_priority += config_GetInt( p_this, "rt-offset" );
00585         }
00586         if( i_priority <= 0 )
00587         {
00588             param.sched_priority = (-1) * i_priority;
00589             i_policy = SCHED_OTHER;
00590         }
00591         else
00592         {
00593             param.sched_priority = i_priority;
00594             i_policy = SCHED_RR;
00595         }
00596         if( (i_error = pthread_setschedparam( p_this->thread_id,
00597                                                i_policy, &param )) )
00598         {
00599             msg_Warn( p_this, "couldn't set thread priority (%s:%d): %s",
00600                       psz_file, i_line, strerror(i_error) );
00601             i_priority = 0;
00602         }
00603     }
00604 #ifndef SYS_DARWIN
00605     else
00606     {
00607         i_priority = 0;
00608     }
00609 #endif
00610 
00611 #elif defined( HAVE_CTHREADS_H )
00612     p_this->thread_id = cthread_fork( (cthread_fn_t)func, (any_t)p_data );
00613     i_ret = 0;
00614 
00615 #endif
00616 
00617     if( i_ret == 0 )
00618     {
00619         if( b_wait )
00620         {
00621             msg_Dbg( p_this, "waiting for thread completion" );
00622             vlc_cond_wait( &p_this->object_wait, &p_this->object_lock );
00623         }
00624 
00625         p_this->b_thread = 1;
00626 
00627         msg_Dbg( p_this, "thread %u (%s) created at priority %d (%s:%d)",
00628                  (unsigned int)p_this->thread_id, psz_name, i_priority,
00629                  psz_file, i_line );
00630 
00631         vlc_mutex_unlock( &p_this->object_lock );
00632     }
00633     else
00634     {
00635 #ifdef HAVE_STRERROR
00636         msg_Err( p_this, "%s thread could not be created at %s:%d (%s)",
00637                          psz_name, psz_file, i_line, strerror(i_ret) );
00638 #else
00639         msg_Err( p_this, "%s thread could not be created at %s:%d",
00640                          psz_name, psz_file, i_line );
00641 #endif
00642         vlc_mutex_unlock( &p_this->object_lock );
00643     }
00644 
00645     return i_ret;
00646 }
00647 
00648 /*****************************************************************************
00649  * vlc_thread_set_priority: set the priority of the current thread when we
00650  * couldn't set it in vlc_thread_create (for instance for the main thread)
00651  *****************************************************************************/
00652 int __vlc_thread_set_priority( vlc_object_t *p_this, char * psz_file,
00653                                int i_line, int i_priority )
00654 {
00655 #if defined( PTH_INIT_IN_PTH_H ) || defined( ST_INIT_IN_ST_H )
00656 #elif defined( WIN32 ) || defined( UNDER_CE )
00657     if( !SetThreadPriority(GetCurrentThread(), i_priority) )
00658     {
00659         msg_Warn( p_this, "couldn't set a faster priority" );
00660         return 1;
00661     }
00662 
00663 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00664 #ifndef SYS_DARWIN
00665     if( config_GetInt( p_this, "rt-priority" ) )
00666 #endif
00667     {
00668         int i_error, i_policy;
00669         struct sched_param param;
00670 
00671         memset( &param, 0, sizeof(struct sched_param) );
00672         if( config_GetType( p_this, "rt-offset" ) )
00673         {
00674             i_priority += config_GetInt( p_this, "rt-offset" );
00675         }
00676         if( i_priority <= 0 )
00677         {
00678             param.sched_priority = (-1) * i_priority;
00679             i_policy = SCHED_OTHER;
00680         }
00681         else
00682         {
00683             param.sched_priority = i_priority;
00684             i_policy = SCHED_RR;
00685         }
00686         if( !p_this->thread_id )
00687             p_this->thread_id = pthread_self();
00688         if( (i_error = pthread_setschedparam( p_this->thread_id,
00689                                                i_policy, &param )) )
00690         {
00691             msg_Warn( p_this, "couldn't set thread priority (%s:%d): %s",
00692                       psz_file, i_line, strerror(i_error) );
00693             i_priority = 0;
00694         }
00695     }
00696 #endif
00697 
00698     return 0;
00699 }
00700 
00701 /*****************************************************************************
00702  * vlc_thread_ready: tell the parent thread we were successfully spawned
00703  *****************************************************************************/
00704 void __vlc_thread_ready( vlc_object_t *p_this )
00705 {
00706     vlc_mutex_lock( &p_this->object_lock );
00707     vlc_cond_signal( &p_this->object_wait );
00708     vlc_mutex_unlock( &p_this->object_lock );
00709 }
00710 
00711 /*****************************************************************************
00712  * vlc_thread_join: wait until a thread exits, inner version
00713  *****************************************************************************/
00714 void __vlc_thread_join( vlc_object_t *p_this, char * psz_file, int i_line )
00715 {
00716     int i_ret = 0;
00717 
00718 #if defined( PTH_INIT_IN_PTH_H )
00719     i_ret = ( pth_join( p_this->thread_id, NULL ) == FALSE );
00720 
00721 #elif defined( ST_INIT_IN_ST_H )
00722     i_ret = st_thread_join( p_this->thread_id, NULL );
00723 
00724 #elif defined( UNDER_CE ) || defined( WIN32 )
00725     HMODULE hmodule;
00726     BOOL (WINAPI *OurGetThreadTimes)( HANDLE, FILETIME*, FILETIME*,
00727                                       FILETIME*, FILETIME* );
00728     FILETIME create_ft, exit_ft, kernel_ft, user_ft;
00729     int64_t real_time, kernel_time, user_time;
00730 
00731     WaitForSingleObject( p_this->thread_id, INFINITE );
00732 
00733 #if defined( UNDER_CE )
00734     hmodule = GetModuleHandle( _T("COREDLL") );
00735 #else
00736     hmodule = GetModuleHandle( _T("KERNEL32") );
00737 #endif
00738     OurGetThreadTimes = (BOOL (WINAPI*)( HANDLE, FILETIME*, FILETIME*,
00739                                          FILETIME*, FILETIME* ))
00740         GetProcAddress( hmodule, _T("GetThreadTimes") );
00741 
00742     if( OurGetThreadTimes &&
00743         OurGetThreadTimes( p_this->thread_id,
00744                            &create_ft, &exit_ft, &kernel_ft, &user_ft ) )
00745     {
00746         real_time =
00747           ((((int64_t)exit_ft.dwHighDateTime)<<32)| exit_ft.dwLowDateTime) -
00748           ((((int64_t)create_ft.dwHighDateTime)<<32)| create_ft.dwLowDateTime);
00749         real_time /= 10;
00750 
00751         kernel_time =
00752           ((((int64_t)kernel_ft.dwHighDateTime)<<32)|
00753            kernel_ft.dwLowDateTime) / 10;
00754 
00755         user_time =
00756           ((((int64_t)user_ft.dwHighDateTime)<<32)|
00757            user_ft.dwLowDateTime) / 10;
00758 
00759         msg_Dbg( p_this, "thread times: "
00760                  "real "I64Fd"m%fs, kernel "I64Fd"m%fs, user "I64Fd"m%fs",
00761                  real_time/60/1000000,
00762                  (double)((real_time%(60*1000000))/1000000.0),
00763                  kernel_time/60/1000000,
00764                  (double)((kernel_time%(60*1000000))/1000000.0),
00765                  user_time/60/1000000,
00766                  (double)((user_time%(60*1000000))/1000000.0) );
00767     }
00768     CloseHandle( p_this->thread_id );
00769 
00770 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00771     int32_t exit_value;
00772     wait_for_thread( p_this->thread_id, &exit_value );
00773 
00774 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00775     i_ret = pthread_join( p_this->thread_id, NULL );
00776 
00777 #elif defined( HAVE_CTHREADS_H )
00778     cthread_join( p_this->thread_id );
00779     i_ret = 1;
00780 
00781 #endif
00782 
00783     if( i_ret )
00784     {
00785 #ifdef HAVE_STRERROR
00786         msg_Err( p_this, "thread_join(%u) failed at %s:%d (%s)",
00787                          (unsigned int)p_this->thread_id, psz_file, i_line,
00788                          strerror(i_ret) );
00789 #else
00790         msg_Err( p_this, "thread_join(%u) failed at %s:%d",
00791                          (unsigned int)p_this->thread_id, psz_file, i_line );
00792 #endif
00793     }
00794     else
00795     {
00796         msg_Dbg( p_this, "thread %u joined (%s:%d)",
00797                          (unsigned int)p_this->thread_id, psz_file, i_line );
00798     }
00799 
00800     p_this->b_thread = 0;
00801 }
00802 

Generated on Tue Dec 20 10:15:00 2005 for vlc-0.8.4a by  doxygen 1.4.2