X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmisc%2Fthreads.c;h=33270df4a65a75be81a6d9ba63b24a761bea1df3;hb=d666030b2349e8a710fcba4d2cabb912cc700580;hp=45ca8740e2698807be99138ba9123a095e667af3;hpb=b648be13957fae14cbcddcbde0309c6d6133d494;p=vlc diff --git a/src/misc/threads.c b/src/misc/threads.c index 45ca8740e2..33270df4a6 100644 --- a/src/misc/threads.c +++ b/src/misc/threads.c @@ -28,13 +28,14 @@ # include "config.h" #endif -#include +#include #include "libvlc.h" #include #ifdef HAVE_UNISTD_H # include #endif +#include #define VLC_THREADS_UNINITIALIZED 0 #define VLC_THREADS_PENDING 1 @@ -45,27 +46,33 @@ * Global mutex for lazy initialization of the threads system *****************************************************************************/ static volatile unsigned i_initializations = 0; -static volatile int i_status = VLC_THREADS_UNINITIALIZED; -static vlc_object_t *p_root; -#if defined( UNDER_CE ) -#elif defined( WIN32 ) - -/* -** On Windows 9x/Me you can use a fast but incorrect condition variables -** implementation (more precisely there is a possibility for a race -** condition to happen). -** However it is possible to use slower alternatives which are more robust. -** Currently you can choose between implementation 0 (which is the -** fastest but slightly incorrect), 1 (default) and 2. -*/ -static int i_win9x_cv = 1; - -#elif defined( HAVE_KERNEL_SCHEDULER_H ) -#elif defined( LIBVLC_USE_PTHREAD ) +#if defined( LIBVLC_USE_PTHREAD ) static pthread_mutex_t once_mutex = PTHREAD_MUTEX_INITIALIZER; #endif +/** + * Global process-wide VLC object. + * Contains inter-instance data, such as the module cache and global mutexes. + */ +static libvlc_global_data_t *p_root; + +libvlc_global_data_t *vlc_global( void ) +{ + assert( i_initializations > 0 ); + return p_root; +} + +/** + * Object running the current thread + */ +static vlc_threadvar_t thread_object_key; + +vlc_object_t *vlc_threadobj (void) +{ + return vlc_threadvar_get (&thread_object_key); +} + vlc_threadvar_t msg_context_global_key; #if defined(LIBVLC_USE_PTHREAD) @@ -76,6 +83,9 @@ static inline unsigned long vlc_threadid (void) return v.i; } +#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) +# include +#endif /***************************************************************************** * vlc_thread_fatal: Report an error from the threading layer @@ -94,7 +104,7 @@ void vlc_pthread_fatal (const char *action, int error, #ifdef __GLIBC__ /* Avoid the strerror_r() prototype brain damage in glibc */ errno = error; - fprintf (stderr, " Error message: %m\n"); + dprintf (2, " Error message: %m at:\n"); #else char buf[1000]; const char *msg; @@ -112,14 +122,26 @@ void vlc_pthread_fatal (const char *action, int error, break; } fprintf (stderr, " Error message: %s\n", msg); + fflush (stderr); +#endif + +#ifdef HAVE_BACKTRACE + void *stack[20]; + int len = backtrace (stack, sizeof (stack) / sizeof (stack[0])); + backtrace_symbols_fd (stack, len, 2); #endif - fflush (stderr); abort (); } +#else +void vlc_pthread_fatal (const char *action, int error, + const char *file, unsigned line) +{ + (void)action; (void)error; (void)file; (void)line; + abort(); +} #endif - /***************************************************************************** * vlc_threads_init: initialize threads system ***************************************************************************** @@ -127,72 +149,39 @@ void vlc_pthread_fatal (const char *action, int error, * keep the library really thread-safe. Some architectures don't support this * and thus do not guarantee the complete reentrancy. *****************************************************************************/ -int __vlc_threads_init( vlc_object_t *p_this ) +int vlc_threads_init( void ) { - libvlc_global_data_t *p_libvlc_global = (libvlc_global_data_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( UNDER_CE ) -#elif defined( WIN32 ) - if( IsDebuggerPresent() ) - { - /* SignalObjectAndWait() is problematic under a debugger */ - i_win9x_cv = 1; - } -#elif defined( HAVE_KERNEL_SCHEDULER_H ) -#elif defined( LIBVLC_USE_PTHREAD ) +#if defined( LIBVLC_USE_PTHREAD ) pthread_mutex_lock( &once_mutex ); #endif - if( i_status == VLC_THREADS_UNINITIALIZED ) + if( i_initializations == 0 ) { - i_status = VLC_THREADS_PENDING; - - /* We should be safe now. Do all the initialization stuff we want. */ - p_libvlc_global->b_ready = false; - - p_root = vlc_custom_create( VLC_OBJECT(p_libvlc_global), 0, - VLC_OBJECT_GLOBAL, "global" ); + p_root = vlc_custom_create( NULL, sizeof( *p_root ), + VLC_OBJECT_GENERIC, "root" ); if( p_root == NULL ) - i_ret = VLC_ENOMEM; - - if( i_ret ) { - i_status = VLC_THREADS_ERROR; - } - else - { - i_initializations++; - i_status = VLC_THREADS_READY; + i_ret = VLC_ENOMEM; + goto out; } - vlc_threadvar_create( p_root, &msg_context_global_key ); - } - else - { - /* Just increment the initialization count */ - i_initializations++; + /* We should be safe now. Do all the initialization stuff we want. */ + vlc_threadvar_create( &thread_object_key, NULL ); + vlc_threadvar_create( &msg_context_global_key, msg_StackDestroy ); } + i_initializations++; - /* If we have lazy mutex initialization support, unlock the mutex; - * otherwize, do a naive wait loop. */ -#if defined( UNDER_CE ) - 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( LIBVLC_USE_PTHREAD ) +out: + /* If we have lazy mutex initialization support, unlock the mutex. + * Otherwize, we are screwed. */ +#if defined( LIBVLC_USE_PTHREAD ) pthread_mutex_unlock( &once_mutex ); #endif - if( i_status != VLC_THREADS_READY ) - { - return VLC_ETHREAD; - } - return i_ret; } @@ -201,52 +190,61 @@ int __vlc_threads_init( vlc_object_t *p_this ) ***************************************************************************** * FIXME: This function is far from being threadsafe. *****************************************************************************/ -int __vlc_threads_end( vlc_object_t *p_this ) +void vlc_threads_end( void ) { - (void)p_this; -#if defined( UNDER_CE ) -#elif defined( WIN32 ) -#elif defined( HAVE_KERNEL_SCHEDULER_H ) -#elif defined( LIBVLC_USE_PTHREAD ) +#if defined( LIBVLC_USE_PTHREAD ) pthread_mutex_lock( &once_mutex ); #endif - if( i_initializations == 0 ) - return VLC_EGENERIC; + assert( i_initializations > 0 ); - i_initializations--; - if( i_initializations == 0 ) + if( i_initializations == 1 ) { - i_status = VLC_THREADS_UNINITIALIZED; vlc_object_release( p_root ); + vlc_threadvar_delete( &msg_context_global_key ); + vlc_threadvar_delete( &thread_object_key ); } + i_initializations--; -#if defined( UNDER_CE ) -#elif defined( WIN32 ) -#elif defined( HAVE_KERNEL_SCHEDULER_H ) -#elif defined( LIBVLC_USE_PTHREAD ) +#if defined( LIBVLC_USE_PTHREAD ) pthread_mutex_unlock( &once_mutex ); #endif - return VLC_SUCCESS; } -#ifdef __linux__ -/* This is not prototyped under Linux, though it exists. */ +#if defined (__GLIBC__) && (__GLIBC_MINOR__ < 6) +/* This is not prototyped under glibc, though it exists. */ int pthread_mutexattr_setkind_np( pthread_mutexattr_t *attr, int kind ); #endif /***************************************************************************** * vlc_mutex_init: initialize a mutex *****************************************************************************/ -int __vlc_mutex_init( vlc_mutex_t *p_mutex ) +int vlc_mutex_init( vlc_mutex_t *p_mutex ) { -#if defined( UNDER_CE ) +#if defined( LIBVLC_USE_PTHREAD ) + pthread_mutexattr_t attr; + int i_result; + + pthread_mutexattr_init( &attr ); + +# ifndef NDEBUG + /* Create error-checking mutex to detect problems more easily. */ +# if defined (__GLIBC__) && (__GLIBC_MINOR__ < 6) + pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_ERRORCHECK_NP ); +# else + pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_ERRORCHECK ); +# endif +# endif + i_result = pthread_mutex_init( p_mutex, &attr ); + pthread_mutexattr_destroy( &attr ); + return i_result; +#elif defined( UNDER_CE ) InitializeCriticalSection( &p_mutex->csection ); return 0; #elif defined( WIN32 ) - p_mutex->mutex = CreateMutex( 0, FALSE, 0 ); - return ( p_mutex->mutex != NULL ? 0 : 1 ); + *p_mutex = CreateMutex( 0, FALSE, 0 ); + return (*p_mutex != NULL) ? 0 : ENOMEM; #elif defined( HAVE_KERNEL_SCHEDULER_H ) /* check the arguments and whether it's already been initialized */ @@ -269,52 +267,31 @@ int __vlc_mutex_init( vlc_mutex_t *p_mutex ) p_mutex->init = 9999; return B_OK; -#elif defined( LIBVLC_USE_PTHREAD ) - pthread_mutexattr_t attr; - int i_result; - - pthread_mutexattr_init( &attr ); - -# ifndef NDEBUG - /* Create error-checking mutex to detect problems more easily. */ -# if defined(SYS_LINUX) - pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_ERRORCHECK_NP ); -# else - pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_ERRORCHECK ); -# endif -# endif - i_result = pthread_mutex_init( p_mutex, &attr ); - pthread_mutexattr_destroy( &attr ); - return i_result; #endif } /***************************************************************************** * vlc_mutex_init: initialize a recursive mutex (Do not use) *****************************************************************************/ -int __vlc_mutex_init_recursive( vlc_mutex_t *p_mutex ) +int vlc_mutex_init_recursive( vlc_mutex_t *p_mutex ) { -#if defined( WIN32 ) - /* Create mutex returns a recursive mutex */ - p_mutex->mutex = CreateMutex( 0, FALSE, 0 ); - return ( p_mutex->mutex != NULL ? 0 : 1 ); -#elif defined( LIBVLC_USE_PTHREAD ) +#if defined( LIBVLC_USE_PTHREAD ) pthread_mutexattr_t attr; int i_result; pthread_mutexattr_init( &attr ); -# ifndef NDEBUG - /* Create error-checking mutex to detect problems more easily. */ -# if defined(SYS_LINUX) - pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_ERRORCHECK_NP ); -# else - pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_ERRORCHECK ); -# endif -# endif +# if defined (__GLIBC__) && (__GLIBC_MINOR__ < 6) + pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_RECURSIVE_NP ); +# else pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE ); +# endif i_result = pthread_mutex_init( p_mutex, &attr ); pthread_mutexattr_destroy( &attr ); return( i_result ); +#elif defined( WIN32 ) + /* Create mutex returns a recursive mutex */ + *p_mutex = CreateMutex( 0, FALSE, 0 ); + return (*p_mutex != NULL) ? 0 : ENOMEM; #else # error Unimplemented! #endif @@ -326,7 +303,11 @@ int __vlc_mutex_init_recursive( vlc_mutex_t *p_mutex ) *****************************************************************************/ void __vlc_mutex_destroy( const char * psz_file, int i_line, vlc_mutex_t *p_mutex ) { -#if defined( UNDER_CE ) +#if defined( LIBVLC_USE_PTHREAD ) + int val = pthread_mutex_destroy( p_mutex ); + VLC_THREAD_ASSERT ("destroying mutex"); + +#elif defined( UNDER_CE ) VLC_UNUSED( psz_file); VLC_UNUSED( i_line ); DeleteCriticalSection( &p_mutex->csection ); @@ -334,10 +315,7 @@ void __vlc_mutex_destroy( const char * psz_file, int i_line, vlc_mutex_t *p_mute #elif defined( WIN32 ) VLC_UNUSED( psz_file); VLC_UNUSED( i_line ); - if( p_mutex->mutex ) - CloseHandle( p_mutex->mutex ); - else - DeleteCriticalSection( &p_mutex->csection ); + CloseHandle( *p_mutex ); #elif defined( HAVE_KERNEL_SCHEDULER_H ) if( p_mutex->init == 9999 ) @@ -345,10 +323,6 @@ void __vlc_mutex_destroy( const char * psz_file, int i_line, vlc_mutex_t *p_mute p_mutex->init = 0; -#elif defined( LIBVLC_USE_PTHREAD ) - int val = pthread_mutex_destroy( p_mutex ); - VLC_THREAD_ASSERT ("destroying mutex"); - #endif } @@ -357,31 +331,36 @@ void __vlc_mutex_destroy( const char * psz_file, int i_line, vlc_mutex_t *p_mute *****************************************************************************/ int __vlc_cond_init( vlc_cond_t *p_condvar ) { -#if defined( UNDER_CE ) - /* Initialize counter */ - p_condvar->i_waiting_threads = 0; +#if defined( LIBVLC_USE_PTHREAD ) + pthread_condattr_t attr; + int ret; - /* Create an auto-reset event. */ - p_condvar->event = CreateEvent( NULL, /* no security */ - FALSE, /* auto-reset event */ - FALSE, /* start non-signaled */ - NULL ); /* unnamed */ - return !p_condvar->event; + ret = pthread_condattr_init (&attr); + if (ret) + return ret; -#elif defined( WIN32 ) +# if !defined (_POSIX_CLOCK_SELECTION) + /* Fairly outdated POSIX support (that was defined in 2001) */ +# define _POSIX_CLOCK_SELECTION (-1) +# endif +# if (_POSIX_CLOCK_SELECTION >= 0) + /* NOTE: This must be the same clock as the one in mtime.c */ + pthread_condattr_setclock (&attr, CLOCK_MONOTONIC); +# endif + + ret = pthread_cond_init (p_condvar, &attr); + pthread_condattr_destroy (&attr); + return ret; + +#elif defined( UNDER_CE ) || defined( WIN32 ) /* Initialize counter */ p_condvar->i_waiting_threads = 0; - /* Misc init */ - p_condvar->i_win9x_cv = i_win9x_cv; - /* Create an auto-reset event. */ p_condvar->event = CreateEvent( NULL, /* no security */ FALSE, /* auto-reset event */ FALSE, /* start non-signaled */ NULL ); /* unnamed */ - - p_condvar->semaphore = NULL; return !p_condvar->event; #elif defined( HAVE_KERNEL_SCHEDULER_H ) @@ -399,27 +378,6 @@ int __vlc_cond_init( vlc_cond_t *p_condvar ) p_condvar->init = 9999; return 0; -#elif defined( LIBVLC_USE_PTHREAD ) - pthread_condattr_t attr; - int ret; - - ret = pthread_condattr_init (&attr); - if (ret) - return ret; - -# if !defined (_POSIX_CLOCK_SELECTION) - /* Fairly outdated POSIX support (that was defined in 2001) */ -# define _POSIX_CLOCK_SELECTION (-1) -# endif -# if (_POSIX_CLOCK_SELECTION >= 0) - /* NOTE: This must be the same clock as the one in mtime.c */ - pthread_condattr_setclock (&attr, CLOCK_MONOTONIC); -# endif - - ret = pthread_cond_init (p_condvar, &attr); - pthread_condattr_destroy (&attr); - return ret; - #endif } @@ -428,55 +386,80 @@ int __vlc_cond_init( vlc_cond_t *p_condvar ) *****************************************************************************/ void __vlc_cond_destroy( const char * psz_file, int i_line, vlc_cond_t *p_condvar ) { -#if defined( UNDER_CE ) - VLC_UNUSED( psz_file); VLC_UNUSED( i_line ); - - CloseHandle( p_condvar->event ); +#if defined( LIBVLC_USE_PTHREAD ) + int val = pthread_cond_destroy( p_condvar ); + VLC_THREAD_ASSERT ("destroying condition"); -#elif defined( WIN32 ) +#elif defined( UNDER_CE ) || defined( WIN32 ) VLC_UNUSED( psz_file); VLC_UNUSED( i_line ); - if( !p_condvar->semaphore ) - CloseHandle( p_condvar->event ); - else - { - CloseHandle( p_condvar->event ); - CloseHandle( p_condvar->semaphore ); - } - - if( p_condvar->semaphore != NULL ) - DeleteCriticalSection( &p_condvar->csection ); + CloseHandle( p_condvar->event ); #elif defined( HAVE_KERNEL_SCHEDULER_H ) p_condvar->init = 0; -#elif defined( LIBVLC_USE_PTHREAD ) - int val = pthread_cond_destroy( p_condvar ); - VLC_THREAD_ASSERT ("destroying condition"); - #endif } /***************************************************************************** * vlc_tls_create: create a thread-local variable *****************************************************************************/ -int __vlc_threadvar_create( vlc_threadvar_t *p_tls ) +int vlc_threadvar_create( vlc_threadvar_t *p_tls, void (*destr) (void *) ) { - int i_ret = -1; + int i_ret; -#if defined( HAVE_KERNEL_SCHEDULER_H ) -# error Unimplemented! -#elif defined( UNDER_CE ) || defined( WIN32 ) +#if defined( LIBVLC_USE_PTHREAD ) + i_ret = pthread_key_create( p_tls, destr ); +#elif defined( UNDER_CE ) + i_ret = ENOSYS; #elif defined( WIN32 ) *p_tls = TlsAlloc(); - i_ret = (*p_tls == INVALID_HANDLE_VALUE) ? EAGAIN : 0; - -#elif defined( LIBVLC_USE_PTHREAD ) - i_ret = pthread_key_create( p_tls, NULL ); + i_ret = (*p_tls == TLS_OUT_OF_INDEXES) ? EAGAIN : 0; +#else +# error Unimplemented! #endif return i_ret; } +void vlc_threadvar_delete (vlc_threadvar_t *p_tls) +{ +#if defined( LIBVLC_USE_PTHREAD ) + pthread_key_delete (*p_tls); +#elif defined( UNDER_CE ) +#elif defined( WIN32 ) + TlsFree (*p_tls); +#else +# error Unimplemented! +#endif +} + +struct vlc_thread_boot +{ + void * (*entry) (void *); + vlc_object_t *object; +}; + +#if defined (LIBVLC_USE_PTHREAD) +# define THREAD_RTYPE void * +# define THREAD_RVAL NULL +#elif defined (WIN32) +# define THREAD_RTYPE __stdcall unsigned +# define THREAD_RVAL 0 +#endif + +static THREAD_RTYPE thread_entry (void *data) +{ + vlc_object_t *obj = ((struct vlc_thread_boot *)data)->object; + void *(*func) (void *) = ((struct vlc_thread_boot *)data)->entry; + + free (data); + vlc_threadvar_set (&thread_object_key, obj); + msg_Dbg (obj, "thread started"); + func (obj); + msg_Dbg (obj, "thread ended"); + return THREAD_RVAL; +} + /***************************************************************************** * vlc_thread_create: create a thread, inner version ***************************************************************************** @@ -488,55 +471,39 @@ int __vlc_thread_create( vlc_object_t *p_this, const char * psz_file, int i_line int i_priority, bool b_wait ) { int i_ret; - void *p_data = (void *)p_this; - vlc_object_internals_t *p_priv = p_this->p_internals; - - vlc_mutex_lock( &p_this->object_lock ); - -#if 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) */ -#if defined( UNDER_CE ) - DWORD threadId; - HANDLE hThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)func, - (LPVOID)p_data, CREATE_SUSPENDED, - &threadId ); -#else - unsigned threadId; - uintptr_t hThread = _beginthreadex( NULL, 0, - (LPTHREAD_START_ROUTINE)func, - (void*)p_data, CREATE_SUSPENDED, - &threadId ); -#endif - p_priv->thread_id.id = (DWORD)threadId; - p_priv->thread_id.hThread = (HANDLE)hThread; - ResumeThread((HANDLE)hThread); - } + vlc_object_internals_t *p_priv = vlc_internals( p_this ); - i_ret = ( p_priv->thread_id.hThread ? 0 : 1 ); - - if( !i_ret && i_priority ) - { - if( !SetThreadPriority(p_priv->thread_id.hThread, i_priority) ) - { - msg_Warn( p_this, "couldn't set a faster priority" ); - i_priority = 0; - } - } + struct vlc_thread_boot *boot = malloc (sizeof (*boot)); + if (boot == NULL) + return errno; + boot->entry = func; + boot->object = p_this; -#elif defined( HAVE_KERNEL_SCHEDULER_H ) - p_priv->thread_id = spawn_thread( (thread_func)func, psz_name, - i_priority, p_data ); - i_ret = resume_thread( p_priv->thread_id ); + vlc_mutex_lock( &p_this->object_lock ); -#elif defined( LIBVLC_USE_PTHREAD ) - i_ret = pthread_create( &p_priv->thread_id, NULL, func, p_data ); +#if defined( LIBVLC_USE_PTHREAD ) + sigset_t set, oldset; + + /* We really don't want signals to (literaly) interrupt our blocking I/O + * system calls. SIGPIPE is especially bad, as it can be caused by remote + * peers through connected sockets. Generally, we cannot know which signals + * are handled by the main program. Also, external LibVLC bindings tend not + * to setup a proper signal mask before invoking LibVLC. + * Hence, we hereby block all signals, except those for which blocking is + * undefined, as listed below. Note that SIGKILL and SIGSTOP need not be + * listed (see the documentation for pthread_sigmask) here. */ + sigfillset (&set); + sigdelset (&set, SIGFPE); + sigdelset (&set, SIGILL); + sigdelset (&set, SIGSEGV); + sigdelset (&set, SIGBUS); + pthread_sigmask (SIG_BLOCK, &set, &oldset); + + i_ret = pthread_create( &p_priv->thread_id, NULL, thread_entry, boot ); + pthread_sigmask (SIG_SETMASK, &oldset, NULL); #ifndef __APPLE__ - if( config_GetInt( p_this, "rt-priority" ) ) + if( config_GetInt( p_this, "rt-priority" ) > 0 ) #endif { int i_error, i_policy; @@ -544,9 +511,7 @@ int __vlc_thread_create( vlc_object_t *p_this, const char * psz_file, int i_line memset( ¶m, 0, sizeof(struct sched_param) ); if( config_GetType( p_this, "rt-offset" ) ) - { i_priority += config_GetInt( p_this, "rt-offset" ); - } if( i_priority <= 0 ) { param.sched_priority = (-1) * i_priority; @@ -568,11 +533,44 @@ int __vlc_thread_create( vlc_object_t *p_this, const char * psz_file, int i_line } #ifndef __APPLE__ else - { i_priority = 0; - } #endif +#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) */ +#if defined( UNDER_CE ) + 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 ); +#endif + p_priv->thread_id = hThread; + ResumeThread(hThread); + } + + i_ret = ( p_priv->thread_id ? 0 : errno ); + + if( !i_ret && i_priority ) + { + if( !SetThreadPriority(p_priv->thread_id, i_priority) ) + { + msg_Warn( p_this, "couldn't set a faster priority" ); + i_priority = 0; + } + } + +#elif defined( HAVE_KERNEL_SCHEDULER_H ) + p_priv->thread_id = spawn_thread( (thread_func)thread_entry, psz_name, + i_priority, p_data ); + i_ret = resume_thread( p_priv->thread_id ); + #endif if( i_ret == 0 ) @@ -584,28 +582,18 @@ int __vlc_thread_create( vlc_object_t *p_this, const char * psz_file, int i_line } p_priv->b_thread = true; - -#if defined( WIN32 ) || defined( UNDER_CE ) - msg_Dbg( p_this, "thread %u (%s) created at priority %d (%s:%d)", - (unsigned int)p_priv->thread_id.id, psz_name, - i_priority, psz_file, i_line ); -#else - msg_Dbg( p_this, "thread %u (%s) created at priority %d (%s:%d)", - (unsigned int)p_priv->thread_id, psz_name, i_priority, + msg_Dbg( p_this, "thread %lu (%s) created at priority %d (%s:%d)", + (unsigned long)p_priv->thread_id, psz_name, i_priority, psz_file, i_line ); -#endif - - - vlc_mutex_unlock( &p_this->object_lock ); } else { errno = i_ret; msg_Err( p_this, "%s thread could not be created at %s:%d (%m)", psz_name, psz_file, i_line ); - vlc_mutex_unlock( &p_this->object_lock ); } + vlc_mutex_unlock( &p_this->object_lock ); return i_ret; } @@ -616,19 +604,9 @@ int __vlc_thread_create( vlc_object_t *p_this, const char * psz_file, int i_line int __vlc_thread_set_priority( vlc_object_t *p_this, const char * psz_file, int i_line, int i_priority ) { - vlc_object_internals_t *p_priv = p_this->p_internals; -#if defined( WIN32 ) || defined( UNDER_CE ) - VLC_UNUSED( psz_file); VLC_UNUSED( i_line ); - - if( !p_priv->thread_id.hThread ) - p_priv->thread_id.hThread = GetCurrentThread(); - if( !SetThreadPriority(p_priv->thread_id.hThread, i_priority) ) - { - msg_Warn( p_this, "couldn't set a faster priority" ); - return 1; - } + vlc_object_internals_t *p_priv = vlc_internals( p_this ); -#elif defined( LIBVLC_USE_PTHREAD ) +#if defined( LIBVLC_USE_PTHREAD ) # ifndef __APPLE__ if( config_GetInt( p_this, "rt-priority" ) > 0 ) # endif @@ -638,9 +616,7 @@ int __vlc_thread_set_priority( vlc_object_t *p_this, const char * psz_file, memset( ¶m, 0, sizeof(struct sched_param) ); if( config_GetType( p_this, "rt-offset" ) ) - { i_priority += config_GetInt( p_this, "rt-offset" ); - } if( i_priority <= 0 ) { param.sched_priority = (-1) * i_priority; @@ -662,6 +638,18 @@ int __vlc_thread_set_priority( vlc_object_t *p_this, const char * psz_file, i_priority = 0; } } + +#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" ); + return 1; + } + #endif return 0; @@ -680,9 +668,18 @@ void __vlc_thread_ready( vlc_object_t *p_this ) *****************************************************************************/ void __vlc_thread_join( vlc_object_t *p_this, const char * psz_file, int i_line ) { - vlc_object_internals_t *p_priv = p_this->p_internals; + vlc_object_internals_t *p_priv = vlc_internals( p_this ); + int i_ret = 0; + +#if defined( LIBVLC_USE_PTHREAD ) + /* 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)) + i_ret = pthread_detach (p_priv->thread_id); + else + i_ret = pthread_join (p_priv->thread_id, NULL); -#if defined( UNDER_CE ) || defined( WIN32 ) +#elif defined( UNDER_CE ) || defined( WIN32 ) HMODULE hmodule; BOOL (WINAPI *OurGetThreadTimes)( HANDLE, FILETIME*, FILETIME*, FILETIME*, FILETIME* ); @@ -695,25 +692,20 @@ void __vlc_thread_join( vlc_object_t *p_this, const char * psz_file, int i_line ** to be on the safe side */ if( ! DuplicateHandle(GetCurrentProcess(), - p_priv->thread_id.hThread, + p_priv->thread_id, GetCurrentProcess(), &hThread, 0, FALSE, DUPLICATE_SAME_ACCESS) ) { - msg_Err( p_this, "thread_join(%u) failed at %s:%d (%u)", - (unsigned int)p_priv->thread_id.id, - psz_file, i_line, (unsigned int)GetLastError() ); p_priv->b_thread = false; - return; + i_ret = GetLastError(); + goto error; } WaitForSingleObject( hThread, INFINITE ); - msg_Dbg( p_this, "thread %u joined (%s:%d)", - (unsigned int)p_priv->thread_id.id, - psz_file, i_line ); #if defined( UNDER_CE ) hmodule = GetModuleHandle( _T("COREDLL") ); #else @@ -741,7 +733,7 @@ void __vlc_thread_join( vlc_object_t *p_this, const char * psz_file, int i_line user_ft.dwLowDateTime) / 10; msg_Dbg( p_this, "thread times: " - "real "I64Fd"m%fs, kernel "I64Fd"m%fs, user "I64Fd"m%fs", + "real %"PRId64"m%fs, kernel %"PRId64"m%fs, user %"PRId64"m%fs", real_time/60/1000000, (double)((real_time%(60*1000000))/1000000.0), kernel_time/60/1000000, @@ -750,38 +742,23 @@ void __vlc_thread_join( vlc_object_t *p_this, const char * psz_file, int i_line (double)((user_time%(60*1000000))/1000000.0) ); } CloseHandle( hThread ); +error: -#else /* !defined(WIN32) */ - - int i_ret = 0; - -#if defined( HAVE_KERNEL_SCHEDULER_H ) +#elif defined( HAVE_KERNEL_SCHEDULER_H ) int32_t exit_value; i_ret = (B_OK == wait_for_thread( p_priv->thread_id, &exit_value )); -#elif defined( LIBVLC_USE_PTHREAD ) - /* 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)) - i_ret = pthread_detach (p_priv->thread_id); - else - i_ret = pthread_join (p_priv->thread_id, NULL); #endif if( i_ret ) { errno = i_ret; - msg_Err( p_this, "thread_join(%u) failed at %s:%d (%m)", - (unsigned int)p_priv->thread_id, psz_file, i_line ); + msg_Err( p_this, "thread_join(%lu) failed at %s:%d (%m)", + (unsigned long)p_priv->thread_id, psz_file, i_line ); } else - { - msg_Dbg( p_this, "thread %u joined (%s:%d)", - (unsigned int)p_priv->thread_id, psz_file, i_line ); - } - -#endif + msg_Dbg( p_this, "thread %lu joined (%s:%d)", + (unsigned long)p_priv->thread_id, psz_file, i_line ); p_priv->b_thread = false; } -