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 )
{