Ignore:
Timestamp:
02/25/02 12:20:39 (9 years ago)
Author:
philburk
Message:

If watchdog detects canary getting starved, then just lower audio thread
priority instead of killing it. If audio completely hung then still kill it.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • portaudio/trunk/pa_unix_oss/pa_unix_oss.c

    r124 r127  
    9999#include <memory.h> 
    100100#include <math.h> 
    101 #include "portaudio.h" 
    102 #include "pa_host.h" 
    103 #include "pa_trace.h" 
    104  
    105101#include <sys/ioctl.h> 
    106102#include <sys/time.h> 
     
    108104#include <unistd.h> 
    109105#include <signal.h> 
    110 #include <stdio.h> 
    111 #include <stdlib.h> 
     106#include <sched.h> 
     107#include <pthread.h> 
     108#include <errno.h> 
    112109 
    113110#ifdef __linux__ 
     
    117114#endif 
    118115 
    119 #include <sched.h> 
    120 #include <pthread.h> 
    121  
     116#include "portaudio.h" 
     117#include "pa_host.h" 
     118#include "pa_trace.h" 
    122119 
    123120#define PRINT(x)   { printf x; fflush(stdout); } 
     
    160157    int              pahsc_AudioPriority;          /* priority of background audio thread */ 
    161158    pthread_t        pahsc_AudioThread;            /* background audio thread */ 
     159    pid_t            pahsc_AudioThreadPID;         /* background audio thread */ 
    162160    pthread_t        pahsc_WatchDogThread;         /* highest priority thread that protects system */ 
     161    int              pahsc_WatchDogRun;           /* Ask WatchDog to stop. */ 
    163162    pthread_t        pahsc_CanaryThread;           /* low priority thread that detects abuse by audio */ 
    164163    struct timeval   pahsc_CanaryTime; 
     164    int              pahsc_CanaryRun;             /* Ask Canary to stop. */ 
    165165    short           *pahsc_NativeInputBuffer; 
    166166    short           *pahsc_NativeOutputBuffer; 
     
    543543static int PaHost_CanaryProc( PaHostSoundControl   *pahsc ) 
    544544{ 
    545     int   result; 
     545    int   result = 0; 
    546546 
    547547#ifdef GNUSTEP 
     
    549549#endif 
    550550 
    551     while( (result = usleep( WATCHDOG_INTERVAL_USEC )) == 0 ) 
     551    while( pahsc->pahsc_CanaryRun && ((result = usleep( WATCHDOG_INTERVAL_USEC )) == 0) ) 
    552552    {  
    553553        gettimeofday( &pahsc->pahsc_CanaryTime, NULL ); 
     
    564564 
    565565/******************************************************************************************* 
    566  * Monitor audio thread and kill it if it hogs the CPU. 
     566 * Monitor audio thread and lower its it if it hogs the CPU. 
    567567 * To prevent getting killed, the audio thread must update a 
    568568 * variable with a timer value. 
     
    595595    /* Compare watchdog time with audio and canary thread times. */ 
    596596    /* Sleep for a while or until thread cancelled. */ 
    597     while( (result = usleep( WATCHDOG_INTERVAL_USEC )) == 0 ) 
     597    while( pahsc->pahsc_WatchDogRun && ((result = usleep( WATCHDOG_INTERVAL_USEC )) == 0) ) 
    598598    { 
    599599        int              delta; 
     
    602602        gettimeofday( &currentTime, NULL ); 
    603603 
    604         /* If audio thread is not advancing, then kill it. */ 
     604        /* If audio thread is not advancing, then lower its priority. */ 
    605605        delta = currentTime.tv_sec - pahsc->pahsc_EntryTime.tv_sec; 
    606606        DBUG(("PaHost_WatchDogProc: audio delta = %d\n", delta )); 
    607607        if( delta > WATCHDOG_MAX_SECONDS ) 
    608608        { 
    609             ERR_RPT(("PaHost_WatchDogProc: killing hung audio thread!\n")); 
    610609            goto killAudio; 
    611610        } 
     
    615614        if( delta > WATCHDOG_MAX_SECONDS ) 
    616615        { 
    617             ERR_RPT(("PaHost_WatchDogProc: canary died! Killing runaway audio thread!\n")); 
    618             goto killAudio; 
     616            ERR_RPT(("PaHost_WatchDogProc: canary died!\n")); 
     617            goto lowerAudio; 
    619618        } 
    620619    } 
     
    626625    return 0; 
    627626     
     627lowerAudio: 
     628    { 
     629        struct sched_param    schat = { 0 }; 
     630        if( sched_setscheduler(pahsc->pahsc_AudioThreadPID, SCHED_OTHER, &schat) != 0) 
     631        { 
     632            ERR_RPT(("PaHost_WatchDogProc: failed to lower audio priority. errno = %d\n", errno )); 
     633            /* Fall through into killing audio thread. */ 
     634        } 
     635        else 
     636        { 
     637            ERR_RPT(("PaHost_WatchDogProc: lowered audio priority to prevent hogging of CPU.\n")); 
     638            goto cleanup; 
     639        } 
     640    } 
     641     
    628642killAudio: 
     643    ERR_RPT(("PaHost_WatchDogProc: killing hung audio thread!\n")); 
    629644    pthread_kill( pahsc->pahsc_AudioThread, SIGKILL ); 
     645 
     646cleanup: 
     647    pahsc->pahsc_CanaryRun = 0; 
     648    DBUG(("PaHost_WatchDogProc: cancel Canary\n")); 
    630649    pthread_cancel( pahsc->pahsc_CanaryThread ); 
     650    DBUG(("PaHost_WatchDogProc: join Canary\n")); 
    631651    pthread_join( pahsc->pahsc_CanaryThread, NULL ); 
     652    DBUG(("PaHost_WatchDogProc: forget Canary\n")); 
    632653    pahsc->pahsc_CanaryThread = INVALID_THREAD; 
    633     pahsc->pahsc_WatchDogThread = INVALID_THREAD; 
    634654     
    635655#ifdef GNUSTEP 
     
    645665    if( pahsc->pahsc_WatchDogThread != INVALID_THREAD ) 
    646666    { 
     667        pahsc->pahsc_WatchDogRun = 0; 
     668        DBUG(("PaHost_StopWatchDog: cancel WatchDog\n")); 
    647669        pthread_cancel( pahsc->pahsc_WatchDogThread ); 
    648670        pthread_join( pahsc->pahsc_WatchDogThread, NULL ); 
     
    652674    if( pahsc->pahsc_CanaryThread != INVALID_THREAD ) 
    653675    { 
     676        pahsc->pahsc_CanaryRun = 0; 
     677        DBUG(("PaHost_StopWatchDog: cancel Canary\n")); 
    654678        pthread_cancel( pahsc->pahsc_CanaryThread ); 
     679        DBUG(("PaHost_StopWatchDog: join Canary\n")); 
    655680        pthread_join( pahsc->pahsc_CanaryThread, NULL ); 
    656681        pahsc->pahsc_CanaryThread = INVALID_THREAD; 
     
    669694 
    670695    /* Launch a canary thread to detect priority abuse. */ 
     696    pahsc->pahsc_CanaryRun = 1; 
    671697    hres = pthread_create(&(pahsc->pahsc_CanaryThread), 
    672698                      NULL /*pthread_attr_t * attr*/, 
     
    681707 
    682708    /* Launch a watchdog thread to prevent runaway audio thread. */ 
     709    pahsc->pahsc_WatchDogRun = 1; 
    683710    hres = pthread_create(&(pahsc->pahsc_WatchDogThread), 
    684711                      NULL /*pthread_attr_t * attr*/, 
     
    711738    if( pahsc == NULL ) return paInternalError; 
    712739         
     740    pahsc->pahsc_AudioThreadPID = getpid(); 
     741    DBUG(("PaHost_BoostPriority: audio PID = %d\n", pahsc->pahsc_AudioThreadPID )); 
     742     
    713743    /* Choose a priority in the middle of the range. */ 
    714744    pahsc->pahsc_AudioPriority = (sched_get_priority_max(SCHEDULER_POLICY) - 
     
    807837        pahsc->pahsc_LastPosPtr = info.bytes; 
    808838    } 
    809  
     839    DBUG(("Pa_AudioThreadProc: left audio loop.\n")); 
     840     
    810841    past->past_IsActive = 0; 
    811  
    812842    PaHost_StopWatchDog( pahsc ); 
    813843     
     844error: 
    814845    DBUG(("leaving audio thread.\n")); 
    815 error: 
    816846#ifdef GNUSTEP 
    817847    GSUnregisterCurrentThread();  /* SB20010904 */ 
Note: See TracChangeset for help on using the changeset viewer.