X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=include%2Fvlc_threads_funcs.h;h=5d0c74ca5040fbcc2c08ce034285d56609b61106;hb=1359fbd1013bb48528d54f8674d3feb2acfbdd45;hp=9398598679ef3de2b25ccda6519f1966ac6b558e;hpb=649f40ae919d7f0a7ac55d5780d82eff7788c4b0;p=vlc diff --git a/include/vlc_threads_funcs.h b/include/vlc_threads_funcs.h index 9398598679..5d0c74ca50 100644 --- a/include/vlc_threads_funcs.h +++ b/include/vlc_threads_funcs.h @@ -45,8 +45,6 @@ VLC_EXPORT( int, __vlc_thread_set_priority, ( vlc_object_t *, const char *, int VLC_EXPORT( void, __vlc_thread_ready, ( vlc_object_t * ) ); VLC_EXPORT( void, __vlc_thread_join, ( vlc_object_t *, const char *, int ) ); -#include - /***************************************************************************** * vlc_threads_init: initialize threads system *****************************************************************************/ @@ -83,7 +81,6 @@ static inline int __vlc_mutex_lock( const char * psz_file, int i_line, int i_result; /* In case of error : */ unsigned long int i_thread = 0; - const char * psz_error = ""; #if defined( PTH_INIT_IN_PTH_H ) i_result = ( pth_mutex_acquire( &p_mutex->mutex, FALSE, NULL ) == FALSE ); @@ -128,7 +125,7 @@ static inline int __vlc_mutex_lock( const char * psz_file, int i_line, if ( i_result ) { i_thread = CAST_PTHREAD_TO_INT(pthread_self()); - psz_error = strerror(i_result); + errno = i_result; } #elif defined( HAVE_CTHREADS_H ) @@ -140,8 +137,8 @@ static inline int __vlc_mutex_lock( const char * psz_file, int i_line, if( i_result ) { msg_Err( p_mutex->p_this, - "thread %li: mutex_lock failed at %s:%d (%d:%s)", - i_thread, psz_file, i_line, i_result, psz_error ); + "thread %li: mutex_lock failed at %s:%d (%d:%m)", + i_thread, psz_file, i_line, i_result ); } return i_result; } @@ -162,7 +159,6 @@ static inline int __vlc_mutex_unlock( const char * psz_file, int i_line, int i_result; /* In case of error : */ unsigned long int i_thread = 0; - const char * psz_error = ""; #if defined( PTH_INIT_IN_PTH_H ) i_result = ( pth_mutex_release( &p_mutex->mutex ) == FALSE ); @@ -205,7 +201,7 @@ static inline int __vlc_mutex_unlock( const char * psz_file, int i_line, if ( i_result ) { i_thread = CAST_PTHREAD_TO_INT(pthread_self()); - psz_error = strerror(i_result); + errno = i_result; } #elif defined( HAVE_CTHREADS_H ) @@ -217,8 +213,8 @@ static inline int __vlc_mutex_unlock( const char * psz_file, int i_line, if( i_result ) { msg_Err( p_mutex->p_this, - "thread %li: mutex_unlock failed at %s:%d (%d:%s)", - i_thread, psz_file, i_line, i_result, psz_error ); + "thread %li: mutex_unlock failed at %s:%d (%d:%m)", + i_thread, psz_file, i_line, i_result ); } return i_result; @@ -248,7 +244,6 @@ static inline int __vlc_cond_signal( const char * psz_file, int i_line, int i_result; /* In case of error : */ unsigned long int i_thread = 0; - const char * psz_error = ""; #if defined( PTH_INIT_IN_PTH_H ) i_result = ( pth_cond_notify( &p_condvar->cond, FALSE ) == FALSE ); @@ -266,6 +261,11 @@ static inline int __vlc_cond_signal( const char * psz_file, int i_line, * by a mutex. This will prevent another thread from stealing the signal */ if( !p_condvar->semaphore ) { + /* + ** PulseEvent() only works if none of the waiting threads is suspended. + ** this is particularily problematic under a debug session. + ** as documented in http://support.microsoft.com/kb/q173260/ + */ PulseEvent( p_condvar->event ); } else if( p_condvar->i_win9x_cv == 1 ) @@ -343,7 +343,7 @@ static inline int __vlc_cond_signal( const char * psz_file, int i_line, if ( i_result ) { i_thread = CAST_PTHREAD_TO_INT(pthread_self()); - psz_error = strerror(i_result); + errno = i_result; } #elif defined( HAVE_CTHREADS_H ) @@ -359,8 +359,8 @@ static inline int __vlc_cond_signal( const char * psz_file, int i_line, if( i_result ) { msg_Err( p_condvar->p_this, - "thread %li: cond_signal failed at %s:%d (%d:%s)", - i_thread, psz_file, i_line, i_result, psz_error ); + "thread %li: cond_signal failed at %s:%d (%d:%m)", + i_thread, psz_file, i_line, i_result ); } return i_result; @@ -378,7 +378,6 @@ static inline int __vlc_cond_wait( const char * psz_file, int i_line, int i_result; /* In case of error : */ unsigned long int i_thread = 0; - const char * psz_error = ""; #if defined( PTH_INIT_IN_PTH_H ) i_result = ( pth_cond_await( &p_condvar->cond, &p_mutex->mutex, NULL ) @@ -505,24 +504,21 @@ static inline int __vlc_cond_wait( const char * psz_file, int i_line, # ifdef DEBUG /* In debug mode, timeout */ - struct timespec timeout; - -# if defined (_POSIX_CLOCK_MONOTONIC) && (_POSIX_CLOCK_MONOTONIC >= 0) - if( clock_gettime( CLOCK_MONOTONIC, &timeout ) ) -# endif - clock_gettime( CLOCK_REALTIME, &timeout ); - - timeout.tv_sec += THREAD_COND_TIMEOUT; + struct timespec timeout = { + (mdate() / 1000000) + THREAD_COND_TIMEOUT, + 0 /* 1Hz precision is sufficient here :-) */ + }; i_result = pthread_cond_timedwait( &p_condvar->cond, &p_mutex->mutex, &timeout ); if( i_result == ETIMEDOUT ) { + errno = ETIMEDOUT; msg_Dbg( p_condvar->p_this, "thread %li: possible condition deadlock " - "at %s:%d (%s)", CAST_PTHREAD_TO_INT(pthread_self()), - psz_file, i_line, strerror(i_result) ); + "at %s:%d (%m)", CAST_PTHREAD_TO_INT(pthread_self()), + psz_file, i_line ); i_result = pthread_cond_wait( &p_condvar->cond, &p_mutex->mutex ); } @@ -534,7 +530,7 @@ static inline int __vlc_cond_wait( const char * psz_file, int i_line, if ( i_result ) { i_thread = CAST_PTHREAD_TO_INT(pthread_self()); - psz_error = strerror(i_result); + errno = i_result; } #elif defined( HAVE_CTHREADS_H ) @@ -546,8 +542,8 @@ static inline int __vlc_cond_wait( const char * psz_file, int i_line, if( i_result ) { msg_Err( p_condvar->p_this, - "thread %li: cond_wait failed at %s:%d (%d:%s)", - i_thread, psz_file, i_line, i_result, psz_error ); + "thread %li: cond_wait failed at %s:%d (%d:%m)", + i_thread, psz_file, i_line, i_result ); } return i_result; @@ -556,6 +552,8 @@ static inline int __vlc_cond_wait( const char * psz_file, int i_line, /***************************************************************************** * vlc_cond_timedwait: wait until condition completion or expiration + ***************************************************************************** + * Returns 0 if object signaled, an error code in case of timeout or error. *****************************************************************************/ #define vlc_cond_timedwait( P_COND, P_MUTEX, DEADLINE ) \ __vlc_cond_timedwait( __FILE__, __LINE__, P_COND, P_MUTEX, DEADLINE ) @@ -567,16 +565,117 @@ static inline int __vlc_cond_timedwait( const char * psz_file, int i_line, { int i_res; unsigned long int i_thread = 0; - const char * psz_error = ""; #if defined( PTH_INIT_IN_PTH_H ) # error Unimplemented #elif defined( ST_INIT_IN_ST_H ) # error Unimplemented #elif defined( UNDER_CE ) -# error Unimplemented + mtime_t delay_ms = (deadline - mdate())/1000; + + DWORD result; + if( delay_ms < 0 ) + delay_ms = 0; + + p_condvar->i_waiting_threads++; + LeaveCriticalSection( &p_mutex->csection ); + result = WaitForSingleObject( p_condvar->event, delay_ms ); + p_condvar->i_waiting_threads--; + + /* Reacquire the mutex before returning. */ + vlc_mutex_lock( p_mutex ); + + i_res = (int)result; + #elif defined( WIN32 ) -# error Unimplemented FIXME FIXME + DWORD result; + + mtime_t delay_ms = (deadline - mdate())/1000; + if( delay_ms < 0 ) + delay_ms = 0; + + if( !p_condvar->semaphore ) + { + /* Increase our wait count */ + p_condvar->i_waiting_threads++; + + if( p_mutex->mutex ) + { + /* It is only possible to atomically release the mutex and + * initiate the waiting on WinNT/2K/XP. Win9x doesn't have + * SignalObjectAndWait(). */ + result = p_condvar->SignalObjectAndWait( p_mutex->mutex, + p_condvar->event, + delay_ms, FALSE ); + } + else + { + LeaveCriticalSection( &p_mutex->csection ); + result = WaitForSingleObject( p_condvar->event, delay_ms ); + } + + p_condvar->i_waiting_threads--; + } + else if( p_condvar->i_win9x_cv == 1 ) + { + int i_waiting_threads; + + /* Wait for the gate to be open */ + result = WaitForSingleObject( p_condvar->event, delay_ms ); + + /* Increase our wait count */ + p_condvar->i_waiting_threads++; + + LeaveCriticalSection( &p_mutex->csection ); + if( !result ) + { + /* recaculate remaining delay */ + delay_ms = (deadline - mdate())/1000; + if( delay_ms < 0 ) + delay_ms = 0; + + result = WaitForSingleObject( p_condvar->semaphore, delay_ms ); + } + + /* Decrement and test must be atomic */ + EnterCriticalSection( &p_condvar->csection ); + + /* Decrease our wait count */ + i_waiting_threads = --p_condvar->i_waiting_threads; + + LeaveCriticalSection( &p_condvar->csection ); + + /* Reopen the gate if we were the last waiting thread */ + if( !i_waiting_threads ) + SetEvent( p_condvar->event ); + } + else + { + int i_waiting_threads; + + /* Increase our wait count */ + p_condvar->i_waiting_threads++; + + LeaveCriticalSection( &p_mutex->csection ); + result = WaitForSingleObject( p_condvar->semaphore, delay_ms ); + + /* Decrement and test must be atomic */ + EnterCriticalSection( &p_condvar->csection ); + + /* Decrease our wait count */ + i_waiting_threads = --p_condvar->i_waiting_threads; + + LeaveCriticalSection( &p_condvar->csection ); + + /* Signal that the last waiting thread just went through */ + if( !i_waiting_threads ) + SetEvent( p_condvar->event ); + } + + /* Reacquire the mutex before returning. */ + vlc_mutex_lock( p_mutex ); + + i_res = (int)result; #elif defined( HAVE_KERNEL_SCHEDULER_H ) # error Unimplemented @@ -586,12 +685,12 @@ static inline int __vlc_cond_timedwait( const char * psz_file, int i_line, i_res = pthread_cond_timedwait( &p_condvar->cond, &p_mutex->mutex, &ts ); if( i_res == ETIMEDOUT ) - i_res = 0; /* this error is perfectly normal */ + return ETIMEDOUT; /* this error is perfectly normal */ else if ( i_res ) /* other errors = bug */ { i_thread = CAST_PTHREAD_TO_INT(pthread_self()); - psz_error = strerror(i_res); + errno = i_res; } #elif defined( HAVE_CTHREADS_H ) @@ -601,8 +700,8 @@ static inline int __vlc_cond_timedwait( const char * psz_file, int i_line, if( i_res ) { msg_Err( p_condvar->p_this, - "thread %li: cond_wait failed at %s:%d (%d:%s)", - i_thread, psz_file, i_line, i_res, psz_error ); + "thread %li: cond_wait failed at %s:%d (%d:%m)", + i_thread, psz_file, i_line, i_res ); } return i_res;