Changeset 914

Show
Ignore:
Timestamp:
03/08/08 05:29:58 (13 years ago)
Author:
ppalmers
Message:

- make the ctr read from dll lockless

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/libffado/src/libieee1394/CycleTimerHelper.cpp

    r912 r914  
    2727#include "ieee1394service.h" 
    2828#include "libutil/PosixThread.h" 
     29#include "libutil/Atomic.h" 
    2930 
    3031#define DLL_PI        (3.141592653589793238) 
     
    4849#define UPDATES_WITH_HIGH_BANDWIDTH \ 
    4950         (5000000 / IEEE1394SERVICE_CYCLETIMER_DLL_UPDATE_INTERVAL_USEC) 
    50  
    51 /* 
    52 #define ENTER_CRITICAL_SECTION { \ 
    53     if (pthread_mutex_trylock(&m_compute_vars_lock) == EBUSY) { \ 
    54         debugWarning(" (%p) lock clash\n", this); \ 
    55         ENTER_CRITICAL_SECTION; \ 
    56     } \ 
    57     } 
    58 */ 
    59 #define ENTER_CRITICAL_SECTION { \ 
    60     pthread_mutex_lock(&m_compute_vars_lock); \ 
    61     } 
    62 #define EXIT_CRITICAL_SECTION { \ 
    63     pthread_mutex_unlock(&m_compute_vars_lock); \ 
    64     } 
    6551 
    6652IMPL_DEBUG_MODULE( CycleTimerHelper, CycleTimerHelper, DEBUG_LEVEL_NORMAL ); 
     
    8167    , m_cycle_timer_ticks_prev ( 0 ) 
    8268    , m_high_bw_updates ( UPDATES_WITH_HIGH_BANDWIDTH ) 
     69    , m_current_shadow_idx ( 0 ) 
    8370    , m_Thread ( NULL ) 
    8471    , m_realtime ( false ) 
     
    10390    , m_cycle_timer_ticks_prev ( 0 ) 
    10491    , m_high_bw_updates ( UPDATES_WITH_HIGH_BANDWIDTH ) 
     92    , m_current_shadow_idx ( 0 ) 
    10593    , m_Thread ( NULL ) 
    10694    , m_realtime ( rt ) 
     
    159147{ 
    160148    debugOutput( DEBUG_LEVEL_VERBOSE, "Initialize %p...\n", this); 
    161     pthread_mutex_init(&m_compute_vars_lock, NULL); 
    162149    return true; 
    163150} 
     
    387374    } 
    388375 
    389     // FIXME: priority inversion possible, run this at higher prio than client threads 
    390     ENTER_CRITICAL_SECTION; 
    391     m_current_vars.ticks = (uint64_t)(m_current_time_ticks); 
    392     m_current_vars.usecs = (uint64_t)m_current_time_usecs; 
    393     m_current_vars.rate = getRate(); 
    394     EXIT_CRITICAL_SECTION; 
    395  
     376    // prepare the new compute vars 
     377    struct compute_vars new_vars; 
     378    new_vars.ticks = (uint64_t)(m_current_time_ticks); 
     379    new_vars.usecs = (uint64_t)m_current_time_usecs; 
     380    new_vars.rate = getRate(); 
     381     
     382    // get the next index 
     383    unsigned int next_idx = (m_current_shadow_idx + 1) % CTRHELPER_NB_SHADOW_VARS; 
     384     
     385    // check whether next index position is in use 
     386    while(m_shadow_usecount[next_idx] > 0) { 
     387        debugOutput(DEBUG_LEVEL_VERBOSE, 
     388                    "next shadow position still in use (pos: %d, %d uses)", 
     389                    next_idx, m_shadow_usecount[next_idx]); 
     390 
     391        // sleep for some time 
     392        m_TimeSource.SleepUsecRelative(100); 
     393    } 
     394    //debugOutputExtreme(DEBUG_LEVEL_VERBOSE, " updating %d\n", next_idx); 
     395 
     396    // the next index position is now unused, so we can update it 
     397    m_shadow_vars[next_idx] = new_vars; 
     398 
     399    // then we can update the current index 
     400    m_current_shadow_idx = next_idx; 
     401    //debugOutputExtreme(DEBUG_LEVEL_VERBOSE, " updated %d\n", m_current_shadow_idx); 
     402     
     403    // reclaim is not necessary since it's a preallocated array 
     404     
    396405    return true; 
    397406} 
     
    410419    struct compute_vars my_vars; 
    411420 
    412     // reduce lock contention 
    413     ENTER_CRITICAL_SECTION; 
    414     my_vars = m_current_vars; 
    415     EXIT_CRITICAL_SECTION; 
    416  
     421    // get pointer and prevent it from disappearing 
     422    // by marking it as in-use 
     423    unsigned int curr_idx; 
     424    do { 
     425        // get the current shadow var set idx 
     426        curr_idx = m_current_shadow_idx; 
     427        // mark it as used 
     428        INC_ATOMIC(&m_shadow_usecount[curr_idx]); 
     429     
     430        // check whether the pointer changed between getting the idx 
     431        // and marking it as used 
     432        if (curr_idx != m_current_shadow_idx) { 
     433            debugOutput(DEBUG_LEVEL_VERBOSE, 
     434                        "pointer (%d) changed to (%d) while marking it as used\n", 
     435                        curr_idx, m_current_shadow_idx); 
     436            // undo in-use marking 
     437            DEC_ATOMIC(&m_shadow_usecount[curr_idx]); 
     438            // this requires a retry to obtain the new pointer 
     439        } 
     440    } while(curr_idx != m_current_shadow_idx); // retry if needed 
     441    //debugOutputExtreme(DEBUG_LEVEL_VERBOSE, " using %d\n",curr_idx); 
     442 
     443    // copy the contents 
     444    my_vars = m_shadow_vars[curr_idx]; 
     445     
     446    // release the pointer 
     447    DEC_ATOMIC(&m_shadow_usecount[curr_idx]); 
     448     
    417449    int64_t time_diff = now - my_vars.usecs; 
    418450    double y_step_in_ticks = ((double)time_diff) * my_vars.rate; 
  • trunk/libffado/src/libieee1394/CycleTimerHelper.h

    r880 r914  
    109109    uint32_t m_usecs_per_update; 
    110110 
    111     float               m_avg_wakeup_delay;  
     111    float    m_avg_wakeup_delay;  
    112112 
    113113    // state variables 
     
    132132    }; 
    133133 
    134     struct compute_vars m_current_vars; 
    135     pthread_mutex_t m_compute_vars_lock; 
     134    #define CTRHELPER_NB_SHADOW_VARS 8 
     135    struct compute_vars m_shadow_vars[CTRHELPER_NB_SHADOW_VARS]; 
     136    SInt32 m_shadow_usecount[CTRHELPER_NB_SHADOW_VARS]; 
     137    unsigned int m_current_shadow_idx; 
    136138 
    137139    // Threading 
  • trunk/libffado/src/libieee1394/ieee1394service.cpp

    r909 r914  
    7878    , m_pIsoManager( new IsoHandlerManager( *this, rt, prio ) ) 
    7979    , m_pCTRHelper ( new CycleTimerHelper( *this, IEEE1394SERVICE_CYCLETIMER_DLL_UPDATE_INTERVAL_USEC, 
    80                                            rt, prio + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE ) ) 
     80                                           rt && IEEE1394SERVICE_CYCLETIMER_HELPER_RUN_REALTIME, 
     81                                           prio + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE ) ) 
    8182    , m_have_new_ctr_read ( false ) 
    8283    , m_pTimeSource ( new Util::SystemTimeSource() ) 
     
    287288    if (m_pCTRHelper) { 
    288289        debugOutput(DEBUG_LEVEL_VERBOSE, "Switching CycleTimerHelper to (rt=%d, prio=%d)\n",  
    289                                          rt, priority + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE); 
    290         result &= m_pCTRHelper->setThreadParameters(rt, priority + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE); 
     290                                         rt && IEEE1394SERVICE_CYCLETIMER_HELPER_RUN_REALTIME, 
     291                                         priority + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE); 
     292        result &= m_pCTRHelper->setThreadParameters(rt && IEEE1394SERVICE_CYCLETIMER_HELPER_RUN_REALTIME, 
     293                                                    priority + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE); 
    291294    } 
    292295    return result;