#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
*****************************************************************************/
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 )
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 );
}
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) && (_POSIX_CLOCK_SELECTION - 0 > 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 );
}
return i_result;
}
return i_ret;
}
-#if defined( WIN32 ) || defined( UNDER_CE )
-
-/*
-** Use a wrapper function which will make sure that
-** thread handle is closed
-*/
-struct _vlc_win32_init_thread_data {
- void * ( *func ) (void * );
- void *p_data;
-};
-
-static unsigned WINAPI __vlc_win32_thread_start(void* p_data) {
- struct _vlc_win32_init_thread_data *p_win32data =
- (struct _vlc_win32_init_thread_data *)p_data;
- vlc_object_t *p_this = (vlc_object_t *)p_win32data->p_data;
- HANDLE hThread = (HANDLE)p_this->p_internals->thread_id;
- void *retval = (*p_win32data->func)((LPVOID)p_this);
- CloseHandle(hThread);
- return (unsigned)retval;
-}
-
-#endif
-
/*****************************************************************************
* vlc_thread_create: create a thread, inner version
*****************************************************************************
int i_ret;
void *p_data = (void *)p_this;
vlc_object_internals_t *p_priv = p_this->p_internals;
-#if defined( WIN32 ) || defined( UNDER_CE )
- struct _vlc_win32_init_thread_data win32data = { func, p_data };
-#endif
vlc_mutex_lock( &p_this->object_lock );
#elif defined( WIN32 ) || defined( UNDER_CE )
{
- unsigned threadID;
/* 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, __vlc_win32_thread_start,
- (LPVOID)&win32data, 0, &threadID );
+ DWORD threadId;
+ HANDLE hThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)func,
+ (LPVOID)p_data, CREATE_SUSPENDED,
+ &threadId );
#else
- uintptr_t hThread = _beginthreadex( NULL, 0, __vlc_win32_thread_start,
- (void*)&win32data, 0, &threadID );
+ unsigned threadId;
+ uintptr_t hThread = _beginthreadex( NULL, 0,
+ (LPTHREAD_START_ROUTINE)func,
+ (void*)p_data, CREATE_SUSPENDED,
+ &threadId );
#endif
- p_priv->thread_id = (HANDLE)hThread;
+ p_priv->thread_id.id = (DWORD)threadId;
+ p_priv->thread_id.hThread = (HANDLE)hThread;
+ ResumeThread((HANDLE)hThread);
}
- if( p_priv->thread_id && i_priority )
+ i_ret = ( p_priv->thread_id.hThread ? 0 : 1 );
+
+ if( i_ret && i_priority )
{
- if( !SetThreadPriority(p_priv->thread_id, i_priority) )
+ if( !SetThreadPriority(p_priv->thread_id.hThread, i_priority) )
{
msg_Warn( p_this, "couldn't set a faster priority" );
i_priority = 0;
}
}
- i_ret = ( p_priv->thread_id ? 0 : 1 );
-
#elif defined( HAVE_KERNEL_SCHEDULER_H )
p_priv->thread_id = spawn_thread( (thread_func)func, psz_name,
i_priority, p_data );
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 );
+#else
msg_Dbg( p_this, "thread %u (%s) created at priority %d (%s:%d)",
(unsigned int)p_priv->thread_id, psz_name, i_priority,
psz_file, i_line );
+#endif
+
vlc_mutex_unlock( &p_this->object_lock );
}
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_mutex_unlock( &p_this->object_lock );
}
vlc_object_internals_t *p_priv = p_this->p_internals;
#if defined( PTH_INIT_IN_PTH_H ) || defined( ST_INIT_IN_ST_H )
#elif defined( WIN32 ) || defined( UNDER_CE )
- if( !p_priv->thread_id )
- p_priv->thread_id = GetCurrentThread();
- if( !SetThreadPriority((HANDLE)p_priv->thread_id, i_priority) )
+ 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;
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 );
}
/*****************************************************************************
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;
- int i_ret = 0;
-
-#if defined( PTH_INIT_IN_PTH_H )
- i_ret = ( pth_join( p_priv->thread_id, NULL ) == FALSE );
-#elif defined( ST_INIT_IN_ST_H )
- i_ret = st_thread_join( p_priv->thread_id, NULL );
-
-#elif defined( UNDER_CE ) || defined( WIN32 )
+#if defined( UNDER_CE ) || defined( WIN32 )
HMODULE hmodule;
BOOL (WINAPI *OurGetThreadTimes)( HANDLE, FILETIME*, FILETIME*,
FILETIME*, FILETIME* );
FILETIME create_ft, exit_ft, kernel_ft, user_ft;
int64_t real_time, kernel_time, user_time;
HANDLE hThread;
-
- /* thread will destroy its own handle on exit, duplicate it here */
+
+ /*
+ ** object will close its thread handle when destroyed, duplicate it here
+ ** to be on the safe side
+ */
if( ! DuplicateHandle(GetCurrentProcess(),
- (HANDLE)p_priv->thread_id,
+ p_priv->thread_id.hThread,
GetCurrentProcess(),
&hThread,
0,
DUPLICATE_SAME_ACCESS) )
{
msg_Err( p_this, "thread_join(%u) failed at %s:%d (%s)",
- (unsigned int)p_priv->thread_id, psz_file, i_line,
- GetLastError() );
+ (unsigned int)p_priv->thread_id.id,
+ psz_file, i_line, GetLastError() );
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 );
#if defined( UNDER_CE )
hmodule = GetModuleHandle( _T("COREDLL") );
#else
}
CloseHandle( hThread );
+#else /* !defined(WIN32) */
+
+ int i_ret = 0;
+
+#if defined( PTH_INIT_IN_PTH_H )
+ i_ret = ( pth_join( p_priv->thread_id, NULL ) == FALSE );
+
+#elif defined( ST_INIT_IN_ST_H )
+ i_ret = st_thread_join( p_priv->thread_id, NULL );
+
#elif defined( HAVE_KERNEL_SCHEDULER_H )
int32_t exit_value;
- wait_for_thread( p_priv->thread_id, &exit_value );
+ i_ret = (B_OK == wait_for_thread( p_priv->thread_id, &exit_value ));
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
i_ret = pthread_join( p_priv->thread_id, NULL );
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 );
}
else
{
(unsigned int)p_priv->thread_id, psz_file, i_line );
}
+#endif
+
p_priv->b_thread = VLC_FALSE;
}