Commit 7d2f6de5 authored by Christophe Massiot's avatar Christophe Massiot

* ./bootstrap : Fixed an issue with old shell versions

* ALL : Added a priority argument to vlc_thread_create(), so that audio
and input threads can run with a higher real-time priority, on systems
allowing you to use priorities.
parent b3c41d79
#! /bin/sh
## bootstrap.sh file for vlc, the VideoLAN Client
## $Id: bootstrap,v 1.12 2002/08/28 19:48:16 massiot Exp $
## $Id: bootstrap,v 1.13 2002/08/29 23:53:22 massiot Exp $
##
## Authors: Samuel Hocevar <sam@zoy.org>
###
### get a sane environment
###
export LANG=C
LANG=C
export LANG
###
### argument check
......
......@@ -12,15 +12,18 @@ MAX_TEX_RECURSION=4
#HTML_SS=/usr/lib/sgml/stylesheets/nwalsh-modular/html/docbook.dsl
#PRINT_SS=/usr/lib/sgml/stylesheets/nwalsh-modular/print/docbook.dsl
#JADE=jade
#TYPE=sgml
# For Mac OS X :
#XML_DECL=/usr/lib/sgml/declaration/xml.decl
XML_DECL=/sw/share/sgml/dsssl/docbook-dsssl-nwalsh/dtds/decls/xml.dcl
HTML_SS=/sw/share/sgml/dsssl/docbook-dsssl-nwalsh/html/docbook.dsl
PRINT_SS=/sw/share/sgml/dsssl/docbook-dsssl-nwalsh/print/docbook.dsl
JADE=openjade
TYPE=sgml
all: manual
#JADE=jade
JADE=openjade
manual: manual.txt manual.ps manual.html
......@@ -30,7 +33,7 @@ manual.tex: audio_output.xml debugging.xml decoders.xml gfdl.xml glossary.xml hi
# No it's not a joke
manual.html: audio_output.xml debugging.xml decoders.xml gfdl.xml glossary.xml history.xml input.xml interface.xml manual.xml overview.xml ports.xml video_output.xml
$(JADE) -t sgml -V %section-autolabel% -V nochunks \
$(JADE) -t $(TYPE) -V %section-autolabel% -V nochunks \
-d $(HTML_SS) $(XML_DECL) manual.xml > $@
manual.dvi: manual.tex modules.eps ps.eps stream.eps ts.eps
......@@ -42,7 +45,7 @@ manual.ps: manual.dvi
dvips -f $< > $@
manual.txt: audio_output.xml debugging.xml decoders.xml gfdl.xml glossary.xml history.xml input.xml interface.xml manual.xml overview.xml ports.xml video_output.xml
$(JADE) -t sgml -V nochunks -d $(HTML_SS) $(XML_DECL) manual.xml > dump.html
$(JADE) -t $(TYPE) -V nochunks -d $(HTML_SS) $(XML_DECL) manual.xml > dump.html
lynx -force_html -dump dump.html > $@
-rm -f dump.html
......
<chapter> <title> The audio output layer </title>
<sect1> <title> Audio output overview </title>
<para>
This chapter documents the audio output layer known under the "audio output 3" codename. It has first been released with VLC version 0.5.0. Previous versions use an antic API, which is no longer documented nor supported. You definitely should write new code only for aout3 and later.
</para>
<para>
The audio output's main purpose is to take sound samples from one or several decoders (called "input streams" in this chapter), to mix them and write them to an output device (called "output stream"). During this process, transformations may be needed or asked by the user, and they will be performed by audio filters.
</para>
<para>
(insert here a schematic of the data flow in aout3)
</para>
<sect2> <title> Typical runcourse </title>
<para>
The input spawns a new decoder audio decoder, say for instance an A/52 decoder. The A/52 decoder parses the sync info for format information, and creates a new aout "input stream" whith aout_InputNew().
</para>
</sect2>
</sect1>
<sect1> <title> API for the decoders </title>
</sect1>
<sect1> <title> API for the output module </title>
</sect1>
<sect1> <title> Writing an audio filter </title>
</sect1>
<sect1> <title> Writing an audio mixer </title>
</sect1>
<sect1> <title> Data exchanges between a decoder and the audio output
</title>
......
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE book PUBLIC "-//Norman Walsh//DTD DocBk XML V3.1.3//EN" "docbookx.dtd"
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "/sw/share/xml/dtd/docbookx/4.1.2/docbookx.dtd"
[
<!ENTITY glossary SYSTEM "glossary.xml">
<!ENTITY overview SYSTEM "overview.xml">
......@@ -57,7 +57,7 @@
<orgname> VideoLAN project </orgname>
</affiliation>
</collab>
<pubdate> $Id: manual.xml,v 1.2 2001/11/13 12:09:17 henri Exp $ </pubdate>
<pubdate> $Id: manual.xml,v 1.3 2002/08/29 23:53:22 massiot Exp $ </pubdate>
<copyright> <year> 2001 </year>
<holder> Christophe Massiot, for IDEALX S.A.S. </holder>
</copyright>
......
/*****************************************************************************
* input_iovec.h: iovec structure
*****************************************************************************
* Copyright (C) 2001 VideoLAN
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Jon Lech Johansen <jon-vl@nanocrew.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* iovec structure: vectored data entry
*****************************************************************************/
struct iovec
{
void *iov_base; /* Pointer to data. */
size_t iov_len; /* Length of data. */
};
/*****************************************************************************
* readv_*: readv() replacements for iovec-impaired C libraries
*****************************************************************************/
#if defined( WIN32 )
static inline int readv( int i_fd, struct iovec *p_iovec, int i_count )
{
int i_index, i_len, i_total = 0;
unsigned char *p_base;
int i_bytes;
for( i_index = i_count; i_index; i_index-- )
{
i_len = p_iovec->iov_len;
p_base = p_iovec->iov_base;
/* Loop is unrolled one time to spare the (i_bytes <= 0) test */
if( i_len > 0 )
{
i_bytes = read( i_fd, p_base, i_len );
if( i_bytes < 0 )
{
/* One of the reads failed, too bad.
We won't even bother returning the reads that went ok,
and as in the posix spec the file postition is left
unspecified after a failure */
return -1;
}
i_total += i_bytes;
if( i_bytes != i_len )
{
/* we reached the end of the file or a signal interrupted
the read */
return i_total;
}
}
p_iovec++;
}
return i_total;
}
#endif /* WIN32 */
......@@ -3,7 +3,7 @@
* Collection of useful common types and macros definitions
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: vlc_common.h,v 1.24 2002/08/26 23:36:20 sam Exp $
* $Id: vlc_common.h,v 1.25 2002/08/29 23:53:22 massiot Exp $
*
* Authors: Samuel Hocevar <sam@via.ecp.fr>
* Vincent Seguin <seguin@via.ecp.fr>
......@@ -493,6 +493,7 @@ typedef __int64 off_t;
#include "vlc_symbols.h"
#include "os_specific.h"
#include "vlc_messages.h"
#include "vlc_threads_funcs.h"
#include "mtime.h"
#include "modules.h"
#include "main.h"
......
......@@ -34,7 +34,7 @@ struct module_symbols_t
int (* __vlc_cond_init_inner) ( vlc_object_t *, vlc_cond_t * ) ;
int (* __vlc_mutex_destroy_inner) ( char *, int, vlc_mutex_t * ) ;
int (* __vlc_mutex_init_inner) ( vlc_object_t *, vlc_mutex_t * ) ;
int (* __vlc_thread_create_inner) ( vlc_object_t *, char *, int, char *, void * ( * ) ( void * ), vlc_bool_t ) ;
int (* __vlc_thread_create_inner) ( vlc_object_t *, char *, int, char *, void * ( * ) ( void * ), int, vlc_bool_t ) ;
int (* __vlc_threads_end_inner) ( vlc_object_t * ) ;
int (* __vlc_threads_init_inner) ( vlc_object_t * ) ;
int (* input_AccessInit_inner) ( input_thread_t * ) ;
......
/*****************************************************************************
* threads.h : threads implementation for the VideoLAN client
* This header provides a portable threads implementation.
* vlc_threads.h : threads implementation for the VideoLAN client
* This header provides portable declarations for mutexes & conditions
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: vlc_threads.h,v 1.9 2002/08/08 00:35:10 sam Exp $
* Copyright (C) 1999, 2002 VideoLAN
* $Id: vlc_threads.h,v 1.10 2002/08/29 23:53:22 massiot Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr>
* Gildas Bazin <gbazin@netcourrier.com>
* Christophe Massiot <massiot@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -63,29 +64,28 @@
/*****************************************************************************
* Constants
*****************************************************************************
* These constants are used by all threads in *_CreateThread() and
* *_DestroyThreads() functions. Since those calls are non-blocking, an integer
* value is used as a shared flag to represent the status of the thread.
*****************************************************************************/
/* Void status - this value can be used to make sure no operation is currently
* in progress on the concerned thread in an array of recorded threads */
#define THREAD_NOP 0 /* nothing happened */
/* Thread priorities */
#ifdef SYS_DARWIN
# define VLC_THREAD_PRIORITY_LOW 10
# define VLC_THREAD_PRIORITY_INPUT 37
# define VLC_THREAD_PRIORITY_AUDIO 38
# define VLC_THREAD_PRIORITY_OUTPUT 38
/* Creation status */
#define THREAD_CREATE 10 /* thread is initializing */
#define THREAD_START 11 /* thread has forked */
#define THREAD_READY 19 /* thread is ready */
#elif defined(WIN32)
# define VLC_THREAD_PRIORITY_LOW 0
# define VLC_THREAD_PRIORITY_INPUT THREAD_PRIORITY_ABOVE_NORMAL
# define VLC_THREAD_PRIORITY_AUDIO THREAD_PRIORITY_ABOVE_NORMAL
# define VLC_THREAD_PRIORITY_OUTPUT THREAD_PRIORITY_ABOVE_NORMAL
/* Destructions status */
#define THREAD_DESTROY 20 /* destruction order has been sent */
#define THREAD_END 21 /* destruction order has been received */
#define THREAD_OVER 29 /* thread does not exist any more */
#else
# define VLC_THREAD_PRIORITY_LOW 0
# define VLC_THREAD_PRIORITY_INPUT 0
# define VLC_THREAD_PRIORITY_AUDIO 0
# define VLC_THREAD_PRIORITY_OUTPUT 0
/* Error status */
#define THREAD_ERROR 30 /* an error occured */
#define THREAD_FATAL 31 /* an fatal error occured - program must end */
#endif
/*****************************************************************************
* Type definitions
......@@ -93,13 +93,29 @@
#if defined( PTH_INIT_IN_PTH_H )
typedef pth_t vlc_thread_t;
typedef pth_mutex_t vlc_mutex_t;
typedef pth_cond_t vlc_cond_t;
typedef struct
{
pth_mutex_t mutex;
vlc_object_t * p_this;
} vlc_mutex_t;
typedef struct
{
pth_cond_t cond;
vlc_object_t * p_this;
} vlc_cond_t;
#elif defined( ST_INIT_IN_ST_H )
typedef st_thread_t * vlc_thread_t;
typedef st_mutex_t * vlc_mutex_t;
typedef st_cond_t * vlc_cond_t;
typedef struct
{
st_mutex_t * mutex;
vlc_object_t * p_this;
} vlc_mutex_t;
typedef struct
{
st_cond_t * cond;
vlc_object_t * p_this;
} vlc_cond_t;
#elif defined( WIN32 )
typedef HANDLE vlc_thread_t;
......@@ -112,6 +128,8 @@ typedef struct
HANDLE mutex;
/* Win95/98/ME implementation */
CRITICAL_SECTION csection;
vlc_object_t * p_this;
} vlc_mutex_t;
typedef struct
......@@ -124,15 +142,25 @@ typedef struct
HANDLE semaphore;
CRITICAL_SECTION csection;
int i_win9x_cv;
vlc_object_t * p_this;
} vlc_cond_t;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
typedef pthread_t vlc_thread_t;
typedef pthread_mutex_t vlc_mutex_t;
typedef pthread_cond_t vlc_cond_t;
typedef pthread_t vlc_thread_t;
typedef struct
{
pthread_mutex_t mutex;
vlc_object_t * p_this;
} vlc_mutex_t;
typedef struct
{
pthread_cond_t cond;
vlc_object_t * p_this;
} vlc_cond_t;
#elif defined( HAVE_CTHREADS_H )
typedef cthread_t vlc_thread_t;
typedef cthread_t vlc_thread_t;
/* Those structs are the ones defined in /include/cthreads.h but we need
* to handle (&foo) where foo is a (mutex_t) while they handle (foo) where
......@@ -143,6 +171,8 @@ typedef struct
spin_lock_t lock;
char *name;
struct cthread_queue queue;
vlc_object_t * p_this;
} vlc_mutex_t;
typedef struct
......@@ -151,6 +181,8 @@ typedef struct
struct cthread_queue queue;
char *name;
struct cond_imp *implications;
vlc_object_t * p_this;
} vlc_cond_t;
#elif defined( HAVE_KERNEL_SCHEDULER_H )
......@@ -164,596 +196,17 @@ typedef struct
{
int32 init;
sem_id lock;
vlc_object_t * p_this;
} vlc_mutex_t;
typedef struct
{
int32 init;
thread_id thread;
} vlc_cond_t;
#endif
/*****************************************************************************
* Function definitions
*****************************************************************************/
VLC_EXPORT( int, __vlc_threads_init, ( vlc_object_t * ) );
VLC_EXPORT( int, __vlc_threads_end, ( vlc_object_t * ) );
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_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 * ) );
VLC_EXPORT( void, __vlc_thread_join, ( vlc_object_t *, char *, int ) );
/*****************************************************************************
* vlc_threads_init: initialize threads system
*****************************************************************************/
#define vlc_threads_init( P_THIS ) \
__vlc_threads_init( VLC_OBJECT(P_THIS) )
/*****************************************************************************
* vlc_threads_end: deinitialize threads system
*****************************************************************************/
#define vlc_threads_end( P_THIS ) \
__vlc_threads_end( VLC_OBJECT(P_THIS) )
/*****************************************************************************
* vlc_mutex_init: initialize a mutex
*****************************************************************************/
#define vlc_mutex_init( P_THIS, P_MUTEX ) \
__vlc_mutex_init( VLC_OBJECT(P_THIS), P_MUTEX )
/*****************************************************************************
* vlc_mutex_lock: lock a mutex
*****************************************************************************/
#ifdef DEBUG
# define vlc_mutex_lock( P_MUTEX ) \
__vlc_mutex_lock( __FILE__, __LINE__, P_MUTEX )
#else
# define vlc_mutex_lock( P_MUTEX ) \
__vlc_mutex_lock( "(unknown)", 0, P_MUTEX )
#endif
static inline int __vlc_mutex_lock( char * psz_file, int i_line,
vlc_mutex_t *p_mutex )
{
#if defined( PTH_INIT_IN_PTH_H )
return pth_mutex_acquire( p_mutex, TRUE, NULL );
#elif defined( ST_INIT_IN_ST_H )
return st_mutex_lock( *p_mutex );
#elif defined( WIN32 )
if( p_mutex->mutex )
{
WaitForSingleObject( p_mutex->mutex, INFINITE );
}
else
{
EnterCriticalSection( &p_mutex->csection );
}
return 0;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
int i_return = pthread_mutex_lock( p_mutex );
if( i_return )
{
#if 0
msg_Err( "thread %d: mutex_lock failed at %s:%d (%s)",
pthread_self(), psz_file, i_line, strerror(i_return) );
#endif
}
return i_return;
#elif defined( HAVE_CTHREADS_H )
mutex_lock( p_mutex );
return 0;
#elif defined( HAVE_KERNEL_SCHEDULER_H )
status_t err;
if( !p_mutex )
{
return B_BAD_VALUE;
}
if( p_mutex->init < 2000 )
{
return B_NO_INIT;
}
err = acquire_sem( p_mutex->lock );
return err;
#endif
}
/*****************************************************************************
* vlc_mutex_unlock: unlock a mutex
*****************************************************************************/
#ifdef DEBUG
# define vlc_mutex_unlock( P_MUTEX ) \
__vlc_mutex_unlock( __FILE__, __LINE__, P_MUTEX )
#else
# define vlc_mutex_unlock( P_MUTEX ) \
__vlc_mutex_unlock( "(unknown)", 0, P_MUTEX )
#endif
static inline int __vlc_mutex_unlock( char * psz_file, int i_line,
vlc_mutex_t *p_mutex )
{
#if defined( PTH_INIT_IN_PTH_H )
return pth_mutex_release( p_mutex );
#elif defined( ST_INIT_IN_ST_H )
return st_mutex_unlock( *p_mutex );
#elif defined( WIN32 )
if( p_mutex->mutex )
{
ReleaseMutex( p_mutex->mutex );
}
else
{
LeaveCriticalSection( &p_mutex->csection );
}
return 0;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
int i_return = pthread_mutex_unlock( p_mutex );
if( i_return )
{
#if 0
msg_Err( "thread %d: mutex_unlock failed at %s:%d (%s)",
pthread_self(), psz_file, i_line, strerror(i_return) );
#endif
}
return i_return;
#elif defined( HAVE_CTHREADS_H )
mutex_unlock( p_mutex );
return 0;
#elif defined( HAVE_KERNEL_SCHEDULER_H )
if( !p_mutex)
{
return B_BAD_VALUE;
}
if( p_mutex->init < 2000 )
{
return B_NO_INIT;
}
release_sem( p_mutex->lock );
return B_OK;
#endif
}
/*****************************************************************************
* vlc_mutex_destroy: destroy a mutex
*****************************************************************************/
#ifdef DEBUG
# define vlc_mutex_destroy( P_MUTEX ) \
__vlc_mutex_destroy( __FILE__, __LINE__, P_MUTEX )
#else
# define vlc_mutex_destroy( P_MUTEX ) \
__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( VLC_OBJECT(P_THIS), P_COND )
/*****************************************************************************
* vlc_cond_signal: start a thread on condition completion
*****************************************************************************/
static inline int vlc_cond_signal( vlc_cond_t *p_condvar )
{
#if defined( PTH_INIT_IN_PTH_H )
return pth_cond_notify( p_condvar, FALSE );
#elif defined( ST_INIT_IN_ST_H )
return st_cond_signal( *p_condvar );
#elif defined( WIN32 )
/* 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 */
if( !p_condvar->semaphore )
{
PulseEvent( p_condvar->event );
}
else if( p_condvar->i_win9x_cv == 1 )
{
/* Wait for the gate to be open */
WaitForSingleObject( p_condvar->event, INFINITE );
if( p_condvar->i_waiting_threads )
{
/* Using a semaphore exposes us to a race condition. It is
* possible for another thread to start waiting on the semaphore
* just after we signaled it and thus steal the signal.
* We have to prevent new threads from entering the cond_wait(). */
ResetEvent( p_condvar->event );
/* A semaphore is used here because Win9x doesn't have
* SignalObjectAndWait() and thus a race condition exists
* during the time we release the mutex and the time we start
* waiting on the event (more precisely, the signal can sometimes
* be missed by the waiting thread if we use PulseEvent()). */
ReleaseSemaphore( p_condvar->semaphore, 1, 0 );
}
}
else
{
if( p_condvar->i_waiting_threads )
{
ReleaseSemaphore( p_condvar->semaphore, 1, 0 );
/* Wait for the last thread to be awakened */
WaitForSingleObject( p_condvar->event, INFINITE );
}
}
return 0;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
return pthread_cond_signal( p_condvar );
#elif defined( HAVE_CTHREADS_H )
/* condition_signal() */
if ( p_condvar->queue.head || p_condvar->implications )
{
cond_signal( (condition_t)p_condvar );
}
return 0;
#elif defined( HAVE_KERNEL_SCHEDULER_H )
if( !p_condvar )
{
return B_BAD_VALUE;
}
if( p_condvar->init < 2000 )
{
return B_NO_INIT;
}
while( p_condvar->thread != -1 )
{
thread_info info;
if( get_thread_info(p_condvar->thread, &info) == B_BAD_VALUE )
{
return 0;
}
if( info.state != B_THREAD_SUSPENDED )
{
/* The waiting thread is not suspended so it could
* have been interrupted beetwen the unlock and the
* suspend_thread line. That is why we sleep a little
* before retesting p_condver->thread. */
snooze( 10000 );
}
else
{
/* Ok, we have to wake up that thread */
resume_thread( p_condvar->thread );
return 0;
}
}
return 0;
#endif
}
/*****************************************************************************
* vlc_cond_broadcast: start all threads waiting on condition completion
*****************************************************************************/
/*
* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
* Only works with pthreads, you need to adapt it for others
* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
*/
static inline int vlc_cond_broadcast( vlc_cond_t *p_condvar )
{
#if defined( PTH_INIT_IN_PTH_H )
return pth_cond_notify( p_condvar, FALSE );
#elif defined( ST_INIT_IN_ST_H )
return st_cond_broadcast( p_condvar );
#elif defined( WIN32 )
/* Release all waiting threads. */
int i;
if( !p_condvar->semaphore )
for( i = p_condvar->i_waiting_threads; i > 0; i-- )
PulseEvent( p_condvar->event );
else if( p_condvar->i_win9x_cv == 1 )
{
/* Wait for the gate to be open */
WaitForSingleObject( p_condvar->event, INFINITE );
if( p_condvar->i_waiting_threads )
{
/* close gate */
ResetEvent( p_condvar->event );
ReleaseSemaphore( p_condvar->semaphore,
p_condvar->i_waiting_threads, 0 );
}
}
else
{
if( p_condvar->i_waiting_threads )
{
ReleaseSemaphore( p_condvar->semaphore,
p_condvar->i_waiting_threads, 0 );
/* Wait for the last thread to be awakened */
WaitForSingleObject( p_condvar->event, INFINITE );
}
}
return 0;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
return pthread_cond_broadcast( p_condvar );
#elif defined( HAVE_CTHREADS_H )
/* condition_signal() */
if ( p_condvar->queue.head || p_condvar->implications )
{
cond_signal( (condition_t)p_condvar );
}
return 0;
#elif defined( HAVE_KERNEL_SCHEDULER_H )
if( !p_condvar )
{
return B_BAD_VALUE;
}
if( p_condvar->init < 2000 )
{
return B_NO_INIT;
}
while( p_condvar->thread != -1 )
{
thread_info info;
if( get_thread_info(p_condvar->thread, &info) == B_BAD_VALUE )
{
return 0;
}
if( info.state != B_THREAD_SUSPENDED )
{
/* The waiting thread is not suspended so it could
* have been interrupted beetwen the unlock and the
* suspend_thread line. That is why we sleep a little
* before retesting p_condver->thread. */
snooze( 10000 );
}
else
{
/* Ok, we have to wake up that thread */
resume_thread( p_condvar->thread );
return 0;
}
}
return 0;
#endif
}
/*****************************************************************************
* vlc_cond_wait: wait until condition completion
*****************************************************************************/
#ifdef DEBUG
# define vlc_cond_wait( P_COND, P_MUTEX ) \
__vlc_cond_wait( __FILE__, __LINE__, P_COND, P_MUTEX )
#else
# define vlc_cond_wait( P_COND, P_MUTEX ) \
__vlc_cond_wait( "(unknown)", 0, P_COND, P_MUTEX )
#endif
static inline int __vlc_cond_wait( char * psz_file, int i_line,
vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex )
{
#if defined( PTH_INIT_IN_PTH_H )
return pth_cond_await( p_condvar, p_mutex, NULL );
#elif defined( ST_INIT_IN_ST_H )
int i_ret;
st_mutex_unlock( *p_mutex );
i_ret = st_cond_wait( *p_condvar );
st_mutex_lock( *p_mutex );
return i_ret;
#elif defined( WIN32 )
if( !p_condvar->semaphore )
{
/* Increase our wait count */
p_condvar->i_waiting_threads++;
if( p_condvar->SignalObjectAndWait && p_mutex->mutex )
/* 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->event,
INFINITE, FALSE );
else
{
LeaveCriticalSection( &p_mutex->csection );
WaitForSingleObject( p_condvar->event, INFINITE );
}
p_condvar->i_waiting_threads--;
}
else if( p_condvar->i_win9x_cv == 1 )
{
int i_waiting_threads;
/* Wait for the gate to be open */
WaitForSingleObject( p_condvar->event, INFINITE );
/* Increase our wait count */
p_condvar->i_waiting_threads++;
LeaveCriticalSection( &p_mutex->csection );
WaitForSingleObject( p_condvar->semaphore, INFINITE );
/* Decrement and test must be atomic */
EnterCriticalSection( &p_condvar->csection );
/* Decrease our wait count */
i_waiting_threads = --p_condvar->i_waiting_threads;
LeaveCriticalSection( &p_condvar->csection );
/* Reopen the gate if we were the last waiting thread */
if( !i_waiting_threads )
SetEvent( p_condvar->event );
}
else
{
int i_waiting_threads;
/* Increase our wait count */
p_condvar->i_waiting_threads++;
LeaveCriticalSection( &p_mutex->csection );
WaitForSingleObject( p_condvar->semaphore, INFINITE );
/* Decrement and test must be atomic */
EnterCriticalSection( &p_condvar->csection );
/* Decrease our wait count */
i_waiting_threads = --p_condvar->i_waiting_threads;
LeaveCriticalSection( &p_condvar->csection );
/* Signal that the last waiting thread just went through */
if( !i_waiting_threads )
SetEvent( p_condvar->event );
}
/* Reacquire the mutex before returning. */
vlc_mutex_lock( p_mutex );
return 0;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
# ifdef DEBUG
/* In debug mode, timeout */
struct timeval now;
struct timespec timeout;
int i_result;
for( ; ; )
{
gettimeofday( &now, NULL );
timeout.tv_sec = now.tv_sec + THREAD_COND_TIMEOUT;
timeout.tv_nsec = now.tv_usec * 1000;
i_result = pthread_cond_timedwait( p_condvar, p_mutex, &timeout );
if( i_result == ETIMEDOUT )
{
#if 0
msg_Warn( "thread %d: possible deadlock detected "
"in cond_wait at %s:%d (%s)", pthread_self(),
psz_file, i_line, strerror(i_result) );
#endif
continue;
}
if( i_result )
{
#if 0
msg_Err( "thread %d: cond_wait failed at %s:%d (%s)",
pthread_self(), psz_file, i_line, strerror(i_result) );
#endif
}
return( i_result );
}
# else
return pthread_cond_wait( p_condvar, p_mutex );
# endif
#elif defined( HAVE_CTHREADS_H )
condition_wait( (condition_t)p_condvar, (mutex_t)p_mutex );
return 0;
#elif defined( HAVE_KERNEL_SCHEDULER_H )
if( !p_condvar )
{
return B_BAD_VALUE;
}
if( !p_mutex )
{
return B_BAD_VALUE;
}
if( p_condvar->init < 2000 )
{
return B_NO_INIT;
}
/* The p_condvar->thread var is initialized before the unlock because
* it enables to identify when the thread is interrupted beetwen the
* unlock line and the suspend_thread line */
p_condvar->thread = find_thread( NULL );
vlc_mutex_unlock( p_mutex );
suspend_thread( p_condvar->thread );
p_condvar->thread = -1;
vlc_mutex_lock( p_mutex );
return 0;
vlc_object_t * p_this;
} vlc_cond_t;
#endif
}
/*****************************************************************************
* vlc_cond_destroy: destroy a condition
*****************************************************************************/
#ifdef DEBUG
# define vlc_cond_destroy( P_COND ) \
__vlc_cond_destroy( __FILE__, __LINE__, P_COND )
#else
# define vlc_cond_destroy( P_COND ) \
__vlc_cond_destroy( "(unknown)", 0, P_COND )
#endif
/*****************************************************************************
* vlc_thread_create: create a thread
*****************************************************************************/
# define vlc_thread_create( P_THIS, PSZ_NAME, FUNC, WAIT ) \
__vlc_thread_create( VLC_OBJECT(P_THIS), __FILE__, __LINE__, PSZ_NAME, (void * ( * ) ( void * ))FUNC, WAIT )
/*****************************************************************************
* vlc_thread_ready: tell the parent thread we were successfully spawned
*****************************************************************************/
# define vlc_thread_ready( P_THIS ) \
__vlc_thread_ready( VLC_OBJECT(P_THIS) )
/*****************************************************************************
* vlc_thread_join: wait until a thread exits
*****************************************************************************/
#ifdef DEBUG
# define vlc_thread_join( P_THIS ) \
__vlc_thread_join( VLC_OBJECT(P_THIS), __FILE__, __LINE__ )
#else
# define vlc_thread_join( P_THIS ) \
__vlc_thread_join( VLC_OBJECT(P_THIS), "(unknown)", 0 )
#endif
/*****************************************************************************
* vlc_threads_funcs.h : threads implementation for the VideoLAN client
* This header provides a portable threads implementation.
*****************************************************************************
* Copyright (C) 1999, 2002 VideoLAN
* $Id: vlc_threads_funcs.h,v 1.1 2002/08/29 23:53:22 massiot Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr>
* Gildas Bazin <gbazin@netcourrier.com>
* Christophe Massiot <massiot@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Function definitions
*****************************************************************************/
VLC_EXPORT( int, __vlc_threads_init, ( vlc_object_t * ) );
VLC_EXPORT( int, __vlc_threads_end, ( vlc_object_t * ) );
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_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 * ), int, vlc_bool_t ) );
VLC_EXPORT( void, __vlc_thread_ready, ( vlc_object_t * ) );
VLC_EXPORT( void, __vlc_thread_join, ( vlc_object_t *, char *, int ) );
/*****************************************************************************
* vlc_threads_init: initialize threads system
*****************************************************************************/
#define vlc_threads_init( P_THIS ) \
__vlc_threads_init( VLC_OBJECT(P_THIS) )
/*****************************************************************************
* vlc_threads_end: deinitialize threads system
*****************************************************************************/
#define vlc_threads_end( P_THIS ) \
__vlc_threads_end( VLC_OBJECT(P_THIS) )
/*****************************************************************************
* vlc_mutex_init: initialize a mutex
*****************************************************************************/
#define vlc_mutex_init( P_THIS, P_MUTEX ) \
__vlc_mutex_init( VLC_OBJECT(P_THIS), P_MUTEX )
/*****************************************************************************
* vlc_mutex_lock: lock a mutex
*****************************************************************************/
#define vlc_mutex_lock( P_MUTEX ) \
__vlc_mutex_lock( __FILE__, __LINE__, P_MUTEX )
static inline int __vlc_mutex_lock( char * psz_file, int i_line,
vlc_mutex_t * p_mutex )
{
int i_result;
/* In case of error : */
int i_thread = -1;
const char * psz_error = "";
#if defined( PTH_INIT_IN_PTH_H )
i_result = pth_mutex_acquire( &p_mutex->mutex, TRUE, NULL );
#elif defined( ST_INIT_IN_ST_H )
i_result = st_mutex_lock( *p_mutex->mutex );
#elif defined( WIN32 )
if( p_mutex->mutex )
{
WaitForSingleObject( p_mutex->mutex, INFINITE );
}
else
{
EnterCriticalSection( &p_mutex->csection );
}
return 0;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
i_result = pthread_mutex_lock( &p_mutex->mutex );
if ( i_result )
{
i_thread = (int)pthread_self();
psz_error = strerror(i_result);
}
#elif defined( HAVE_CTHREADS_H )
mutex_lock( p_mutex->mutex );
return 0;
#elif defined( HAVE_KERNEL_SCHEDULER_H )
if( p_mutex == NULL )
{
i_result = B_BAD_VALUE;
}
else if( p_mutex->init < 2000 )
{
i_result = B_NO_INIT;
}
else
{
i_result = acquire_sem( p_mutex->lock );
}
#endif
if( i_result )
{
msg_Err( p_mutex->p_this,
"thread %d: mutex_lock failed at %s:%d (%d:%s)",
i_thread, psz_file, i_line, i_result, psz_error );
}
return i_result;
}
/*****************************************************************************
* vlc_mutex_unlock: unlock a mutex
*****************************************************************************/
#define vlc_mutex_unlock( P_MUTEX ) \
__vlc_mutex_unlock( __FILE__, __LINE__, P_MUTEX )
static inline int __vlc_mutex_unlock( char * psz_file, int i_line,
vlc_mutex_t *p_mutex )
{
int i_result;
/* In case of error : */
int i_thread = -1;
const char * psz_error = "";
#if defined( PTH_INIT_IN_PTH_H )
i_result = pth_mutex_release( &p_mutex->mutex );
#elif defined( ST_INIT_IN_ST_H )
i_result = st_mutex_unlock( *p_mutex->mutex );
#elif defined( WIN32 )
if( p_mutex->mutex )
{
ReleaseMutex( p_mutex->mutex );
}
else
{
LeaveCriticalSection( &p_mutex->csection );
}
return 0;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
i_result = pthread_mutex_unlock( &p_mutex->mutex );
if ( i_result )
{
i_thread = (int)pthread_self();
psz_error = strerror(i_result);
}
#elif defined( HAVE_CTHREADS_H )
mutex_unlock( p_mutex );
return 0;
#elif defined( HAVE_KERNEL_SCHEDULER_H )
if( p_mutex == NULL )
{
i_result = B_BAD_VALUE;
}
else if( p_mutex->init < 2000 )
{
i_result = B_NO_INIT;
}
else
{
release_sem( p_mutex->lock );
return B_OK;
}
#endif
if( i_result )
{
msg_Err( p_mutex->p_this,
"thread %d: mutex_unlock failed at %s:%d (%d:%s)",
i_thread, psz_file, i_line, i_result, psz_error );
}
return i_result;
}
/*****************************************************************************
* vlc_mutex_destroy: destroy a mutex
*****************************************************************************/
#define vlc_mutex_destroy( P_MUTEX ) \
__vlc_mutex_destroy( __FILE__, __LINE__, P_MUTEX )
/*****************************************************************************
* vlc_cond_init: initialize a condition
*****************************************************************************/
#define vlc_cond_init( P_THIS, P_COND ) \
__vlc_cond_init( VLC_OBJECT(P_THIS), P_COND )
/*****************************************************************************
* vlc_cond_signal: start a thread on condition completion
*****************************************************************************/
#define vlc_cond_signal( P_COND ) \
__vlc_cond_signal( __FILE__, __LINE__, P_COND )
static inline int __vlc_cond_signal( char * psz_file, int i_line,
vlc_cond_t *p_condvar )
{
int i_result;
/* In case of error : */
int i_thread = -1;
const char * psz_error = "";
#if defined( PTH_INIT_IN_PTH_H )
i_result = pth_cond_notify( &p_condvar->cond, FALSE );
#elif defined( ST_INIT_IN_ST_H )
i_result = st_cond_signal( *p_condvar->cond );
#elif defined( WIN32 )
/* 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 */
if( !p_condvar->semaphore )
{
PulseEvent( p_condvar->event );
}
else if( p_condvar->i_win9x_cv == 1 )
{
/* Wait for the gate to be open */
WaitForSingleObject( p_condvar->event, INFINITE );
if( p_condvar->i_waiting_threads )
{
/* Using a semaphore exposes us to a race condition. It is
* possible for another thread to start waiting on the semaphore
* just after we signaled it and thus steal the signal.
* We have to prevent new threads from entering the cond_wait(). */
ResetEvent( p_condvar->event );
/* A semaphore is used here because Win9x doesn't have
* SignalObjectAndWait() and thus a race condition exists
* during the time we release the mutex and the time we start
* waiting on the event (more precisely, the signal can sometimes
* be missed by the waiting thread if we use PulseEvent()). */
ReleaseSemaphore( p_condvar->semaphore, 1, 0 );
}
}
else
{
if( p_condvar->i_waiting_threads )
{
ReleaseSemaphore( p_condvar->semaphore, 1, 0 );
/* Wait for the last thread to be awakened */
WaitForSingleObject( p_condvar->event, INFINITE );
}
}
return 0;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
i_result = pthread_cond_signal( &p_condvar->cond );
if ( i_result )
{
i_thread = (int)pthread_self();
psz_error = strerror(i_result);
}
#elif defined( HAVE_CTHREADS_H )
/* condition_signal() */
if ( p_condvar->queue.head || p_condvar->implications )
{
cond_signal( (condition_t)p_condvar );
}
return 0;
#elif defined( HAVE_KERNEL_SCHEDULER_H )
if( p_condvar == NULL )
{
i_result = B_BAD_VALUE;
}
else if( p_condvar->init < 2000 )
{
i_result = B_NO_INIT;
}
else
{
while( p_condvar->thread != -1 )
{
thread_info info;
if( get_thread_info(p_condvar->thread, &info) == B_BAD_VALUE )
{
return 0;
}
if( info.state != B_THREAD_SUSPENDED )
{
/* The waiting thread is not suspended so it could
* have been interrupted beetwen the unlock and the
* suspend_thread line. That is why we sleep a little
* before retesting p_condver->thread. */
snooze( 10000 );
}
else
{
/* Ok, we have to wake up that thread */
resume_thread( p_condvar->thread );
return 0;
}
}
}
#endif
if( i_result )
{
msg_Err( p_condvar->p_this,
"thread %d: cond_signal failed at %s:%d (%d:%s)",
i_thread, psz_file, i_line, i_result, psz_error );
}
return i_result;
}
/*****************************************************************************
* vlc_cond_broadcast: start all threads waiting on condition completion
*****************************************************************************/
/*
* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
* Only works with pthreads, st, win32
* You need to adapt it for others
* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
*/
#define vlc_cond_broadcast( P_COND ) \
__vlc_cond_broadcast( __FILE__, __LINE__, P_COND )
static inline int __vlc_cond_broadcast( char * psz_file, int i_line,
vlc_cond_t *p_condvar )
{
int i_result;
/* In case of error : */
int i_thread = -1;
const char * psz_error = "";
#if defined( PTH_INIT_IN_PTH_H )
i_result = pth_cond_notify( &p_condvar->cond, FALSE );
#elif defined( ST_INIT_IN_ST_H )
i_result = st_cond_broadcast( *p_condvar->cond );
#elif defined( WIN32 )
/* Release all waiting threads. */
if( !p_condvar->semaphore )
{
for( i = p_condvar->i_waiting_threads; i > 0; i-- )
{
PulseEvent( p_condvar->event );
}
}
else if( p_condvar->i_win9x_cv == 1 )
{
/* Wait for the gate to be open */
WaitForSingleObject( p_condvar->event, INFINITE );
if( p_condvar->i_waiting_threads )
{
/* Using a semaphore exposes us to a race condition. It is
* possible for another thread to start waiting on the semaphore
* just after we signaled it and thus steal the signal.
* We have to prevent new threads from entering the cond_wait(). */
ResetEvent( p_condvar->event );
/* A semaphore is used here because Win9x doesn't have
* SignalObjectAndWait() and thus a race condition exists
* during the time we release the mutex and the time we start
* waiting on the event (more precisely, the signal can sometimes
* be missed by the waiting thread if we use PulseEvent()). */
ReleaseSemaphore( p_condvar->semaphore,
p_condvar->i_waiting_threads, 0 );
}
}
else
{
if( p_condvar->i_waiting_threads )
{
ReleaseSemaphore( p_condvar->semaphore,
p_condvar->i_waiting_threads, 0 );
/* Wait for the last thread to be awakened */
WaitForSingleObject( p_condvar->event, INFINITE );
}
}
return 0;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
i_result = pthread_cond_broadcast( &p_condvar->cond );
if ( i_result )
{
i_thread = (int)pthread_self();
psz_error = strerror(i_result);
}
#elif defined( HAVE_CTHREADS_H )
/* condition_signal() */
if ( p_condvar->queue.head || p_condvar->implications )
{
cond_signal( (condition_t)p_condvar );
}
return 0;
#elif defined( HAVE_KERNEL_SCHEDULER_H )
if( p_condvar == NULL )
{
i_result = B_BAD_VALUE;
}
else if( p_condvar->init < 2000 )
{
i_result = B_NO_INIT;
}
else
{
while( p_condvar->thread != -1 )
{
thread_info info;
if( get_thread_info(p_condvar->thread, &info) == B_BAD_VALUE )
{
return 0;
}
if( info.state != B_THREAD_SUSPENDED )
{
/* The waiting thread is not suspended so it could
* have been interrupted beetwen the unlock and the
* suspend_thread line. That is why we sleep a little
* before retesting p_condver->thread. */
snooze( 10000 );
}
else
{
/* Ok, we have to wake up that thread */
resume_thread( p_condvar->thread );
return 0;
}
}
}
#endif
if( i_result )
{
msg_Err( p_condvar->p_this,
"thread %d: cond_broadcast failed at %s:%d (%d:%s)",
i_thread, psz_file, i_line, i_result, psz_error );
}
return i_result;
}
/*****************************************************************************
* vlc_cond_wait: wait until condition completion
*****************************************************************************/
#define vlc_cond_wait( P_COND, P_MUTEX ) \
__vlc_cond_wait( __FILE__, __LINE__, P_COND, P_MUTEX )
static inline int __vlc_cond_wait( char * psz_file, int i_line,
vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex )
{
int i_result;
/* In case of error : */
int i_thread = -1;
const char * psz_error = "";
#if defined( PTH_INIT_IN_PTH_H )
i_result = pth_cond_await( &p_condvar->cond, &p_mutex->mutex, NULL );
#elif defined( ST_INIT_IN_ST_H )
st_mutex_unlock( *p_mutex->mutex );
i_result = st_cond_wait( *p_condvar->cond );
st_mutex_lock( *p_mutex->mutex );
#elif defined( WIN32 )
if( !p_condvar->semaphore )
{
/* Increase our wait count */
p_condvar->i_waiting_threads++;
if( p_condvar->SignalObjectAndWait && p_mutex->mutex )
{
/* 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->event,
INFINITE, FALSE );
}
else
{
LeaveCriticalSection( &p_mutex->csection );
WaitForSingleObject( p_condvar->event, INFINITE );
}
p_condvar->i_waiting_threads--;
}
else if( p_condvar->i_win9x_cv == 1 )
{
int i_waiting_threads;
/* Wait for the gate to be open */
WaitForSingleObject( p_condvar->event, INFINITE );
/* Increase our wait count */
p_condvar->i_waiting_threads++;
LeaveCriticalSection( &p_mutex->csection );
WaitForSingleObject( p_condvar->semaphore, INFINITE );
/* Decrement and test must be atomic */
EnterCriticalSection( &p_condvar->csection );
/* Decrease our wait count */
i_waiting_threads = --p_condvar->i_waiting_threads;
LeaveCriticalSection( &p_condvar->csection );
/* Reopen the gate if we were the last waiting thread */
if( !i_waiting_threads )
SetEvent( p_condvar->event );
}
else
{
int i_waiting_threads;
/* Increase our wait count */
p_condvar->i_waiting_threads++;
LeaveCriticalSection( &p_mutex->csection );
WaitForSingleObject( p_condvar->semaphore, INFINITE );
/* Decrement and test must be atomic */
EnterCriticalSection( &p_condvar->csection );
/* Decrease our wait count */
i_waiting_threads = --p_condvar->i_waiting_threads;
LeaveCriticalSection( &p_condvar->csection );
/* Signal that the last waiting thread just went through */
if( !i_waiting_threads )
SetEvent( p_condvar->event );
}
/* Reacquire the mutex before returning. */
vlc_mutex_lock( p_mutex );
return 0;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
# ifdef DEBUG
/* In debug mode, timeout */
struct timeval now;
struct timespec timeout;
for( ; ; )
{
gettimeofday( &now, NULL );
timeout.tv_sec = now.tv_sec + THREAD_COND_TIMEOUT;
timeout.tv_nsec = now.tv_usec * 1000;
i_result = pthread_cond_timedwait( &p_condvar->cond, &p_mutex->mutex,
&timeout );
if( i_result == ETIMEDOUT )
{
msg_Warn( p_condvar->p_this,
"thread %d: possible deadlock detected "
"in cond_wait at %s:%d (%s)", pthread_self(),
psz_file, i_line, strerror(i_result) );
}
else break;
}
# else
i_result = pthread_cond_wait( &p_condvar->cond, &p_mutex->mutex );
# endif
if ( i_result )
{
i_thread = (int)pthread_self();
psz_error = strerror(i_result);
}
#elif defined( HAVE_CTHREADS_H )
condition_wait( (condition_t)p_condvar, (mutex_t)p_mutex );
return 0;
#elif defined( HAVE_KERNEL_SCHEDULER_H )
if( p_condvar == NULL )
{
i_result = B_BAD_VALUE;
}
else if( p_mutex == NULL )
{
i_result = B_BAD_VALUE;
}
else if( p_condvar->init < 2000 )
{
i_result = B_NO_INIT;
}
/* The p_condvar->thread var is initialized before the unlock because
* it enables to identify when the thread is interrupted beetwen the
* unlock line and the suspend_thread line */
p_condvar->thread = find_thread( NULL );
vlc_mutex_unlock( p_mutex );
suspend_thread( p_condvar->thread );
p_condvar->thread = -1;
vlc_mutex_lock( p_mutex );
return 0;
#endif
if( i_result )
{
msg_Err( p_condvar->p_this,
"thread %d: cond_wait failed at %s:%d (%d:%s)",
i_thread, psz_file, i_line, i_result, psz_error );
}
return i_result;
}
/*****************************************************************************
* vlc_cond_destroy: destroy a condition
*****************************************************************************/
#define vlc_cond_destroy( P_COND ) \
__vlc_cond_destroy( __FILE__, __LINE__, P_COND )
/*****************************************************************************
* vlc_thread_create: create a thread
*****************************************************************************/
#define vlc_thread_create( P_THIS, PSZ_NAME, FUNC, PRIORITY, WAIT ) \
__vlc_thread_create( VLC_OBJECT(P_THIS), __FILE__, __LINE__, PSZ_NAME, (void * ( * ) ( void * ))FUNC, PRIORITY, WAIT )
/*****************************************************************************
* vlc_thread_ready: tell the parent thread we were successfully spawned
*****************************************************************************/
#define vlc_thread_ready( P_THIS ) \
__vlc_thread_ready( VLC_OBJECT(P_THIS) )
/*****************************************************************************
* vlc_thread_join: wait until a thread exits
*****************************************************************************/
#define vlc_thread_join( P_THIS ) \
__vlc_thread_join( VLC_OBJECT(P_THIS), __FILE__, __LINE__ )
......@@ -2,7 +2,7 @@
* access.c: access capabilities for dvdplay plugin.
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: access.c,v 1.2 2002/08/07 00:29:36 sam Exp $
* $Id: access.c,v 1.3 2002/08/29 23:53:22 massiot Exp $
*
* Author: Stphane Borel <stef@via.ecp.fr>
*
......@@ -47,12 +47,6 @@
#if defined( WIN32 )
# include <io.h> /* read() */
#else
# include <sys/uio.h> /* struct iovec */
#endif
#if defined( WIN32 )
# include "input_iovec.h"
#endif
#include "dvd.h"
......
......@@ -6,7 +6,7 @@
* It depends on: libdvdread for ifo files and block reading.
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: input.c,v 1.2 2002/08/07 00:29:36 sam Exp $
* $Id: input.c,v 1.3 2002/08/29 23:53:22 massiot Exp $
*
* Author: Stphane Borel <stef@via.ecp.fr>
*
......@@ -56,12 +56,6 @@
#if defined( WIN32 )
# include <io.h> /* read() */
#else
# include <sys/uio.h> /* struct iovec */
#endif
#if defined( WIN32 )
# include "input_iovec.h"
#endif
#include <dvdread/dvd_reader.h>
......
......@@ -2,7 +2,7 @@
* vcd.c : VCD input module for vlc
*****************************************************************************
* Copyright (C) 2000 VideoLAN
* $Id: vcd.c,v 1.4 2002/08/08 22:28:22 sam Exp $
* $Id: vcd.c,v 1.5 2002/08/29 23:53:22 massiot Exp $
*
* Author: Johan Bilien <jobi@via.ecp.fr>
*
......@@ -44,12 +44,6 @@
#if defined( WIN32 )
# include <io.h> /* read() */
#else
# include <sys/uio.h> /* struct iovec */
#endif
#if defined( WIN32 )
# include "input_iovec.h"
#endif
#include "vcd.h"
......
......@@ -2,7 +2,7 @@
* alsa.c : alsa plugin for vlc
*****************************************************************************
* Copyright (C) 2000-2001 VideoLAN
* $Id: alsa.c,v 1.8 2002/08/25 09:39:59 sam Exp $
* $Id: alsa.c,v 1.9 2002/08/29 23:53:22 massiot Exp $
*
* Authors: Henri Fallon <henri@videolan.org> - Original Author
* Jeffrey Baker <jwbaker@acm.org> - Port to ALSA 1.0 API
......@@ -115,7 +115,8 @@ static int Open( vlc_object_t *p_this )
/* Create ALSA thread and wait for its readiness. */
p_sys->b_initialized = VLC_FALSE;
if( vlc_thread_create( p_aout, "aout", ALSAThread, VLC_FALSE ) )
if( vlc_thread_create( p_aout, "aout", ALSAThread,
VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
{
msg_Err( p_aout, "cannot create ALSA thread (%s)", strerror(errno) );
free( p_sys );
......
......@@ -101,7 +101,8 @@ static int Open( vlc_object_t *p_this )
/* Create aRts thread and wait for its readiness. */
p_sys->b_initialized = VLC_FALSE;
if( vlc_thread_create( p_aout, "aout", aRtsThread, VLC_FALSE ) )
if( vlc_thread_create( p_aout, "aout", aRtsThread,
VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
{
msg_Err( p_aout, "cannot create aRts thread (%s)", strerror(errno) );
free( p_sys );
......
......@@ -2,7 +2,7 @@
* esd.c : EsounD module
*****************************************************************************
* Copyright (C) 2000, 2001 VideoLAN
* $Id: esd.c,v 1.10 2002/08/25 09:39:59 sam Exp $
* $Id: esd.c,v 1.11 2002/08/29 23:53:22 massiot Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -91,7 +91,8 @@ static int Open( vlc_object_t *p_this )
/* Create ESD thread and wait for its readiness. */
p_sys->b_initialized = VLC_FALSE;
if( vlc_thread_create( p_aout, "aout", ESDThread, VLC_FALSE ) )
if( vlc_thread_create( p_aout, "aout", ESDThread,
VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
{
msg_Err( p_aout, "cannot create ESD thread (%s)", strerror(errno) );
free( p_sys );
......
......@@ -2,7 +2,7 @@
* oss.c : OSS /dev/dsp module for vlc
*****************************************************************************
* Copyright (C) 2000-2002 VideoLAN
* $Id: oss.c,v 1.19 2002/08/25 16:55:55 sam Exp $
* $Id: oss.c,v 1.20 2002/08/29 23:53:22 massiot Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
......@@ -131,7 +131,8 @@ static int Open( vlc_object_t *p_this )
/* Create OSS thread and wait for its readiness. */
p_sys->b_initialized = VLC_FALSE;
if( vlc_thread_create( p_aout, "aout", OSSThread, VLC_FALSE ) )
if( vlc_thread_create( p_aout, "aout", OSSThread,
VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
{
msg_Err( p_aout, "cannot create OSS thread (%s)", strerror(errno) );
close( p_sys->i_fd );
......
......@@ -2,7 +2,7 @@
* video_decoder.c : video decoder thread
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: decoder.c,v 1.3 2002/08/08 00:35:11 sam Exp $
* $Id: decoder.c,v 1.4 2002/08/29 23:53:22 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Michel Lespinasse <walken@zoy.org>
......@@ -71,7 +71,8 @@ vdec_thread_t * vdec_CreateThread( vdec_pool_t * p_pool )
p_vdec->p_pool = p_pool;
/* Spawn the video decoder thread */
if( vlc_thread_create( p_vdec, "video decoder", RunThread, 0 ) )
if( vlc_thread_create( p_vdec, "video decoder", RunThread,
VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
{
msg_Err( p_vdec, "cannot spawn video decoder thread" );
vlc_object_destroy( p_vdec );
......
......@@ -2,7 +2,7 @@
* aout.cpp: BeOS audio output
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: AudioOutput.cpp,v 1.5 2002/08/23 14:16:23 tcastley Exp $
* $Id: AudioOutput.cpp,v 1.6 2002/08/29 23:53:22 massiot Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
......@@ -105,9 +105,10 @@ int E_(OpenAudio) ( vlc_object_t * p_this )
return -1;
}
if( vlc_thread_create( p_aout, "aout", BeOSThread, VLC_FALSE) )
if( vlc_thread_create( p_aout, "aout", BeOSThread,
VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
{
msg_Err( p_aout, "cannot create OSS thread " );
msg_Err( p_aout, "cannot create aout thread" );
delete p_sys->p_sound;
free( p_sys->p_format );
free( p_sys );
......@@ -278,4 +279,5 @@ static int BeOSThread( aout_instance_t * p_aout )
return 0;
}
\ No newline at end of file
}
......@@ -104,7 +104,8 @@ int E_(OpenAudio)( vlc_object_t *p_this )
/* Create audio thread and wait for its readiness. */
p_aout->output.p_sys->b_initialized = VLC_FALSE;
if( vlc_thread_create( p_aout, "aout", QNXaoutThread, VLC_FALSE ) )
if( vlc_thread_create( p_aout, "aout", QNXaoutThread,
VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
{
msg_Err( p_aout, "cannot create QNX audio thread (%s)", strerror(errno) );
E_(CloseAudio)( p_this );
......
......@@ -2,7 +2,7 @@
* gtk_main.c : Gtk+ wrapper for gtk_main
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: gtk_main.c,v 1.4 2002/08/21 17:31:58 sam Exp $
* $Id: gtk_main.c,v 1.5 2002/08/29 23:53:22 massiot Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -98,7 +98,8 @@ static int Open( vlc_object_t *p_this )
/* Launch the gtk_main() thread. It will not return until it has
* called gdk_threads_enter(), which ensures us thread safety. */
if( vlc_thread_create( p_gtk_main, "gtk_main", GtkMain, VLC_TRUE ) )
if( vlc_thread_create( p_gtk_main, "gtk_main", GtkMain,
VLC_THREAD_PRIORITY_LOW, VLC_TRUE ) )
{
vlc_object_destroy( p_gtk_main );
i_refcount--;
......
......@@ -2,7 +2,7 @@
* aout.c: Windows DirectX audio output method
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: aout.c,v 1.7 2002/08/25 09:40:00 sam Exp $
* $Id: aout.c,v 1.8 2002/08/29 23:53:22 massiot Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
......@@ -175,7 +175,7 @@ int E_(OpenAudio) ( vlc_object_t *p_this )
msg_Dbg( p_aout, "creating DirectSoundThread" );
if( vlc_thread_create( p_aout->output.p_sys->p_notif,
"DirectSound Notification Thread",
DirectSoundThread, 1 ) )
DirectSoundThread, VLC_THREAD_PRIORITY_OUTPUT, 1 ) )
{
msg_Err( p_aout, "cannot create DirectSoundThread" );
goto error;
......
......@@ -2,7 +2,7 @@
* vout.c: Windows DirectX video output display method
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: vout.c,v 1.2 2002/08/12 09:34:15 sam Exp $
* $Id: vout.c,v 1.3 2002/08/29 23:53:22 massiot Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
......@@ -140,7 +140,8 @@ int E_(OpenVideo) ( vlc_object_t *p_this )
vlc_object_create( p_vout, sizeof(event_thread_t) );
p_vout->p_sys->p_event->p_vout = p_vout;
if( vlc_thread_create( p_vout->p_sys->p_event,
"DirectX Events Thread", DirectXEventThread, 1 ) )
"DirectX Events Thread", DirectXEventThread,
VLC_THREAD_PRIORITY_LOW 1 ) )
{
msg_Err( p_vout, "cannot create DirectXEventThread" );
vlc_object_destroy( p_vout->p_sys->p_event );
......
......@@ -4,7 +4,7 @@
* decoders.
*****************************************************************************
* Copyright (C) 1998-2002 VideoLAN
* $Id: input.c,v 1.211 2002/08/16 12:31:04 sam Exp $
* $Id: input.c,v 1.212 2002/08/29 23:53:22 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -158,7 +158,8 @@ input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
vlc_object_attach( p_input, p_parent );
/* Create thread and wait for its readiness. */
if( vlc_thread_create( p_input, "input", RunThread, VLC_TRUE ) )
if( vlc_thread_create( p_input, "input", RunThread,
VLC_THREAD_PRIORITY_INPUT, VLC_TRUE ) )
{
msg_Err( p_input, "cannot create input thread (%s)", strerror(errno) );
free( p_input );
......
......@@ -2,7 +2,7 @@
* input_dec.c: Functions for the management of decoders
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: input_dec.c,v 1.45 2002/08/12 22:12:51 massiot Exp $
* $Id: input_dec.c,v 1.46 2002/08/29 23:53:22 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -46,6 +46,7 @@ decoder_fifo_t * input_RunDecoder( input_thread_t * p_input,
es_descriptor_t * p_es )
{
decoder_fifo_t *p_fifo;
int i_priority;
/* Create the decoder configuration structure */
p_fifo = CreateDecoderFifo( p_input, p_es );
......@@ -67,8 +68,18 @@ decoder_fifo_t * input_RunDecoder( input_thread_t * p_input,
return NULL;
}
if ( p_es->i_cat == AUDIO_ES )
{
i_priority = VLC_THREAD_PRIORITY_AUDIO;
}
else
{
i_priority = VLC_THREAD_PRIORITY_LOW;
}
/* Spawn the decoder thread */
if( vlc_thread_create( p_fifo, "decoder", p_fifo->pf_run, 0 ) )
if( vlc_thread_create( p_fifo, "decoder", p_fifo->pf_run,
i_priority, VLC_FALSE ) )
{
msg_Err( p_fifo, "cannot spawn decoder thread \"%s\"",
p_fifo->p_module->psz_object_name );
......
......@@ -4,7 +4,7 @@
* interface, such as command line.
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: interface.c,v 1.98 2002/08/04 20:04:11 sam Exp $
* $Id: interface.c,v 1.99 2002/08/29 23:53:22 massiot Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
*
......@@ -103,7 +103,8 @@ vlc_error_t intf_RunThread( intf_thread_t *p_intf )
if( p_intf->b_block )
{
/* Run a manager thread, launch the interface, kill the manager */
if( vlc_thread_create( p_intf, "manager", Manager, 0 ) )
if( vlc_thread_create( p_intf, "manager", Manager,
VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
{
msg_Err( p_intf, "cannot spawn manager thread" );
return VLC_EGENERIC;
......@@ -118,7 +119,8 @@ vlc_error_t intf_RunThread( intf_thread_t *p_intf )
else
{
/* Run the interface in a separate thread */
if( vlc_thread_create( p_intf, "interface", p_intf->pf_run, 0 ) )
if( vlc_thread_create( p_intf, "interface", p_intf->pf_run,
VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
{
msg_Err( p_intf, "cannot spawn interface thread" );
return VLC_EGENERIC;
......
......@@ -2,7 +2,7 @@
* beos_init.cpp: Initialization for BeOS specific features
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: beos_specific.cpp,v 1.24 2002/08/12 09:34:15 sam Exp $
* $Id: beos_specific.cpp,v 1.25 2002/08/29 23:53:22 massiot Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
*
......@@ -70,7 +70,8 @@ void system_Init( vlc_t *p_this, int *pi_argc, char *ppsz_argv[] )
(vlc_object_t *)vlc_object_create( p_this, sizeof(vlc_object_t) );
/* Create the BApplication thread and wait for initialization */
vlc_thread_create( p_this->p_vlc->p_appthread, "app thread", AppThread, 1 );
vlc_thread_create( p_this->p_vlc->p_appthread, "app thread", AppThread,
VLC_THREAD_PRIORITY_LOW, VLC_TRUE );
}
/*****************************************************************************
......
......@@ -2,7 +2,7 @@
* threads.c : threads implementation for the VideoLAN client
*****************************************************************************
* Copyright (C) 1999, 2000, 2001, 2002 VideoLAN
* $Id: threads.c,v 1.12 2002/08/08 00:35:11 sam Exp $
* $Id: threads.c,v 1.13 2002/08/29 23:53:22 massiot Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
......@@ -218,11 +218,13 @@ int __vlc_threads_end( vlc_object_t *p_this )
*****************************************************************************/
int __vlc_mutex_init( vlc_object_t *p_this, vlc_mutex_t *p_mutex )
{
p_mutex->p_this = p_this;
#if defined( PTH_INIT_IN_PTH_H )
return pth_mutex_init( p_mutex );
return pth_mutex_init( &p_mutex->mutex );
#elif defined( ST_INIT_IN_ST_H )
*p_mutex = st_mutex_new();
*p_mutex->mutex = st_mutex_new();
return ( *p_mutex == NULL ) ? errno : 0;
#elif defined( WIN32 )
......@@ -234,7 +236,7 @@ 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 );
return ( p_mutex->mutex ? 0 : 1 );
return ( p_mutex->mutex != NULL ? 0 : 1 );
}
else
{
......@@ -245,24 +247,25 @@ int __vlc_mutex_init( vlc_object_t *p_this, vlc_mutex_t *p_mutex )
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
# if defined(DEBUG) && defined(SYS_LINUX)
/* Create error-checking mutex to detect threads problems more easily. */
pthread_mutexattr_t attr;
int i_result;
pthread_mutexattr_init( &attr );
pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_ERRORCHECK_NP );
i_result = pthread_mutex_init( p_mutex, &attr );
pthread_mutexattr_destroy( &attr );
return( i_result );
{
/* Create error-checking mutex to detect problems more easily. */
pthread_mutexattr_t attr;
int i_result;
pthread_mutexattr_init( &attr );
pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_ERRORCHECK_NP );
i_result = pthread_mutex_init( p_mutex, &attr );
pthread_mutexattr_destroy( &attr );
return( i_result );
}
# endif
return pthread_mutex_init( p_mutex, NULL );
return pthread_mutex_init( &p_mutex->mutex, NULL );
#elif defined( HAVE_CTHREADS_H )
mutex_init( p_mutex );
return 0;
#elif defined( HAVE_KERNEL_SCHEDULER_H )
/* check the arguments and whether it's already been initialized */
if( p_mutex == NULL )
{
......@@ -291,11 +294,16 @@ int __vlc_mutex_init( vlc_object_t *p_this, vlc_mutex_t *p_mutex )
*****************************************************************************/
int __vlc_mutex_destroy( char * psz_file, int i_line, vlc_mutex_t *p_mutex )
{
int i_result;
/* In case of error : */
int i_thread = -1;
const char * psz_error = "";
#if defined( PTH_INIT_IN_PTH_H )
return 0;
#elif defined( ST_INIT_IN_ST_H )
return st_mutex_destroy( *p_mutex );
i_result = st_mutex_destroy( *p_mutex );
#elif defined( WIN32 )
if( p_mutex->mutex )
......@@ -309,15 +317,12 @@ int __vlc_mutex_destroy( char * psz_file, int i_line, vlc_mutex_t *p_mutex )
return 0;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
int i_return = pthread_mutex_destroy( p_mutex );
if( i_return )
i_result = pthread_mutex_destroy( &p_mutex->mutex );
if ( i_result )
{
#if 0
intf_ErrMsg( "thread %d error: mutex_destroy failed at %s:%d (%s)",
pthread_self(), psz_file, i_line, strerror(i_return) );
#endif
i_thread = pthread_self();
psz_error = strerror(i_result);
}
return i_return;
#elif defined( HAVE_CTHREADS_H )
return 0;
......@@ -330,8 +335,15 @@ int __vlc_mutex_destroy( char * psz_file, int i_line, vlc_mutex_t *p_mutex )
p_mutex->init = 0;
return B_OK;
#endif
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 );
}
return i_result;
}
/*****************************************************************************
......@@ -339,12 +351,14 @@ int __vlc_mutex_destroy( char * psz_file, int i_line, vlc_mutex_t *p_mutex )
*****************************************************************************/
int __vlc_cond_init( vlc_object_t *p_this, vlc_cond_t *p_condvar )
{
p_condvar->p_this = p_this;
#if defined( PTH_INIT_IN_PTH_H )
return pth_cond_init( p_condvar );
return pth_cond_init( &p_condvar->cond );
#elif defined( ST_INIT_IN_ST_H )
*p_condvar = st_cond_new();
return ( *p_condvar == NULL ) ? errno : 0;
*p_condvar->cond = st_cond_new();
return ( *p_condvar->cond == NULL ) ? errno : 0;
#elif defined( WIN32 )
/* Initialize counter */
......@@ -385,7 +399,7 @@ int __vlc_cond_init( vlc_object_t *p_this, vlc_cond_t *p_condvar )
}
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
return pthread_cond_init( p_condvar, NULL );
return pthread_cond_init( &p_condvar->cond, NULL );
#elif defined( HAVE_CTHREADS_H )
/* condition_init() */
......@@ -410,7 +424,6 @@ int __vlc_cond_init( vlc_object_t *p_this, vlc_cond_t *p_condvar )
p_condvar->thread = -1;
p_condvar->init = 9999;
return 0;
#endif
}
......@@ -419,29 +432,31 @@ int __vlc_cond_init( vlc_object_t *p_this, vlc_cond_t *p_condvar )
*****************************************************************************/
int __vlc_cond_destroy( char * psz_file, int i_line, vlc_cond_t *p_condvar )
{
int i_result;
/* In case of error : */
int i_thread = -1;
const char * psz_error = "";
#if defined( PTH_INIT_IN_PTH_H )
return 0;
#elif defined( ST_INIT_IN_ST_H )
return st_cond_destroy( *p_condvar );
i_result = st_cond_destroy( *p_condvar->cond );
#elif defined( WIN32 )
if( !p_condvar->semaphore )
return !CloseHandle( p_condvar->event );
i_result = !CloseHandle( p_condvar->event );
else
return !CloseHandle( p_condvar->event )
i_result = !CloseHandle( p_condvar->event )
|| !CloseHandle( p_condvar->semaphore );
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
int i_result = pthread_cond_destroy( p_condvar );
if( i_result )
i_result = pthread_cond_destroy( &p_condvar->cond );
if ( i_result )
{
#if 0
intf_ErrMsg( "thread %d error: cond_destroy failed at %s:%d (%s)",
pthread_self(), psz_file, i_line, strerror(i_result) );
#endif
i_thread = pthread_self();
psz_error = strerror(i_result);
}
return i_result;
#elif defined( HAVE_CTHREADS_H )
return 0;
......@@ -449,16 +464,26 @@ int __vlc_cond_destroy( char * psz_file, int i_line, vlc_cond_t *p_condvar )
#elif defined( HAVE_KERNEL_SCHEDULER_H )
p_condvar->init = 0;
return 0;
#endif
#endif
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 );
}
return i_result;
}
/*****************************************************************************
* vlc_thread_create: create a thread, inner version
*****************************************************************************
* Note that i_priority is only taken into account on platforms supporting
* userland real-time priority threads.
*****************************************************************************/
int __vlc_thread_create( vlc_object_t *p_this, char * psz_file, int i_line,
char *psz_name, void * ( *func ) ( void * ),
vlc_bool_t b_wait )
int i_priority, vlc_bool_t b_wait )
{
int i_ret;
......@@ -500,11 +525,32 @@ int __vlc_thread_create( vlc_object_t *p_this, char * psz_file, int i_line,
(void *)p_this, 0, &threadID );
}
if ( p_this->thread_id && i_priority )
{
if ( !SetThreadPriority(p_this->thread_id, i_priority) )
{
msg_Warn( p_this, "couldn't set a faster priority" );
i_priority = 0;
}
}
i_ret = ( p_this->thread_id ? 0 : 1 );
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
i_ret = pthread_create( &p_this->thread_id, NULL, func, (void *)p_this );
if ( i_priority )
{
struct sched_param param;
memset( &param, 0, sizeof(struct sched_param) );
param.sched_priority = i_priority;
if ( pthread_setschedparam( p_this->thread_id, SCHED_RR, &param ) )
{
msg_Warn( p_this, "couldn't go to real-time priority" );
i_priority = 0;
}
}
#elif defined( HAVE_CTHREADS_H )
p_this->thread_id = cthread_fork( (cthread_fn_t)func, (any_t)p_this );
i_ret = 0;
......@@ -537,8 +583,9 @@ int __vlc_thread_create( vlc_object_t *p_this, char * psz_file, int i_line,
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 );
msg_Dbg( p_this, "thread %d (%s) created at priority %d (%s:%d)",
p_this->thread_id, psz_name, i_priority,
psz_file, i_line );
vlc_mutex_unlock( &p_this->object_lock );
}
......
......@@ -2,7 +2,7 @@
* playlist.c : Playlist management functions
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: playlist.c,v 1.12 2002/08/25 19:27:20 sam Exp $
* $Id: playlist.c,v 1.13 2002/08/29 23:53:22 massiot Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -67,7 +67,8 @@ playlist_t * __playlist_Create ( vlc_object_t *p_parent )
p_playlist->i_size = 0;
p_playlist->pp_items = NULL;
if( vlc_thread_create( p_playlist, "playlist", RunThread, VLC_TRUE ) )
if( vlc_thread_create( p_playlist, "playlist", RunThread,
VLC_THREAD_PRIORITY_LOW, VLC_TRUE ) )
{
msg_Err( p_playlist, "cannot spawn playlist thread" );
vlc_object_destroy( p_playlist );
......
......@@ -5,7 +5,7 @@
* thread, and destroy a previously oppened video output thread.
*****************************************************************************
* Copyright (C) 2000-2001 VideoLAN
* $Id: video_output.c,v 1.190 2002/08/12 09:34:15 sam Exp $
* $Id: video_output.c,v 1.191 2002/08/29 23:53:22 massiot Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
*
......@@ -202,7 +202,8 @@ vout_thread_t * __vout_CreateThread ( vlc_object_t *p_parent,
vlc_object_attach( p_vout, p_parent );
if( vlc_thread_create( p_vout, "video output", RunThread, 0 ) )
if( vlc_thread_create( p_vout, "video output", RunThread,
VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
{
msg_Err( p_vout, "%s", strerror(ENOMEM) );
module_Unneed( p_vout, p_vout->p_module );
......
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