Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
221 changes: 1 addition & 220 deletions src/os/unix/pa_unix_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,48 +318,7 @@ PaError PaUnixThread_New( PaUnixThread* self, void* (*threadFunc)( void* ), void

if( rtSched )
{
#if 0
if( self->useWatchdog )
{
int err;
struct sched_param wdSpm = { 0 };
/* Launch watchdog, watchdog sets callback thread priority */
int prio = PA_MIN( self->rtPrio + 4, sched_get_priority_max( SCHED_FIFO ) );
wdSpm.sched_priority = prio;

PA_UNLESS( !pthread_attr_init( &attr ), paInternalError );
PA_UNLESS( !pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED ), paInternalError );
PA_UNLESS( !pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM ), paInternalError );
PA_UNLESS( !pthread_attr_setschedpolicy( &attr, SCHED_FIFO ), paInternalError );
PA_UNLESS( !pthread_attr_setschedparam( &attr, &wdSpm ), paInternalError );
if( (err = pthread_create( &self->watchdogThread, &attr, &WatchdogFunc, self )) )
{
PA_UNLESS( err == EPERM, paInternalError );
/* Permission error, go on without realtime privileges */
PA_DEBUG(( "Failed bumping priority\n" ));
}
else
{
int policy;
self->watchdogRunning = 1;
PA_ENSURE_SYSTEM( pthread_getschedparam( self->watchdogThread, &policy, &wdSpm ), 0 );
/* Check if priority is right, policy could potentially differ from SCHED_FIFO (but that's alright) */
if( wdSpm.sched_priority != prio )
{
PA_DEBUG(( "Watchdog priority not set correctly (%d)\n", wdSpm.sched_priority ));
PA_ENSURE( paInternalError );
}
}
}
else
#endif
PA_ENSURE( BoostPriority( self ) );

{
int policy;
struct sched_param spm;
pthread_getschedparam(self->thread, &policy, &spm);
}
PA_ENSURE( BoostPriority( self ) );
}

if( self->parentWaiting )
Expand Down Expand Up @@ -424,23 +383,6 @@ PaError PaUnixThread_Terminate( PaUnixThread* self, int wait, PaError* exitResul
{
*exitResult = paNoError;
}
#if 0
if( watchdogExitResult )
*watchdogExitResult = paNoError;

if( th->watchdogRunning )
{
pthread_cancel( th->watchdogThread );
PA_ENSURE_SYSTEM( pthread_join( th->watchdogThread, &pret ), 0 );

if( pret && pret != PTHREAD_CANCELED )
{
if( watchdogExitResult )
*watchdogExitResult = *(PaError *) pret;
free( pret );
}
}
#endif

/* Only kill the thread if it isn't in the process of stopping (flushing adaptation buffers) */
/* TODO: Make join time out */
Expand Down Expand Up @@ -563,164 +505,3 @@ PaError PaUnixMutex_Unlock( PaUnixMutex* self )
error:
return result;
}


#if 0
static void OnWatchdogExit( void *userData )
{
PaAlsaThreading *th = (PaAlsaThreading *) userData;
struct sched_param spm = { 0 };
assert( th );

PA_ASSERT_CALL( pthread_setschedparam( th->callbackThread, SCHED_OTHER, &spm ), 0 ); /* Lower before exiting */
PA_DEBUG(( "Watchdog exiting\n" ));
}

static void *WatchdogFunc( void *userData )
{
PaError result = paNoError, *pres = NULL;
int err;
PaAlsaThreading *th = (PaAlsaThreading *) userData;
unsigned intervalMsec = 500;
const PaTime maxSeconds = 3.; /* Max seconds between callbacks */
PaTime timeThen = PaUtil_GetTime(), timeNow, timeElapsed, cpuTimeThen, cpuTimeNow, cpuTimeElapsed;
double cpuLoad, avgCpuLoad = 0.;
int throttled = 0;

assert( th );

/* Execute OnWatchdogExit when exiting */
pthread_cleanup_push( &OnWatchdogExit, th );

/* Boost priority of callback thread */
PA_ENSURE( result = BoostPriority( th ) );
if( !result )
{
/* Boost failed, might as well exit */
pthread_exit( NULL );
}

cpuTimeThen = th->callbackCpuTime;
{
int policy;
struct sched_param spm = { 0 };
pthread_getschedparam( pthread_self(), &policy, &spm );
PA_DEBUG(( "%s: Watchdog priority is %d\n", __FUNCTION__, spm.sched_priority ));
}

while( 1 )
{
double lowpassCoeff = 0.9, lowpassCoeff1 = 0.99999 - lowpassCoeff;

/* Test before and after in case whatever underlying sleep call isn't interrupted by pthread_cancel */
pthread_testcancel();
Pa_Sleep( intervalMsec );
pthread_testcancel();

if( PaUtil_GetTime() - th->callbackTime > maxSeconds )
{
PA_DEBUG(( "Watchdog: Terminating callback thread\n" ));
/* Tell thread to terminate */
err = pthread_kill( th->callbackThread, SIGKILL );
pthread_exit( NULL );
}

PA_DEBUG(( "%s: PortAudio reports CPU load: %g\n", __FUNCTION__, PaUtil_GetCpuLoad( th->cpuLoadMeasurer ) ));

/* Check if we should throttle, or unthrottle :P */
cpuTimeNow = th->callbackCpuTime;
cpuTimeElapsed = cpuTimeNow - cpuTimeThen;
cpuTimeThen = cpuTimeNow;

timeNow = PaUtil_GetTime();
timeElapsed = timeNow - timeThen;
timeThen = timeNow;
cpuLoad = cpuTimeElapsed / timeElapsed;
avgCpuLoad = avgCpuLoad * lowpassCoeff + cpuLoad * lowpassCoeff1;
/*
if( throttled )
PA_DEBUG(( "Watchdog: CPU load: %g, %g\n", avgCpuLoad, cpuTimeElapsed ));
*/
if( PaUtil_GetCpuLoad( th->cpuLoadMeasurer ) > .925 )
{
static int policy;
static struct sched_param spm = { 0 };
static const struct sched_param defaultSpm = { 0 };
PA_DEBUG(( "%s: Throttling audio thread, priority %d\n", __FUNCTION__, spm.sched_priority ));

pthread_getschedparam( th->callbackThread, &policy, &spm );
if( !pthread_setschedparam( th->callbackThread, SCHED_OTHER, &defaultSpm ) )
{
throttled = 1;
}
else
PA_DEBUG(( "Watchdog: Couldn't lower priority of audio thread: %s\n", strerror( errno ) ));

/* Give other processes a go, before raising priority again */
PA_DEBUG(( "%s: Watchdog sleeping for %lu msecs before unthrottling\n", __FUNCTION__, th->throttledSleepTime ));
Pa_Sleep( th->throttledSleepTime );

/* Reset callback priority */
if( pthread_setschedparam( th->callbackThread, SCHED_FIFO, &spm ) != 0 )
{
PA_DEBUG(( "%s: Couldn't raise priority of audio thread: %s\n", __FUNCTION__, strerror( errno ) ));
}

if( PaUtil_GetCpuLoad( th->cpuLoadMeasurer ) >= .99 )
intervalMsec = 50;
else
intervalMsec = 100;

/*
lowpassCoeff = .97;
lowpassCoeff1 = .99999 - lowpassCoeff;
*/
}
else if( throttled && avgCpuLoad < .8 )
{
intervalMsec = 500;
throttled = 0;

/*
lowpassCoeff = .9;
lowpassCoeff1 = .99999 - lowpassCoeff;
*/
}
}

pthread_cleanup_pop( 1 ); /* Execute cleanup on exit */

error:
/* Shouldn't get here in the normal case */

/* Pass on error code */
pres = malloc( sizeof (PaError) );
*pres = result;

pthread_exit( pres );
}

static void CallbackUpdate( PaAlsaThreading *th )
{
th->callbackTime = PaUtil_GetTime();
th->callbackCpuTime = PaUtil_GetCpuLoad( th->cpuLoadMeasurer );
}

/*
static void *CanaryFunc( void *userData )
{
const unsigned intervalMsec = 1000;
PaUtilThreading *th = (PaUtilThreading *) userData;

while( 1 )
{
th->canaryTime = PaUtil_GetTime();

pthread_testcancel();
Pa_Sleep( intervalMsec );
}

pthread_exit( NULL );
}
*/
#endif
Loading