X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmisc%2Fthreads.c;h=3b2072c39da1a202bdb5e9bcc356ae4a021ac676;hb=c73cac4ec8416f946774be2104cada36550b44e5;hp=9ff9b4ecfba6e34d628512fce9587e01176b973f;hpb=1b7ce2697e98a3fcff4f78d1610f7f0268cd47c1;p=vlc diff --git a/src/misc/threads.c b/src/misc/threads.c index 9ff9b4ecfb..3b2072c39d 100644 --- a/src/misc/threads.c +++ b/src/misc/threads.c @@ -1,8 +1,8 @@ /***************************************************************************** * threads.c : threads implementation for the VideoLAN client ***************************************************************************** - * Copyright (C) 1999, 2000, 2001, 2002 VideoLAN - * $Id: threads.c,v 1.27 2002/12/06 10:10:40 sam Exp $ + * Copyright (C) 1999-2004 VideoLAN + * $Id: threads.c,v 1.46 2004/02/20 17:20:01 massiot Exp $ * * Authors: Jean-Marc Dressler * Samuel Hocevar @@ -41,10 +41,10 @@ static volatile int i_initializations = 0; #elif defined( ST_INIT_IN_ST_H ) #elif defined( UNDER_CE ) #elif defined( WIN32 ) +#elif defined( HAVE_KERNEL_SCHEDULER_H ) #elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) static pthread_mutex_t once_mutex = PTHREAD_MUTEX_INITIALIZER; #elif defined( HAVE_CTHREADS_H ) -#elif defined( HAVE_KERNEL_SCHEDULER_H ) #endif /***************************************************************************** @@ -81,10 +81,10 @@ int __vlc_threads_init( vlc_object_t *p_this ) #elif defined( UNDER_CE ) #elif defined( WIN32 ) HINSTANCE hInstLib; +#elif defined( HAVE_KERNEL_SCHEDULER_H ) #elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) pthread_mutex_lock( &once_mutex ); #elif defined( HAVE_CTHREADS_H ) -#elif defined( HAVE_KERNEL_SCHEDULER_H ) #endif if( i_status == VLC_THREADS_UNINITIALIZED ) @@ -92,11 +92,10 @@ int __vlc_threads_init( vlc_object_t *p_this ) 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(); + i_ret = ( pth_init() == FALSE ); #elif defined( ST_INIT_IN_ST_H ) i_ret = st_init(); @@ -125,11 +124,13 @@ int __vlc_threads_init( vlc_object_t *p_this ) p_libvlc->b_fast_mutex = 0; p_libvlc->i_win9x_cv = 0; +#elif defined( HAVE_KERNEL_SCHEDULER_H ) #elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) #elif defined( HAVE_CTHREADS_H ) -#elif defined( HAVE_KERNEL_SCHEDULER_H ) #endif + vlc_object_create( p_libvlc, VLC_OBJECT_ROOT ); + if( i_ret ) { i_status = VLC_THREADS_ERROR; @@ -156,12 +157,12 @@ int __vlc_threads_init( vlc_object_t *p_this ) while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP ); #elif defined( WIN32 ) while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP ); +#elif defined( HAVE_KERNEL_SCHEDULER_H ) + while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP ); #elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) pthread_mutex_unlock( &once_mutex ); #elif defined( HAVE_CTHREADS_H ) while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP ); -#elif defined( HAVE_KERNEL_SCHEDULER_H ) - while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP ); #endif if( i_status != VLC_THREADS_READY ) @@ -184,7 +185,7 @@ int __vlc_threads_end( vlc_object_t *p_this ) i_initializations--; if( i_initializations == 0 ) { - return pth_kill(); + return ( pth_kill() == FALSE ); } #elif defined( ST_INIT_IN_ST_H ) @@ -196,6 +197,9 @@ int __vlc_threads_end( vlc_object_t *p_this ) #elif defined( WIN32 ) i_initializations--; +#elif defined( HAVE_KERNEL_SCHEDULER_H ) + i_initializations--; + #elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) pthread_mutex_lock( &once_mutex ); i_initializations--; @@ -204,51 +208,10 @@ int __vlc_threads_end( vlc_object_t *p_this ) #elif defined( HAVE_CTHREADS_H ) i_initializations--; -#elif defined( HAVE_KERNEL_SCHEDULER_H ) - i_initializations--; - #endif return VLC_SUCCESS; } -/***************************************************************************** - * Prototype for GPROF wrapper - *****************************************************************************/ -#ifdef GPROF -/* Wrapper function for profiling */ -static void * vlc_thread_wrapper ( void *p_wrapper ); - -# if defined( WIN32 ) && !defined( UNDER_CE ) - -# 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 && !UNDER_CE */ - -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 *****************************************************************************/ @@ -257,7 +220,7 @@ int __vlc_mutex_init( vlc_object_t *p_this, vlc_mutex_t *p_mutex ) p_mutex->p_this = p_this; #if defined( PTH_INIT_IN_PTH_H ) - return pth_mutex_init( &p_mutex->mutex ); + return ( pth_mutex_init( &p_mutex->mutex ) == FALSE ); #elif defined( ST_INIT_IN_ST_H ) p_mutex->mutex = st_mutex_new(); @@ -286,26 +249,6 @@ int __vlc_mutex_init( vlc_object_t *p_this, vlc_mutex_t *p_mutex ) return 0; } -#elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) -# if defined(DEBUG) && defined(SYS_LINUX) - { - /* Create error-checking mutex to detect problems more easily. */ - pthread_mutexattr_t attr; - int i_result; - - pthread_mutexattr_init( &attr ); - pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_ERRORCHECK_NP ); - i_result = pthread_mutex_init( &p_mutex->mutex, &attr ); - pthread_mutexattr_destroy( &attr ); - return( i_result ); - } -# endif - return pthread_mutex_init( &p_mutex->mutex, NULL ); - -#elif defined( HAVE_CTHREADS_H ) - mutex_init( p_mutex ); - return 0; - #elif defined( HAVE_KERNEL_SCHEDULER_H ) /* check the arguments and whether it's already been initialized */ if( p_mutex == NULL ) @@ -327,6 +270,26 @@ int __vlc_mutex_init( vlc_object_t *p_this, vlc_mutex_t *p_mutex ) p_mutex->init = 9999; return B_OK; +#elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) +# if defined(DEBUG) && defined(SYS_LINUX) + { + /* Create error-checking mutex to detect problems more easily. */ + pthread_mutexattr_t attr; + int i_result; + + pthread_mutexattr_init( &attr ); + pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_ERRORCHECK_NP ); + i_result = pthread_mutex_init( &p_mutex->mutex, &attr ); + pthread_mutexattr_destroy( &attr ); + return( i_result ); + } +# endif + return pthread_mutex_init( &p_mutex->mutex, NULL ); + +#elif defined( HAVE_CTHREADS_H ) + mutex_init( p_mutex ); + return 0; + #endif } @@ -361,6 +324,15 @@ int __vlc_mutex_destroy( char * psz_file, int i_line, vlc_mutex_t *p_mutex ) } return 0; +#elif defined( HAVE_KERNEL_SCHEDULER_H ) + if( p_mutex->init == 9999 ) + { + delete_sem( p_mutex->lock ); + } + + p_mutex->init = 0; + return B_OK; + #elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) i_result = pthread_mutex_destroy( &p_mutex->mutex ); if ( i_result ) @@ -372,14 +344,6 @@ int __vlc_mutex_destroy( char * psz_file, int i_line, vlc_mutex_t *p_mutex ) #elif defined( HAVE_CTHREADS_H ) return 0; -#elif defined( HAVE_KERNEL_SCHEDULER_H ) - if( p_mutex->init == 9999 ) - { - delete_sem( p_mutex->lock ); - } - - p_mutex->init = 0; - return B_OK; #endif if( i_result ) @@ -399,7 +363,7 @@ int __vlc_cond_init( vlc_object_t *p_this, vlc_cond_t *p_condvar ) p_condvar->p_this = p_this; #if defined( PTH_INIT_IN_PTH_H ) - return pth_cond_init( &p_condvar->cond ); + return ( pth_cond_init( &p_condvar->cond ) == FALSE ); #elif defined( ST_INIT_IN_ST_H ) p_condvar->cond = st_cond_new(); @@ -455,18 +419,6 @@ int __vlc_cond_init( vlc_object_t *p_this, vlc_cond_t *p_condvar ) return !p_condvar->semaphore || !p_condvar->event; } -#elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) - return pthread_cond_init( &p_condvar->cond, NULL ); - -#elif defined( HAVE_CTHREADS_H ) - /* condition_init() */ - spin_lock_init( &p_condvar->lock ); - cthread_queue_init( &p_condvar->queue ); - p_condvar->name = 0; - p_condvar->implications = 0; - - return 0; - #elif defined( HAVE_KERNEL_SCHEDULER_H ) if( !p_condvar ) { @@ -481,6 +433,19 @@ int __vlc_cond_init( vlc_object_t *p_this, vlc_cond_t *p_condvar ) p_condvar->thread = -1; p_condvar->init = 9999; return 0; + +#elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) + return pthread_cond_init( &p_condvar->cond, NULL ); + +#elif defined( HAVE_CTHREADS_H ) + /* condition_init() */ + spin_lock_init( &p_condvar->lock ); + cthread_queue_init( &p_condvar->queue ); + p_condvar->name = 0; + p_condvar->implications = 0; + + return 0; + #endif } @@ -510,6 +475,10 @@ int __vlc_cond_destroy( char * psz_file, int i_line, vlc_cond_t *p_condvar ) i_result = !CloseHandle( p_condvar->event ) || !CloseHandle( p_condvar->semaphore ); +#elif defined( HAVE_KERNEL_SCHEDULER_H ) + p_condvar->init = 0; + return 0; + #elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) i_result = pthread_cond_destroy( &p_condvar->cond ); if ( i_result ) @@ -521,9 +490,6 @@ int __vlc_cond_destroy( char * psz_file, int i_line, vlc_cond_t *p_condvar ) #elif defined( HAVE_CTHREADS_H ) return 0; -#elif defined( HAVE_KERNEL_SCHEDULER_H ) - p_condvar->init = 0; - return 0; #endif if( i_result ) @@ -546,32 +512,16 @@ int __vlc_thread_create( vlc_object_t *p_this, char * psz_file, int i_line, int i_priority, vlc_bool_t b_wait ) { int i_ret; + void *p_data = (void *)p_this; vlc_mutex_lock( &p_this->object_lock ); -#ifdef GPROF - wrapper_t wrapper; - - /* Initialize the wrapper structure */ - wrapper.func = func; - wrapper.p_data = (void *)p_this; - getitimer( ITIMER_PROF, &wrapper.itimer ); - vlc_mutex_init( p_this, &wrapper.lock ); - vlc_cond_init( p_this, &wrapper.wait ); - vlc_mutex_lock( &wrapper.lock ); - - /* Alter user-passed data so that we call the wrapper instead - * of the real function */ - p_data = &wrapper; - func = vlc_thread_wrapper; -#endif - #if defined( PTH_INIT_IN_PTH_H ) - p_this->thread_id = pth_spawn( PTH_ATTR_DEFAULT, func, (void *)p_this ); - i_ret = 0; + p_this->thread_id = pth_spawn( PTH_ATTR_DEFAULT, func, p_data ); + i_ret = p_this->thread_id == NULL; #elif defined( ST_INIT_IN_ST_H ) - p_this->thread_id = st_thread_create( func, (void *)p_this, 1, 0 ); + p_this->thread_id = st_thread_create( func, p_data, 1, 0 ); i_ret = 0; #elif defined( WIN32 ) || defined( UNDER_CE ) @@ -584,10 +534,10 @@ int __vlc_thread_create( vlc_object_t *p_this, char * psz_file, int i_line, p_this->thread_id = #if defined( UNDER_CE ) (HANDLE)CreateThread( NULL, 0, (PTHREAD_START) func, - (void *)p_this, 0, &threadID ); + p_data, 0, &threadID ); #else (HANDLE)_beginthreadex( NULL, 0, (PTHREAD_START) func, - (void *)p_this, 0, &threadID ); + p_data, 0, &threadID ); #endif } @@ -602,41 +552,52 @@ int __vlc_thread_create( vlc_object_t *p_this, char * psz_file, int i_line, i_ret = ( p_this->thread_id ? 0 : 1 ); +#elif defined( HAVE_KERNEL_SCHEDULER_H ) + p_this->thread_id = spawn_thread( (thread_func)func, psz_name, + i_priority, p_data ); + i_ret = resume_thread( p_this->thread_id ); + #elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) - i_ret = pthread_create( &p_this->thread_id, NULL, func, (void *)p_this ); + i_ret = pthread_create( &p_this->thread_id, NULL, func, p_data ); - if ( i_priority ) + if ( i_priority +#ifndef SYS_DARWIN + && config_GetInt( p_this, "rt-priority" ) +#endif + ) { + int i_error, i_policy; struct sched_param param; + memset( ¶m, 0, sizeof(struct sched_param) ); - param.sched_priority = i_priority; - if ( pthread_setschedparam( p_this->thread_id, SCHED_RR, ¶m ) ) + i_priority += config_GetInt( p_this, "rt-offset" ); + if ( i_priority < 0 ) + { + param.sched_priority = (-1) * i_priority; + i_policy = SCHED_OTHER; + } + else + { + param.sched_priority = i_priority; + i_policy = SCHED_RR; + } + if ( (i_error = pthread_setschedparam( p_this->thread_id, + i_policy, ¶m )) ) { - msg_Warn( p_this, "couldn't go to real-time priority" ); + msg_Warn( p_this, "couldn't set thread priority (%s:%d): %s", + psz_file, i_line, strerror(i_error) ); i_priority = 0; } } + else + { + i_priority = 0; + } #elif defined( HAVE_CTHREADS_H ) - p_this->thread_id = cthread_fork( (cthread_fn_t)func, (any_t)p_this ); + p_this->thread_id = cthread_fork( (cthread_fn_t)func, (any_t)p_data ); i_ret = 0; -#elif defined( HAVE_KERNEL_SCHEDULER_H ) - p_this->thread_id = spawn_thread( (thread_func)func, psz_name, - B_NORMAL_PRIORITY, (void *)p_this ); - i_ret = resume_thread( p_this->thread_id ); - -#endif - -#ifdef GPROF - if( i_ret == 0 ) - { - vlc_cond_wait( &wrapper.wait, &wrapper.lock ); - } - - vlc_mutex_unlock( &wrapper.lock ); - vlc_mutex_destroy( &wrapper.lock ); - vlc_cond_destroy( &wrapper.wait ); #endif if( i_ret == 0 ) @@ -650,7 +611,7 @@ int __vlc_thread_create( vlc_object_t *p_this, char * psz_file, int i_line, p_this->b_thread = 1; msg_Dbg( p_this, "thread %d (%s) created at priority %d (%s:%d)", - p_this->thread_id, psz_name, i_priority, + (int)p_this->thread_id, psz_name, i_priority, psz_file, i_line ); vlc_mutex_unlock( &p_this->object_lock ); @@ -670,6 +631,56 @@ int __vlc_thread_create( vlc_object_t *p_this, char * psz_file, int i_line, return i_ret; } +/***************************************************************************** + * vlc_thread_set_priority: set the priority of the current thread when we + * couldn't set it in vlc_thread_create (for instance for the main thread) + *****************************************************************************/ +int __vlc_thread_set_priority( vlc_object_t *p_this, char * psz_file, + int i_line, int i_priority ) +{ +#if defined( PTH_INIT_IN_PTH_H ) || defined( ST_INIT_IN_ST_H ) +#elif defined( WIN32 ) || defined( UNDER_CE ) + if ( !SetThreadPriority(GetCurrentThread(), i_priority) ) + { + msg_Warn( p_this, "couldn't set a faster priority" ); + return 1; + } + +#elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) + if ( i_priority +#ifndef SYS_DARWIN + && config_GetInt( p_this, "rt-priority" ) +#endif + ) + { + int i_error, i_policy; + struct sched_param param; + + memset( ¶m, 0, sizeof(struct sched_param) ); + i_priority += config_GetInt( p_this, "rt-offset" ); + if ( i_priority < 0 ) + { + param.sched_priority = (-1) * i_priority; + i_policy = SCHED_OTHER; + } + else + { + param.sched_priority = i_priority; + i_policy = SCHED_RR; + } + if ( (i_error = pthread_setschedparam( p_this->thread_id, + i_policy, ¶m )) ) + { + msg_Warn( p_this, "couldn't set thread priority (%s:%d): %s", + psz_file, i_line, strerror(i_error) ); + i_priority = 0; + } + } +#endif + + return 0; +} + /***************************************************************************** * vlc_thread_ready: tell the parent thread we were successfully spawned *****************************************************************************/ @@ -688,7 +699,7 @@ void __vlc_thread_join( vlc_object_t *p_this, char * psz_file, int i_line ) int i_ret = 0; #if defined( PTH_INIT_IN_PTH_H ) - i_ret = pth_join( p_this->thread_id, NULL ); + i_ret = ( pth_join( p_this->thread_id, NULL ) == FALSE ); #elif defined( ST_INIT_IN_ST_H ) i_ret = st_thread_join( p_this->thread_id, NULL ); @@ -699,6 +710,10 @@ void __vlc_thread_join( vlc_object_t *p_this, char * psz_file, int i_line ) #elif defined( WIN32 ) WaitForSingleObject( p_this->thread_id, INFINITE ); +#elif defined( HAVE_KERNEL_SCHEDULER_H ) + int32_t exit_value; + wait_for_thread( p_this->thread_id, &exit_value ); + #elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) i_ret = pthread_join( p_this->thread_id, NULL ); @@ -706,50 +721,25 @@ void __vlc_thread_join( vlc_object_t *p_this, char * psz_file, int i_line ) cthread_join( p_this->thread_id ); i_ret = 1; -#elif defined( HAVE_KERNEL_SCHEDULER_H ) - int32 exit_value; - wait_for_thread( p_this->thread_id, &exit_value ); - #endif if( i_ret ) { #ifdef HAVE_STRERROR msg_Err( p_this, "thread_join(%d) failed at %s:%d (%s)", - p_this->thread_id, psz_file, i_line, strerror(i_ret) ); + (int)p_this->thread_id, psz_file, i_line, + strerror(i_ret) ); #else msg_Err( p_this, "thread_join(%d) failed at %s:%d", - p_this->thread_id, psz_file, i_line ); + (int)p_this->thread_id, psz_file, i_line ); #endif } else { msg_Dbg( p_this, "thread %d joined (%s:%d)", - p_this->thread_id, psz_file, i_line ); + (int)p_this->thread_id, psz_file, i_line ); } p_this->b_thread = 0; } -/***************************************************************************** - * vlc_thread_wrapper: wrapper around thread functions used when profiling. - *****************************************************************************/ -#ifdef GPROF -static void *vlc_thread_wrapper( void *p_wrapper ) -{ - /* Put user data in thread-local variables */ - void * p_data = ((wrapper_t*)p_wrapper)->p_data; - vlc_thread_func_t func = ((wrapper_t*)p_wrapper)->func; - - /* Set the profile timer value */ - setitimer( ITIMER_PROF, &((wrapper_t*)p_wrapper)->itimer, NULL ); - - /* Tell the calling thread that we don't need its data anymore */ - vlc_mutex_lock( &((wrapper_t*)p_wrapper)->lock ); - vlc_cond_signal( &((wrapper_t*)p_wrapper)->wait ); - vlc_mutex_unlock( &((wrapper_t*)p_wrapper)->lock ); - - /* Call the real function */ - return func( p_data ); -} -#endif