Commit 8fbbb959 authored by Sam Hocevar's avatar Sam Hocevar

* ./include/vlc_threads.h, ./src/misc/threads.c: improved the cond_wait

    implementation to avoid races, by using SetEvent instead of PulseEvent.
parent ece55c8f
#! /bin/sh
## bootstrap.sh file for vlc, the VideoLAN Client
## $Id: bootstrap.sh,v 1.4 2002/06/07 14:30:40 sam Exp $
## $Id: bootstrap.sh,v 1.5 2002/06/08 14:08:46 sam Exp $
##
## Authors: Samuel Hocevar <sam@zoy.org>
......@@ -35,12 +35,12 @@ echo '' >> $file
echo 'struct module_symbols_s' >> $file
echo '{' >> $file
cat include/*.h | grep '^ *VLC_EXPORT.*;' | \
sed 's/VLC_EXPORT( *\([^,]*\), *\([^,]*\), *\(.*\));.*/ \1 (* \2_inner) \3;/' >> $file
sed 's/VLC_EXPORT( *\([^,]*\), *\([^,]*\), *\(.*\));.*/ \1 (* \2_inner) \3;/' | sort >> $file
echo '};' >> $file
echo '' >> $file
echo '#ifdef __PLUGIN__' >> $file
cat include/*.h | grep '^ *VLC_EXPORT.*;' | \
sed 's/VLC_EXPORT( *\([^,]*\), *\([^,]*\), *\(.*\));.*/# define \2 p_symbols->\2_inner/' >> $file
sed 's/VLC_EXPORT( *\([^,]*\), *\([^,]*\), *\(.*\));.*/# define \2 p_symbols->\2_inner/' | sort >> $file
echo '#endif /* __PLUGIN__ */' >> $file
echo '' >> $file
echo "$file."
......
This diff is collapsed.
......@@ -3,7 +3,7 @@
* This header provides a portable threads implementation.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: vlc_threads.h,v 1.2 2002/06/02 13:38:03 gbazin Exp $
* $Id: vlc_threads.h,v 1.3 2002/06/08 14:08:46 sam Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr>
......@@ -108,15 +108,23 @@ typedef unsigned (__stdcall *PTHREAD_START) (void *);
typedef struct
{
CRITICAL_SECTION csection;
/* WinNT/2K/XP implementation */
HANDLE mutex;
SIGNALOBJECTANDWAIT SignalObjectAndWait;
/* Win95/98/ME implementation */
CRITICAL_SECTION csection;
} vlc_mutex_t;
typedef struct
{
int i_waiting_threads;
HANDLE signal;
int i_waiting_threads;
/* WinNT/2K/XP implementation */
HANDLE semaphore;
HANDLE signal;
vlc_bool_t b_broadcast;
SIGNALOBJECTANDWAIT SignalObjectAndWait;
/* Win95/98/ME implementation */
enum { SIGNAL = 0, BROADCAST = 1 };
HANDLE p_events[2];
} vlc_cond_t;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
......@@ -174,7 +182,7 @@ VLC_EXPORT( int, __vlc_threads_init, ( vlc_object_t * ) );
VLC_EXPORT( int, vlc_threads_end, ( void ) );
VLC_EXPORT( int, __vlc_mutex_init, ( vlc_object_t *, vlc_mutex_t * ) );
VLC_EXPORT( int, __vlc_mutex_destroy, ( char *, int, vlc_mutex_t * ) );
VLC_EXPORT( int, vlc_cond_init, ( vlc_cond_t * ) );
VLC_EXPORT( int, __vlc_cond_init, ( vlc_object_t *, vlc_cond_t * ) );
VLC_EXPORT( int, __vlc_cond_destroy, ( char *, int, vlc_cond_t * ) );
VLC_EXPORT( int, __vlc_thread_create, ( vlc_object_t *, char *, int, char *, void * ( * ) ( void * ), vlc_bool_t ) );
VLC_EXPORT( void, __vlc_thread_ready, ( vlc_object_t * ) );
......@@ -327,6 +335,12 @@ static inline int __vlc_mutex_unlock( char * psz_file, int i_line,
__vlc_mutex_destroy( "(unknown)", 0, P_MUTEX )
#endif
/*****************************************************************************
* vlc_cond_init: initialize a condition
*****************************************************************************/
#define vlc_cond_init( P_THIS, P_COND ) \
__vlc_cond_init( CAST_TO_VLC_OBJECT(P_THIS), P_COND )
/*****************************************************************************
* vlc_cond_signal: start a thread on condition completion
*****************************************************************************/
......@@ -342,7 +356,17 @@ static inline int vlc_cond_signal( vlc_cond_t *p_condvar )
/* Release one waiting thread if one is available. */
/* For this trick to work properly, the vlc_cond_signal must be surrounded
* by a mutex. This will prevent another thread from stealing the signal */
PulseEvent( p_condvar->signal );
if( p_condvar->i_waiting_threads )
{
if( p_condvar->signal )
{
ReleaseSemaphore( p_condvar->semaphore, 1, 0 );
}
else
{
SetEvent( p_condvar->p_events[SIGNAL] );
}
}
return 0;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
......@@ -413,10 +437,22 @@ static inline int vlc_cond_broadcast( vlc_cond_t *p_condvar )
#elif defined( WIN32 )
/* Release all waiting threads. */
while( p_condvar->i_waiting_threads )
if( p_condvar->i_waiting_threads )
{
PulseEvent( p_condvar->signal );
Sleep( 1 ); /* deschedule the current thread */
if( p_condvar->signal )
{
p_condvar->b_broadcast = 1;
/* This call is atomic */
ReleaseSemaphore( p_condvar->semaphore,
p_condvar->i_waiting_threads, 0 );
/* Wait for all threads to get the semaphore */
WaitForSingleObject( p_condvar->signal, INFINITE );
p_condvar->b_broadcast = 0;
}
else
{
SetEvent( p_condvar->p_events[BROADCAST] );
}
}
return 0;
......@@ -497,30 +533,55 @@ static inline int __vlc_cond_wait( char * psz_file, int i_line,
return i_ret;
#elif defined( WIN32 )
/* It is only possible to atomically release the mutex and initiate the
* waiting on WinNT/2K/XP. Win9x doesn't have SignalObjectAndWait().
*/
int i_result;
p_condvar->i_waiting_threads ++;
/* Increase our wait count */
p_condvar->i_waiting_threads++;
if( p_mutex->mutex )
if( p_condvar->signal )
{
p_mutex->SignalObjectAndWait( p_mutex->mutex, p_condvar->signal,
INFINITE, FALSE );
/* It is only possible to atomically release the mutex and initiate the
* waiting on WinNT/2K/XP. Win9x doesn't have SignalObjectAndWait(). */
p_condvar->SignalObjectAndWait( p_mutex->mutex, p_condvar->semaphore,
INFINITE, FALSE );
/* XXX: we should protect i_waiting_threads with a mutex, but
* is it really worth it ? */
p_condvar->i_waiting_threads--;
if( p_condvar->b_broadcast
&& p_condvar->i_waiting_threads == 0 )
{
p_condvar->SignalObjectAndWait( p_condvar->signal, p_mutex->mutex,
INFINITE, FALSE );
}
else
{
/* Just take back the lock */
WaitForSingleObject( p_mutex->mutex, INFINITE );
}
return 0;
}
else
{
/* Release the mutex */
vlc_mutex_unlock( p_mutex );
i_result = WaitForSingleObject( p_condvar->signal, INFINITE);
p_condvar->i_waiting_threads --;
}
int i_ret;
/* Reacquire the mutex before returning. */
vlc_mutex_lock( p_mutex );
/* Release the mutex, wait, and reacquire. */
LeaveCriticalSection( &p_mutex->csection );
i_ret = WaitForMultipleObjects( 2, p_condvar->p_events,
FALSE, INFINITE );
EnterCriticalSection( &p_mutex->csection );
/* Decrease our wait count */
p_condvar->i_waiting_threads--;
return( i_result == WAIT_FAILED );
/* If we are the last waiter and it was a broadcast signal, reset
* the broadcast event. */
if( i_ret == WAIT_OBJECT_0 + BROADCAST
&& p_condvar->i_waiting_threads == 0 )
{
ResetEvent( p_condvar->p_events[BROADCAST] );
}
return( i_ret == WAIT_FAILED );
}
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
......
......@@ -2,7 +2,7 @@
* aout_macosx.c : CoreAudio output plugin
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: aout_macosx.m,v 1.5 2002/06/01 12:32:00 sam Exp $
* $Id: aout_macosx.m,v 1.6 2002/06/08 14:08:46 sam Exp $
*
* Authors: Colin Delacroix <colin@zoy.org>
* Jon Lech Johansen <jon-vl@nanocrew.net>
......@@ -157,7 +157,7 @@ static int aout_Open( aout_thread_t *p_aout )
/* initialize mutex and cond */
vlc_mutex_init( p_aout, &p_aout->p_sys->mutex_lock );
vlc_cond_init( &p_aout->p_sys->cond_sync );
vlc_cond_init( p_aout, &p_aout->p_sys->cond_sync );
/* initialize source stream format */
memcpy( &p_aout->p_sys->s_src_stream_format,
......
......@@ -2,7 +2,7 @@
* vpar_pool.c : management of the pool of decoder threads
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: vpar_pool.c,v 1.11 2002/06/02 09:03:54 sam Exp $
* $Id: vpar_pool.c,v 1.12 2002/06/08 14:08:46 sam Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -57,8 +57,8 @@ void vpar_InitPool( vpar_thread_t * p_vpar )
/* Initialize mutex and cond. */
vlc_mutex_init( p_vpar->p_fifo, &p_vpar->pool.lock );
vlc_cond_init( &p_vpar->pool.wait_empty );
vlc_cond_init( &p_vpar->pool.wait_undecoded );
vlc_cond_init( p_vpar->p_fifo, &p_vpar->pool.wait_empty );
vlc_cond_init( p_vpar->p_fifo, &p_vpar->pool.wait_undecoded );
/* Spawn optional video decoder threads. */
p_vpar->pool.i_smp = 0;
......
......@@ -2,7 +2,7 @@
* audio_output.c : audio output thread
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: audio_output.c,v 1.85 2002/06/01 12:32:01 sam Exp $
* $Id: audio_output.c,v 1.86 2002/06/08 14:08:46 sam Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Cyril Deguet <asmax@via.ecp.fr>
......@@ -154,7 +154,7 @@ static int aout_SpawnThread( aout_thread_t * p_aout )
{
p_aout->fifo[i_index].i_format = AOUT_FIFO_NONE;
vlc_mutex_init( p_aout, &p_aout->fifo[i_index].data_lock );
vlc_cond_init( &p_aout->fifo[i_index].data_wait );
vlc_cond_init( p_aout, &p_aout->fifo[i_index].data_wait );
}
/* Compute the size (in audio units) of the audio output buffer. Although
......
......@@ -4,7 +4,7 @@
* decoders.
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: input.c,v 1.203 2002/06/07 23:53:44 sam Exp $
* $Id: input.c,v 1.204 2002/06/08 14:08:46 sam Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -112,7 +112,7 @@ input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
/* Set locks. */
vlc_mutex_init( p_input, &p_input->stream.stream_lock );
vlc_cond_init( &p_input->stream.stream_wait );
vlc_cond_init( p_input, &p_input->stream.stream_wait );
vlc_mutex_init( p_input, &p_input->stream.control.control_lock );
/* Initialize stream description */
......
......@@ -2,7 +2,7 @@
* input_dec.c: Functions for the management of decoders
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: input_dec.c,v 1.38 2002/06/02 09:03:54 sam Exp $
* $Id: input_dec.c,v 1.39 2002/06/08 14:08:46 sam Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -229,7 +229,7 @@ static decoder_fifo_t * CreateDecoderFifo( input_thread_t * p_input,
/* Initialize the p_fifo structure */
vlc_mutex_init( p_input, &p_fifo->data_lock );
vlc_cond_init( &p_fifo->data_wait );
vlc_cond_init( p_input, &p_fifo->data_wait );
p_es->p_decoder_fifo = p_fifo;
p_fifo->i_id = p_es->i_id;
......
......@@ -268,9 +268,6 @@ static inline const char * module_error( char *psz_buffer )
(p_symbols)->msleep_inner = msleep; \
(p_symbols)->__network_ChannelJoin_inner = __network_ChannelJoin; \
(p_symbols)->__network_ChannelCreate_inner = __network_ChannelCreate; \
(p_symbols)->playlist_Command_inner = playlist_Command; \
(p_symbols)->playlist_Add_inner = playlist_Add; \
(p_symbols)->playlist_Delete_inner = playlist_Delete; \
(p_symbols)->__vout_CreateThread_inner = __vout_CreateThread; \
(p_symbols)->vout_DestroyThread_inner = vout_DestroyThread; \
(p_symbols)->vout_ChromaCmp_inner = vout_ChromaCmp; \
......@@ -301,11 +298,14 @@ static inline const char * module_error( char *psz_buffer )
(p_symbols)->__vlc_object_detach_all_inner = __vlc_object_detach_all; \
(p_symbols)->__vlc_object_attach_inner = __vlc_object_attach; \
(p_symbols)->__vlc_dumpstructure_inner = __vlc_dumpstructure; \
(p_symbols)->playlist_Command_inner = playlist_Command; \
(p_symbols)->playlist_Add_inner = playlist_Add; \
(p_symbols)->playlist_Delete_inner = playlist_Delete; \
(p_symbols)->__vlc_threads_init_inner = __vlc_threads_init; \
(p_symbols)->vlc_threads_end_inner = vlc_threads_end; \
(p_symbols)->__vlc_mutex_init_inner = __vlc_mutex_init; \
(p_symbols)->__vlc_mutex_destroy_inner = __vlc_mutex_destroy; \
(p_symbols)->vlc_cond_init_inner = vlc_cond_init; \
(p_symbols)->__vlc_cond_init_inner = __vlc_cond_init; \
(p_symbols)->__vlc_cond_destroy_inner = __vlc_cond_destroy; \
(p_symbols)->__vlc_thread_create_inner = __vlc_thread_create; \
(p_symbols)->__vlc_thread_ready_inner = __vlc_thread_ready; \
......
......@@ -2,7 +2,7 @@
* objects.c: vlc_object_t handling
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: objects.c,v 1.10 2002/06/07 23:53:44 sam Exp $
* $Id: objects.c,v 1.11 2002/06/08 14:08:46 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -147,7 +147,7 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type )
p_new->i_children = 0;
vlc_mutex_init( p_new, &p_new->object_lock );
vlc_cond_init( &p_new->object_wait );
vlc_cond_init( p_new, &p_new->object_wait );
//msg_Dbg( p_new, "created object" );
......
......@@ -2,7 +2,7 @@
* threads.c : threads implementation for the VideoLAN client
*****************************************************************************
* Copyright (C) 1999, 2000, 2001, 2002 VideoLAN
* $Id: threads.c,v 1.6 2002/06/04 00:11:12 sam Exp $
* $Id: threads.c,v 1.7 2002/06/08 14:08:46 sam Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
......@@ -176,13 +176,12 @@ int __vlc_mutex_init( vlc_object_t *p_this, vlc_mutex_t *p_mutex )
{
/* We are running on NT/2K/XP, we can use SignalObjectAndWait */
p_mutex->mutex = CreateMutex( 0, FALSE, 0 );
p_mutex->SignalObjectAndWait = p_this->p_vlc->SignalObjectAndWait;
return ( p_mutex->mutex ? 0 : 1 );
}
else
{
InitializeCriticalSection( &p_mutex->csection );
p_mutex->mutex = NULL;
InitializeCriticalSection( &p_mutex->csection );
return 0;
}
......@@ -278,7 +277,7 @@ int __vlc_mutex_destroy( char * psz_file, int i_line, vlc_mutex_t *p_mutex )
/*****************************************************************************
* vlc_cond_init: initialize a condition
*****************************************************************************/
int vlc_cond_init( vlc_cond_t *p_condvar )
int __vlc_cond_init( vlc_object_t *p_this, vlc_cond_t *p_condvar )
{
#if defined( PTH_INIT_IN_PTH_H )
return pth_cond_init( p_condvar );
......@@ -288,16 +287,32 @@ int vlc_cond_init( vlc_cond_t *p_condvar )
return ( *p_condvar == NULL ) ? errno : 0;
#elif defined( WIN32 )
/* initialise counter */
/* Initialize counter */
p_condvar->i_waiting_threads = 0;
/* Create an auto-reset event. */
p_condvar->signal = CreateEvent( NULL, /* no security */
FALSE, /* auto-reset event */
FALSE, /* non-signaled initially */
NULL ); /* unnamed */
if( (GetVersion() < 0x80000000) && !p_this->p_vlc->b_fast_pthread )
{
/* Create an auto-reset event and a semaphore. */
p_condvar->signal = CreateEvent( NULL, FALSE, FALSE, NULL );
p_condvar->semaphore = CreateSemaphore( NULL, 0, 0x7fffffff, NULL );
p_condvar->b_broadcast = 0;
/* We are running on NT/2K/XP, we can use SignalObjectAndWait */
p_condvar->SignalObjectAndWait = p_this->p_vlc->SignalObjectAndWait;
return !p_condvar->signal || !p_condvar->semaphore;
}
else
{
p_condvar->signal = NULL;
return( !p_condvar->signal );
/* Create an auto-reset event and a manual-reset event. */
p_condvar->p_events[SIGNAL] = CreateEvent( NULL, FALSE, FALSE, NULL );
p_condvar->p_events[BROADCAST] = CreateEvent( NULL, TRUE, FALSE, NULL );
return !p_condvar->p_events[SIGNAL] || !p_condvar->p_events[BROADCAST];
}
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
return pthread_cond_init( p_condvar, NULL );
......@@ -341,7 +356,16 @@ int __vlc_cond_destroy( char * psz_file, int i_line, vlc_cond_t *p_condvar )
return st_cond_destroy( *p_condvar );
#elif defined( WIN32 )
return( !CloseHandle( p_condvar->signal ) );
if( p_condvar->signal )
{
return !CloseHandle( p_condvar->signal )
|| !CloseHandle( p_condvar->semaphore );
}
else
{
return !CloseHandle( p_condvar->p_events[SIGNAL] )
|| !CloseHandle( p_condvar->p_events[BROADCAST] );
}
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
int i_result = pthread_cond_destroy( p_condvar );
......@@ -381,7 +405,7 @@ int __vlc_thread_create( vlc_object_t *p_this, char * psz_file, int i_line,
wrapper.p_data = (void *)p_this;
getitimer( ITIMER_PROF, &wrapper.itimer );
vlc_mutex_init( p_this, &wrapper.lock );
vlc_cond_init( &wrapper.wait );
vlc_cond_init( p_this, &wrapper.wait );
vlc_mutex_lock( &wrapper.lock );
/* Alter user-passed data so that we call the wrapper instead
......@@ -438,17 +462,17 @@ int __vlc_thread_create( vlc_object_t *p_this, char * psz_file, int i_line,
if( i_ret == 0 )
{
msg_Dbg( p_this, "thread %d (%s) created (%s:%d)",
p_this->thread_id, psz_name, psz_file, i_line );
p_this->b_thread = 1;
if( b_wait )
{
msg_Dbg( p_this, "waiting for thread completion" );
vlc_cond_wait( &p_this->object_wait, &p_this->object_lock );
}
p_this->b_thread = 1;
msg_Dbg( p_this, "thread %d (%s) created (%s:%d)",
p_this->thread_id, psz_name, psz_file, i_line );
vlc_mutex_unlock( &p_this->object_lock );
}
else
......
......@@ -2,7 +2,7 @@
* win32_specific.c: Win32 specific features
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: win32_specific.c,v 1.11 2002/06/02 14:26:16 gbazin Exp $
* $Id: win32_specific.c,v 1.12 2002/06/08 14:08:46 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Gildas Bazin <gbazin@netcourrier.com>
......@@ -60,7 +60,7 @@ void system_Init( vlc_t *p_this, int *pi_argc, char *ppsz_argv[] )
*****************************************************************************/
void system_Configure( vlc_t *p_this )
{
p_this->p_vlc->b_fast_pthread = config_GetInt( p_this, "fast_pthread" );
p_this->p_vlc->b_fast_pthread = config_GetInt( p_this, "fast-pthread" );
}
/*****************************************************************************
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment