X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmisc%2Fthreads.c;h=9cac384deb65caebc5a68ef1508e18699abf5e15;hb=848489c3863b1b7ddbe542aa3e746063722b9280;hp=a7ab5c07b0d3f9441e31a55e2648d800bb41bcd7;hpb=566d7d2fc459ca6047acbf3194275ce780c8190c;p=vlc diff --git a/src/misc/threads.c b/src/misc/threads.c index a7ab5c07b0..9cac384deb 100644 --- a/src/misc/threads.c +++ b/src/misc/threads.c @@ -101,14 +101,13 @@ void vlc_pthread_fatal (const char *action, int error, { fprintf (stderr, "LibVLC fatal error %s in thread %lu at %s:%u: %d\n", action, vlc_threadid (), file, line, error); - fflush (stderr); /* Sometimes strerror_r() crashes too, so make sure we print an error * message before we invoke it */ #ifdef __GLIBC__ /* Avoid the strerror_r() prototype brain damage in glibc */ errno = error; - dprintf (2, " Error message: %m at:\n"); + fprintf (stderr, " Error message: %m at:\n"); #else char buf[1000]; const char *msg; @@ -126,8 +125,8 @@ void vlc_pthread_fatal (const char *action, int error, break; } fprintf (stderr, " Error message: %s\n", msg); - fflush (stderr); #endif + fflush (stderr); #ifdef HAVE_BACKTRACE void *stack[20]; @@ -165,7 +164,7 @@ int vlc_threads_init( void ) if( i_initializations == 0 ) { - p_root = vlc_custom_create( NULL, sizeof( *p_root ), + p_root = vlc_custom_create( (vlc_object_t *)NULL, sizeof( *p_root ), VLC_OBJECT_GENERIC, "root" ); if( p_root == NULL ) { @@ -467,6 +466,12 @@ static THREAD_RTYPE thread_entry (void *data) msg_Dbg (obj, "thread started"); func (obj); msg_Dbg (obj, "thread ended"); + + libvlc_priv_t *libpriv = libvlc_priv (obj->p_libvlc); + vlc_mutex_lock (&libpriv->threads_lock); + if (--libpriv->threads_count == 0) + vlc_cond_signal (&libpriv->threads_wait); + vlc_mutex_unlock (&libpriv->threads_lock); return THREAD_RVAL; } @@ -482,6 +487,7 @@ int __vlc_thread_create( vlc_object_t *p_this, const char * psz_file, int i_line { int i_ret; vlc_object_internals_t *p_priv = vlc_internals( p_this ); + libvlc_priv_t *libpriv = libvlc_priv (p_this->p_libvlc); struct vlc_thread_boot *boot = malloc (sizeof (*boot)); if (boot == NULL) @@ -489,7 +495,14 @@ int __vlc_thread_create( vlc_object_t *p_this, const char * psz_file, int i_line boot->entry = func; boot->object = p_this; - vlc_mutex_lock( &p_this->object_lock ); + vlc_mutex_lock (&libpriv->threads_lock); + libpriv->threads_count++; + vlc_mutex_unlock (&libpriv->threads_lock); + + vlc_object_lock( p_this ); + + /* Make sure we don't re-create a thread if the object has already one */ + assert( !p_priv->b_thread ); #if defined( LIBVLC_USE_PTHREAD ) pthread_attr_t attr; @@ -539,34 +552,30 @@ int __vlc_thread_create( vlc_object_t *p_this, const char * psz_file, int i_line pthread_attr_destroy (&attr); #elif defined( WIN32 ) || defined( UNDER_CE ) - { - /* When using the MSVCRT C library you have to use the _beginthreadex - * function instead of CreateThread, otherwise you'll end up with - * memory leaks and the signal functions not working (see Microsoft - * Knowledge Base, article 104641) */ + /* When using the MSVCRT C library you have to use the _beginthreadex + * function instead of CreateThread, otherwise you'll end up with + * memory leaks and the signal functions not working (see Microsoft + * Knowledge Base, article 104641) */ #if defined( UNDER_CE ) - HANDLE hThread = CreateThread( NULL, 0, thread_entry, - (LPVOID)boot, CREATE_SUSPENDED, - NULL ); + HANDLE hThread = CreateThread( NULL, 0, thread_entry, + (LPVOID)boot, CREATE_SUSPENDED, NULL ); #else - HANDLE hThread = (HANDLE)(uintptr_t) - _beginthreadex( NULL, 0, thread_entry, boot, - CREATE_SUSPENDED, NULL ); + HANDLE hThread = (HANDLE)(uintptr_t) + _beginthreadex( NULL, 0, thread_entry, boot, CREATE_SUSPENDED, NULL ); #endif - p_priv->thread_id = hThread; - ResumeThread(hThread); - } - - i_ret = ( p_priv->thread_id ? 0 : errno ); - - if( !i_ret && i_priority ) + if( hThread ) { - if( !SetThreadPriority(p_priv->thread_id, i_priority) ) + p_priv->thread_id = hThread; + ResumeThread (hThread); + i_ret = 0; + if( i_priority && !SetThreadPriority (hThread, i_priority) ) { msg_Warn( p_this, "couldn't set a faster priority" ); i_priority = 0; } } + else + i_ret = errno; #elif defined( HAVE_KERNEL_SCHEDULER_H ) p_priv->thread_id = spawn_thread( (thread_func)thread_entry, psz_name, @@ -595,7 +604,15 @@ int __vlc_thread_create( vlc_object_t *p_this, const char * psz_file, int i_line psz_name, psz_file, i_line ); } - vlc_mutex_unlock( &p_this->object_lock ); + vlc_object_unlock( p_this ); + + if (i_ret) + { + vlc_mutex_lock (&libpriv->threads_lock); + if (--libpriv->threads_count == 0) + vlc_cond_signal (&libpriv->threads_wait); + vlc_mutex_unlock (&libpriv->threads_lock); + } return i_ret; } @@ -608,6 +625,12 @@ int __vlc_thread_set_priority( vlc_object_t *p_this, const char * psz_file, { vlc_object_internals_t *p_priv = vlc_internals( p_this ); + if( !p_priv->b_thread ) + { + msg_Err( p_this, "couldn't set priority of non-existent thread" ); + return ESRCH; + } + #if defined( LIBVLC_USE_PTHREAD ) # ifndef __APPLE__ if( config_GetInt( p_this, "rt-priority" ) > 0 ) @@ -629,10 +652,8 @@ int __vlc_thread_set_priority( vlc_object_t *p_this, const char * psz_file, param.sched_priority = i_priority; i_policy = SCHED_RR; } - if( !p_priv->thread_id ) - p_priv->thread_id = pthread_self(); if( (i_error = pthread_setschedparam( p_priv->thread_id, - i_policy, ¶m )) ) + i_policy, ¶m )) ) { errno = i_error; msg_Warn( p_this, "couldn't set thread priority (%s:%d): %m", @@ -644,8 +665,6 @@ int __vlc_thread_set_priority( vlc_object_t *p_this, const char * psz_file, #elif defined( WIN32 ) || defined( UNDER_CE ) VLC_UNUSED( psz_file); VLC_UNUSED( i_line ); - if( !p_priv->thread_id ) - p_priv->thread_id = GetCurrentThread(); if( !SetThreadPriority(p_priv->thread_id, i_priority) ) { msg_Warn( p_this, "couldn't set a faster priority" ); @@ -657,14 +676,6 @@ int __vlc_thread_set_priority( vlc_object_t *p_this, const char * psz_file, return 0; } -/***************************************************************************** - * vlc_thread_ready: tell the parent thread we were successfully spawned - *****************************************************************************/ -void __vlc_thread_ready( vlc_object_t *p_this ) -{ - vlc_object_signal( p_this ); -} - /***************************************************************************** * vlc_thread_join: wait until a thread exits, inner version *****************************************************************************/ @@ -677,7 +688,10 @@ void __vlc_thread_join( vlc_object_t *p_this, const char * psz_file, int i_line /* Make sure we do return if we are calling vlc_thread_join() * from the joined thread */ if (pthread_equal (pthread_self (), p_priv->thread_id)) + { + msg_Warn (p_this, "joining the active thread (VLC might crash)"); i_ret = pthread_detach (p_priv->thread_id); + } else i_ret = pthread_join (p_priv->thread_id, NULL);