#include <vlc/vlc.h>
-#include <stdlib.h>
#include "libvlc.h"
+#include <assert.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
#define VLC_THREADS_UNINITIALIZED 0
#define VLC_THREADS_PENDING 1
vlc_threadvar_t msg_context_global_key;
+/*****************************************************************************
+ * vlc_threads_error: Report an error from the threading mecanism
+ *****************************************************************************
+ * This is especially useful to debug those errors, as this is a nice symbol
+ * on which you can break.
+ *****************************************************************************/
+void
+__vlc_threads_error( vlc_object_t *p_this )
+{
+ msg_Err( p_this, "Error detected. Put a breakpoint in '%s' to debug.",
+ __func__ );
+}
+
/*****************************************************************************
* vlc_threads_init: initialize threads system
*****************************************************************************
*****************************************************************************/
int __vlc_mutex_init( vlc_object_t *p_this, vlc_mutex_t *p_mutex )
{
+ assert( p_this );
p_mutex->p_this = p_this;
#if defined( PTH_INIT_IN_PTH_H )
return B_OK;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
-# if defined(DEBUG) && defined(SYS_LINUX)
+# if defined(DEBUG)
{
/* Create error-checking mutex to detect problems more easily. */
pthread_mutexattr_t attr;
int i_result;
pthread_mutexattr_init( &attr );
+# if defined(SYS_LINUX)
pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_ERRORCHECK_NP );
+# else
+ pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_ERRORCHECK );
+# endif
+
i_result = pthread_mutex_init( &p_mutex->mutex, &attr );
pthread_mutexattr_destroy( &attr );
return( i_result );
}
-# endif
+# endif
return pthread_mutex_init( &p_mutex->mutex, NULL );
#elif defined( HAVE_CTHREADS_H )
#endif
}
+/*****************************************************************************
+ * vlc_mutex_init: initialize a recursive mutex (Do not use)
+ *****************************************************************************/
+int __vlc_mutex_init_recursive( vlc_object_t *p_this, 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( PTHREAD_COND_T_IN_PTHREAD_H )
+ pthread_mutexattr_t attr;
+ int i_result;
+
+ pthread_mutexattr_init( &attr );
+# if defined(DEBUG)
+ /* 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
+ pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
+ i_result = pthread_mutex_init( &p_mutex->mutex, &attr );
+ pthread_mutexattr_destroy( &attr );
+ return( i_result );
+#else
+ msg_Err(p_this, "no recursive mutex found. Falling back to regular mutex.\n"
+ "Expect hangs\n")
+ return __vlc_mutex_init( p_this, p_mutex );
+#endif
+}
+
+
/*****************************************************************************
* vlc_mutex_destroy: destroy a mutex, inner version
*****************************************************************************/
int i_result;
/* In case of error : */
int i_thread = -1;
- const char * psz_error = "";
#if defined( PTH_INIT_IN_PTH_H )
return 0;
if( i_result )
{
i_thread = CAST_PTHREAD_TO_INT(pthread_self());
- psz_error = strerror(i_result);
+ errno = i_result;
}
#elif defined( HAVE_CTHREADS_H )
if( i_result )
{
msg_Err( p_mutex->p_this,
- "thread %d: mutex_destroy failed at %s:%d (%d:%s)",
- i_thread, psz_file, i_line, i_result, psz_error );
+ "thread %d: mutex_destroy failed at %s:%d (%d:%m)",
+ i_thread, psz_file, i_line, i_result );
+ vlc_threads_error( p_mutex->p_this );
}
return i_result;
}
return 0;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
- return pthread_cond_init( &p_condvar->cond, NULL );
+ 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->cond, &attr);
+ pthread_condattr_destroy (&attr);
+ return ret;
#elif defined( HAVE_CTHREADS_H )
/* condition_init() */
int i_result;
/* In case of error : */
int i_thread = -1;
- const char * psz_error = "";
#if defined( PTH_INIT_IN_PTH_H )
return 0;
|| !CloseHandle( p_condvar->semaphore );
if( p_condvar->semaphore != NULL )
- DeleteCriticalSection( &p_condvar->csection );
+ DeleteCriticalSection( &p_condvar->csection );
#elif defined( HAVE_KERNEL_SCHEDULER_H )
p_condvar->init = 0;
if( i_result )
{
i_thread = CAST_PTHREAD_TO_INT(pthread_self());
- psz_error = strerror(i_result);
+ errno = i_result;
}
#elif defined( HAVE_CTHREADS_H )
if( i_result )
{
msg_Err( p_condvar->p_this,
- "thread %d: cond_destroy failed at %s:%d (%d:%s)",
- i_thread, psz_file, i_line, i_result, psz_error );
+ "thread %d: cond_destroy failed at %s:%d (%d:%m)",
+ i_thread, psz_file, i_line, i_result );
+ vlc_threads_error( p_condvar->p_this );
}
return i_result;
}
DWORD threadId;
HANDLE hThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)func,
(LPVOID)p_data, CREATE_SUSPENDED,
- &threadId );
+ &threadId );
#else
unsigned threadId;
uintptr_t hThread = _beginthreadex( NULL, 0,
- (LPTHREAD_START_ROUTINE)func,
+ (LPTHREAD_START_ROUTINE)func,
(void*)p_data, CREATE_SUSPENDED,
- &threadId );
+ &threadId );
#endif
p_priv->thread_id.id = (DWORD)threadId;
p_priv->thread_id.hThread = (HANDLE)hThread;
- ResumeThread((HANDLE)hThread);
+ ResumeThread((HANDLE)hThread);
}
i_ret = ( p_priv->thread_id.hThread ? 0 : 1 );
if( (i_error = pthread_setschedparam( p_priv->thread_id,
i_policy, ¶m )) )
{
- msg_Warn( p_this, "couldn't set thread priority (%s:%d): %s",
- psz_file, i_line, strerror(i_error) );
+ errno = i_error;
+ msg_Warn( p_this, "couldn't set thread priority (%s:%d): %m",
+ psz_file, i_line );
i_priority = 0;
}
}
if( b_wait )
{
msg_Dbg( p_this, "waiting for thread completion" );
- vlc_cond_wait( &p_this->object_wait, &p_this->object_lock );
+ vlc_object_wait( p_this );
}
p_priv->b_thread = VLC_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 );
+ 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,
}
else
{
- msg_Err( p_this, "%s thread could not be created at %s:%d (%s)",
- psz_name, psz_file, i_line, strerror(i_ret) );
+ errno = i_ret;
+ msg_Err( p_this, "%s thread could not be created at %s:%d (%m)",
+ psz_name, psz_file, i_line );
+ vlc_threads_error( p_this );
vlc_mutex_unlock( &p_this->object_lock );
}
if( (i_error = pthread_setschedparam( p_priv->thread_id,
i_policy, ¶m )) )
{
- msg_Warn( p_this, "couldn't set thread priority (%s:%d): %s",
- psz_file, i_line, strerror(i_error) );
+ errno = i_error;
+ msg_Warn( p_this, "couldn't set thread priority (%s:%d): %m",
+ psz_file, i_line );
i_priority = 0;
}
}
*****************************************************************************/
void __vlc_thread_ready( vlc_object_t *p_this )
{
- vlc_mutex_lock( &p_this->object_lock );
- vlc_cond_signal( &p_this->object_wait );
- vlc_mutex_unlock( &p_this->object_lock );
+ vlc_object_signal( p_this );
}
/*****************************************************************************
FILETIME create_ft, exit_ft, kernel_ft, user_ft;
int64_t real_time, kernel_time, user_time;
HANDLE hThread;
-
+
/*
- ** object will close its thread handle when destroyed, duplicate it here
+ ** object will close its thread handle when destroyed, duplicate it here
** to be on the safe side
*/
if( ! DuplicateHandle(GetCurrentProcess(),
{
msg_Err( p_this, "thread_join(%u) failed at %s:%d (%s)",
(unsigned int)p_priv->thread_id.id,
- psz_file, i_line, GetLastError() );
+ psz_file, i_line, GetLastError() );
+ vlc_threads_error( p_this );
p_priv->b_thread = VLC_FALSE;
return;
}
WaitForSingleObject( hThread, INFINITE );
msg_Dbg( p_this, "thread %u joined (%s:%d)",
- (unsigned int)p_priv->thread_id.id,
- psz_file, i_line );
+ (unsigned int)p_priv->thread_id.id,
+ psz_file, i_line );
#if defined( UNDER_CE )
hmodule = GetModuleHandle( _T("COREDLL") );
#else
if( i_ret )
{
- msg_Err( p_this, "thread_join(%u) failed at %s:%d (%s)",
- (unsigned int)p_priv->thread_id, psz_file, i_line,
- strerror(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 );
+ vlc_threads_error( p_this );
}
else
{