From: dmitrykos Date: Sun, 6 Jun 2010 17:36:33 +0000 (+0000) Subject: oss: fixed compile for systems missing 'pthread_cancel' series of functions, this... X-Git-Tag: pa_stable_v19_20110326_r1647~120 X-Git-Url: https://andrewgundersen.net/repos?a=commitdiff_plain;h=01f740b88257ee63c9794f4424b3878c3fe18c17;p=portaudio oss: fixed compile for systems missing 'pthread_cancel' series of functions, this allows to compile PortAudio under Android platform with OSS as audio host back-end --- diff --git a/src/hostapi/oss/pa_unix_oss.c b/src/hostapi/oss/pa_unix_oss.c index 225c028..e51201b 100644 --- a/src/hostapi/oss/pa_unix_oss.c +++ b/src/hostapi/oss/pa_unix_oss.c @@ -185,7 +185,7 @@ typedef struct PaOssStream double sampleRate; int callbackMode; - int callbackStop, callbackAbort; + volatile int callbackStop, callbackAbort; PaOssStreamComponent *capture, *playback; unsigned long pollTimeout; @@ -1317,7 +1317,17 @@ static PaError PaOssStream_WaitForFrames( PaOssStream *stream, unsigned long *fr while( pollPlayback || pollCapture ) { +#ifdef PTHREAD_CANCELED pthread_testcancel(); +#else + /* avoid indefinite waiting on thread not supporting cancelation */ + if( stream->callbackStop || stream->callbackAbort ) + { + PA_DEBUG(( "Cancelling PaOssStream_WaitForFrames\n" )); + (*frames) = 0; + return paNoError; + } +#endif /* select may modify the timeout parameter */ selectTimeval.tv_usec = timeout; @@ -1341,8 +1351,17 @@ static PaError PaOssStream_WaitForFrames( PaOssStream *stream, unsigned long *fr ENSURE_( -1, paUnanticipatedHostError ); } */ +#ifdef PTHREAD_CANCELED pthread_testcancel(); - +#else + /* avoid indefinite waiting on thread not supporting cancelation */ + if( stream->callbackStop || stream->callbackAbort ) + { + PA_DEBUG(( "Cancelling PaOssStream_WaitForFrames\n" )); + (*frames) = 0; + return paNoError; + } +#endif if( pollCapture ) { if( FD_ISSET( captureFd, &readFds ) ) @@ -1603,8 +1622,15 @@ static void *PaOSS_AudioThreadProc( void *userData ) while( 1 ) { +#ifdef PTHREAD_CANCELED pthread_testcancel(); - +#else + if( stream->callbackAbort ) /* avoid indefinite waiting on thread not supporting cancelation */ + { + PA_DEBUG(( "Aborting callback thread\n" )); + break; + } +#endif if( stream->callbackStop && callbackResult == paContinue ) { PA_DEBUG(( "Setting callbackResult to paComplete\n" )); @@ -1631,8 +1657,21 @@ static void *PaOSS_AudioThreadProc( void *userData ) { unsigned long frames = framesAvail; +#ifdef PTHREAD_CANCELED pthread_testcancel(); +#else + if( stream->callbackStop ) + { + PA_DEBUG(( "Setting callbackResult to paComplete\n" )); + callbackResult = paComplete; + } + if( stream->callbackAbort ) /* avoid indefinite waiting on thread not supporting cancelation */ + { + PA_DEBUG(( "Aborting callback thread\n" )); + break; + } +#endif PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer ); /* Read data */ diff --git a/src/os/unix/pa_unix_util.c b/src/os/unix/pa_unix_util.c index a0fcfca..63ccf44 100644 --- a/src/os/unix/pa_unix_util.c +++ b/src/os/unix/pa_unix_util.c @@ -193,9 +193,15 @@ PaError PaUtil_CancelThreading( PaUtilThreading *threading, int wait, PaError *e if( exitResult ) *exitResult = paNoError; + /* If pthread_cancel is not supported (Android platform) whole this function can lead to indefinite waiting if + working thread (callbackThread) has'n received any stop signals from outside, please keep + this in mind when considering using PaUtil_CancelThreading + */ +#ifdef PTHREAD_CANCELED /* Only kill the thread if it isn't in the process of stopping (flushing adaptation buffers) */ if( !wait ) pthread_cancel( threading->callbackThread ); /* XXX: Safe to call this if the thread has exited on its own? */ +#endif pthread_join( threading->callbackThread, &pret ); #ifdef PTHREAD_CANCELED @@ -427,12 +433,19 @@ PaError PaUnixThread_Terminate( PaUnixThread* self, int wait, PaError* exitResul { PA_DEBUG(( "%s: Canceling thread %d\n", __FUNCTION__, self->thread )); /* XXX: Safe to call this if the thread has exited on its own? */ +#ifdef PTHREAD_CANCELED pthread_cancel( self->thread ); +#endif } PA_DEBUG(( "%s: Joining thread %d\n", __FUNCTION__, self->thread )); PA_ENSURE_SYSTEM( pthread_join( self->thread, &pret ), 0 ); +#ifdef PTHREAD_CANCELED if( pret && PTHREAD_CANCELED != pret ) +#else + /* !wait means the thread may have been canceled */ + if( pret && wait ) +#endif { if( exitResult ) { @@ -508,7 +521,9 @@ PaError PaUnixMutex_Lock( PaUnixMutex* self ) PaError result = paNoError; int oldState; +#ifdef PTHREAD_CANCEL PA_ENSURE_SYSTEM( pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &oldState ), 0 ); +#endif PA_ENSURE_SYSTEM( pthread_mutex_lock( &self->mtx ), 0 ); error: @@ -525,7 +540,9 @@ PaError PaUnixMutex_Unlock( PaUnixMutex* self ) int oldState; PA_ENSURE_SYSTEM( pthread_mutex_unlock( &self->mtx ), 0 ); +#ifdef PTHREAD_CANCEL PA_ENSURE_SYSTEM( pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, &oldState ), 0 ); +#endif error: return result;