Changeset 752

Show
Ignore:
Timestamp:
12/02/07 07:49:37 (16 years ago)
Author:
ppalmers
Message:

- Implement a DLL based mechanism to read the cycle timer. This can potentially be more lightweight for the reader threads since it avoids a the CTR read kernel call. It also has the
side effect that FFADO now works on older kernels that don't implement the cycle timer read call.

Files:

Legend:

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

    r750 r752  
    2727#include "cycletimer.h" 
    2828#include "IsoHandlerManager.h" 
     29#include "CycleTimerHelper.h" 
    2930 
    3031#include <libavc1394/avc1394.h> 
     
    3233#include <libiec61883/iec61883.h> 
    3334 
     35#include "libutil/SystemTimeSource.h" 
     36 
    3437#include <errno.h> 
    3538#include <netinet/in.h> 
     
    4245#define FFADO_MAX_FIREWIRE_PORTS 16 
    4346 
     47#define ISOMANAGER_PRIO_INCREASE         5 
     48#define CYCLETIMER_HELPER_PRIO_INCREASE  6 
     49 
    4450IMPL_DEBUG_MODULE( Ieee1394Service, Ieee1394Service, DEBUG_LEVEL_NORMAL ); 
    4551 
    4652Ieee1394Service::Ieee1394Service() 
    47     : m_handle( 0 ), m_resetHandle( 0 ), m_rtHandle( 0 ) 
     53    : m_handle( 0 ), m_resetHandle( 0 ), m_util_handle( 0 ) 
    4854    , m_port( -1 ) 
    4955    , m_threadRunning( false ) 
    50     , m_isoManager( new IsoHandlerManager( *this ) ) 
     56    , m_realtime ( false ) 
     57    , m_base_priority ( 0 ) 
     58    , m_pIsoManager( new IsoHandlerManager( *this ) ) 
     59    , m_pCTRHelper ( new CycleTimerHelper( *this, 1000 ) ) 
     60    , m_have_new_ctr_read ( false ) 
     61    , m_pTimeSource ( new Util::SystemTimeSource() ) 
    5162{ 
    5263    pthread_mutex_init( &m_mutex, 0 ); 
     
    6374} 
    6475 
     76Ieee1394Service::Ieee1394Service(bool rt, int prio) 
     77    : m_handle( 0 ), m_resetHandle( 0 ), m_util_handle( 0 ) 
     78    , m_port( -1 ) 
     79    , m_threadRunning( false ) 
     80    , m_realtime ( rt ) 
     81    , m_base_priority ( prio ) 
     82    , m_pIsoManager( new IsoHandlerManager( *this, rt, prio + ISOMANAGER_PRIO_INCREASE ) ) 
     83    , m_pCTRHelper ( new CycleTimerHelper( *this, 1000, rt, prio + CYCLETIMER_HELPER_PRIO_INCREASE ) ) 
     84    , m_have_new_ctr_read ( false ) 
     85    , m_pTimeSource ( new Util::SystemTimeSource() ) 
     86{ 
     87    pthread_mutex_init( &m_mutex, 0 ); 
     88 
     89    for (unsigned int i=0; i<64; i++) { 
     90        m_channels[i].channel=-1; 
     91        m_channels[i].bandwidth=-1; 
     92        m_channels[i].alloctype=AllocFree; 
     93        m_channels[i].xmit_node=0xFFFF; 
     94        m_channels[i].xmit_plug=-1; 
     95        m_channels[i].recv_node=0xFFFF; 
     96        m_channels[i].recv_plug=-1; 
     97    } 
     98} 
     99 
    65100Ieee1394Service::~Ieee1394Service() 
    66101{ 
    67     delete m_isoManager; 
     102    delete m_pCTRHelper; 
     103    delete m_pIsoManager; 
     104    delete m_pTimeSource; 
    68105    stopRHThread(); 
    69106    for ( arm_handler_vec_t::iterator it = m_armHandlers.begin(); 
     
    85122        raw1394_destroy_handle( m_resetHandle ); 
    86123    } 
    87     if ( m_rtHandle ) { 
    88         raw1394_destroy_handle( m_rtHandle ); 
     124    if ( m_util_handle ) { 
     125        raw1394_destroy_handle( m_util_handle ); 
    89126    } 
    90127} 
     
    137174        return false; 
    138175    } 
    139      
    140     m_rtHandle = raw1394_new_handle_on_port( port ); 
    141     if ( !m_rtHandle ) { 
     176 
     177    m_util_handle = raw1394_new_handle_on_port( port ); 
     178    if ( !m_util_handle ) { 
    142179        if ( !errno ) { 
    143180            debugFatal("libraw1394 not compatible\n"); 
     
    156193    err=raw1394_read_cycle_timer(m_handle, &cycle_timer, &local_time); 
    157194    if(err) { 
    158         debugError("raw1394_read_cycle_timer failed.\n"); 
    159         debugError(" Error: %s\n", strerror(err)); 
    160         debugError(" Your system doesn't seem to support the raw1394_read_cycle_timer call\n"); 
    161         return false; 
     195        debugOutput(DEBUG_LEVEL_VERBOSE, "raw1394_read_cycle_timer failed.\n"); 
     196        debugOutput(DEBUG_LEVEL_VERBOSE, " Error descr: %s\n", strerror(err)); 
     197        debugWarning("==================================================================\n"); 
     198        debugWarning(" This system doesn't support the raw1394_read_cycle_timer call.   \n"); 
     199        debugWarning(" Fallback to indirect CTR read method.                            \n"); 
     200        debugWarning(" FFADO should work, but achieving low-latency might be a problem. \n"); 
     201        debugWarning(" Upgrade the kernel to version 2.6.21 or higher to solve this.    \n"); 
     202        debugWarning("==================================================================\n"); 
     203        m_have_new_ctr_read = false; 
     204    } else { 
     205        debugOutput(DEBUG_LEVEL_NORMAL, "This system supports the raw1394_read_cycle_timer call, using it.\n"); 
     206        m_have_new_ctr_read = true; 
    162207    } 
    163208 
     
    190235    raw1394_set_userdata( m_handle, this ); 
    191236    raw1394_set_userdata( m_resetHandle, this ); 
    192     raw1394_set_userdata( m_rtHandle, this ); 
     237    raw1394_set_userdata( m_util_handle, this ); 
    193238    raw1394_set_bus_reset_handler( m_resetHandle, 
    194239                                   this->resetHandlerLowLevel ); 
     
    197242                                   this->armHandlerLowLevel ); 
    198243 
    199     if(!m_isoManager) { 
     244    if(!m_pCTRHelper) { 
     245        debugFatal("No CycleTimerHelper available, bad!\n"); 
     246        return false; 
     247    } 
     248    m_pCTRHelper->setVerboseLevel(getDebugLevel()); 
     249    if(!m_pCTRHelper->Start()) { 
     250        debugFatal("Could not start CycleTimerHelper\n"); 
     251        return false; 
     252    } 
     253 
     254    if(!m_pIsoManager) { 
    200255        debugFatal("No IsoHandlerManager available, bad!\n"); 
    201256        return false; 
    202257    } 
    203     m_isoManager->setVerboseLevel(getDebugLevel()); 
    204     if(!m_isoManager->init()) { 
     258    m_pIsoManager->setVerboseLevel(getDebugLevel()); 
     259    if(!m_pIsoManager->init()) { 
    205260        debugFatal("Could not initialize IsoHandlerManager\n"); 
    206261        return false; 
     
    208263 
    209264    startRHThread(); 
     265 
     266    // make sure that the thread parameters of all our helper threads are OK 
     267    if(!setThreadParameters(m_realtime, m_base_priority)) { 
     268        debugFatal("Could not set thread parameters\n"); 
     269        return false; 
     270    } 
    210271    return true; 
    211272} 
     
    213274bool 
    214275Ieee1394Service::setThreadParameters(bool rt, int priority) { 
    215     if (m_isoManager) { 
    216         return m_isoManager->setThreadParameters(rt, priority); 
     276    if (priority > 98) priority = 98; 
     277    m_base_priority = priority; 
     278    m_realtime = rt; 
     279    if (m_pIsoManager) { 
     280        return m_pIsoManager->setThreadParameters(rt, priority + ISOMANAGER_PRIO_INCREASE); 
    217281    } else { 
    218282        return true; 
    219283    } 
     284    if (m_pCTRHelper) { 
     285        return m_pCTRHelper->setThreadParameters(rt, priority + CYCLETIMER_HELPER_PRIO_INCREASE); 
     286    } else { 
     287        return true; 
     288    } 
    220289} 
    221290 
     
    236305 */ 
    237306 
    238 unsigned in
     307uint32_
    239308Ieee1394Service::getCycleTimerTicks() { 
    240     // the new api should be realtime safe. 
    241     // it might cause a reschedule when turning preemption, 
    242     // back on but that won't hurt us if we have sufficient 
    243     // priority 
    244     int err; 
    245     uint32_t cycle_timer; 
    246     uint64_t local_time; 
    247     err=raw1394_read_cycle_timer(m_rtHandle, &cycle_timer, &local_time); 
    248     if(err) { 
    249         debugWarning("raw1394_read_cycle_timer: %s\n", strerror(err)); 
    250     } 
    251     return CYCLE_TIMER_TO_TICKS(cycle_timer); 
     309    return m_pCTRHelper->getCycleTimerTicks(); 
    252310} 
    253311 
     
    258316 */ 
    259317 
    260 unsigned in
     318uint32_
    261319Ieee1394Service::getCycleTimer() { 
    262320    // the new api should be realtime safe. 
     
    267325    uint32_t cycle_timer; 
    268326    uint64_t local_time; 
    269     err=raw1394_read_cycle_timer(m_rtHandle, &cycle_timer, &local_time); 
     327    err=raw1394_read_cycle_timer(m_util_handle, &cycle_timer, &local_time); 
    270328    if(err) { 
    271329        debugWarning("raw1394_read_cycle_timer: %s\n", strerror(err)); 
    272330    } 
    273331    return cycle_timer; 
     332} 
     333 
     334bool 
     335Ieee1394Service::readCycleTimerReg(uint32_t *cycle_timer, uint64_t *local_time) 
     336{ 
     337    if(m_have_new_ctr_read) { 
     338        int err; 
     339        err = raw1394_read_cycle_timer(m_util_handle, cycle_timer, local_time); 
     340        if(err) { 
     341            debugWarning("raw1394_read_cycle_timer: %s\n", strerror(err)); 
     342            return false; 
     343        } 
     344        return true; 
     345    } else { 
     346        // do a normal read of the CTR register 
     347        // the disadvantage is that local_time and cycle time are not 
     348        // read at the same time instant (scheduling issues) 
     349        *local_time = getCurrentTimeAsUsecs(); 
     350        if ( raw1394_read( m_util_handle, 
     351                getLocalNodeId() | 0xFFC0, 
     352                CSR_REGISTER_BASE | CSR_CYCLE_TIME, 
     353                sizeof(uint32_t), cycle_timer ) == 0 ) { 
     354            *cycle_timer = ntohl(*cycle_timer); 
     355            return true; 
     356        } else { 
     357            return false; 
     358        } 
     359    } 
     360} 
     361 
     362uint64_t 
     363Ieee1394Service::getCurrentTimeAsUsecs() { 
     364    assert(m_pTimeSource); 
     365    return m_pTimeSource->getCurrentTimeAsUsecs(); 
    274366} 
    275367 
     
    501593    // do a simple read on ourself in order to update the internal structures 
    502594    // this avoids failures after a bus reset 
    503     read_quadlet( getLocalNodeId() & 0xFFC0, 
     595    read_quadlet( getLocalNodeId() | 0xFFC0, 
    504596                  CSR_REGISTER_BASE | CSR_CYCLE_TIME, 
    505597                  &buf ); 
     
    9741066Ieee1394Service::setVerboseLevel(int l) 
    9751067{ 
    976     if (m_isoManager) m_isoManager->setVerboseLevel(l); 
     1068    if (m_pIsoManager) m_pIsoManager->setVerboseLevel(l); 
     1069    if (m_pCTRHelper) m_pCTRHelper->setVerboseLevel(l); 
    9771070    setDebugLevel(l); 
    9781071    debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l ); 
     
    9851078    debugOutput( DEBUG_LEVEL_VERBOSE, " Name: %s\n", getPortName().c_str() ); 
    9861079    debugOutputShort( DEBUG_LEVEL_NORMAL, "Iso handler info:\n"); 
    987     if (m_isoManager) m_isoManager->dumpInfo(); 
    988 } 
     1080    if (m_pIsoManager) m_pIsoManager->dumpInfo(); 
     1081} 
  • trunk/libffado/src/libieee1394/ieee1394service.h

    r750 r752  
    4141class ARMHandler; 
    4242class IsoHandlerManager; 
     43class CycleTimerHelper; 
     44 
     45namespace Util { 
     46    class TimeSource; 
     47} 
    4348 
    4449class Ieee1394Service : public IEC61883 { 
    4550public: 
    4651    Ieee1394Service(); 
     52    Ieee1394Service(bool rt, int prio); 
    4753    ~Ieee1394Service(); 
    4854 
     
    94100    nodeid_t getLocalNodeId(); 
    95101 
    96     /// get the most recent cycle timer value (in ticks) 
    97     unsigned int getCycleTimerTicks(); 
    98     /// get the most recent cycle timer value (as is) 
    99     unsigned int getCycleTimer(); 
    100  
    101  
    102    /** 
    103     * @brief send async read request to a node and wait for response. 
    104     * 
    105     * This does the complete transaction and will return when it's finished. 
    106     * 
    107     * @param node target node (\todo needs 0xffc0 stuff) 
    108     * @param addr address to read from 
    109     * @param length amount of data to read in quadlets 
    110     * @param buffer pointer to buffer where data will be saved 
    111  
    112     * @return true on success or false on failure (sets errno) 
    113     */ 
     102    /** 
     103     * @brief get the most recent cycle timer value (in ticks) 
     104     * 
     105     * @note Uses the most appropriate method for getting the cycle timer 
     106     *       which is not necessarily a direct read (could be DLL) 
     107     */ 
     108    uint32_t getCycleTimerTicks(); 
     109 
     110    /** 
     111     * @brief get the most recent cycle timer value (in CTR format) 
     112     * 
     113     * @note Uses the most appropriate method for getting the cycle timer 
     114     *       which is not necessarily a direct read (could be DLL) 
     115     */ 
     116    uint32_t getCycleTimer(); 
     117 
     118    /** 
     119     * @brief read the cycle timer value from the controller (in CTR format) 
     120     * 
     121     * @note Uses a direct method to read the value from the controller 
     122     * @return true if successful 
     123     */ 
     124    bool readCycleTimerReg(uint32_t *cycle_timer, uint64_t *local_time); 
     125 
     126    /** 
     127     * @brief provide the current system time 
     128     * @return  
     129     */ 
     130    uint64_t getCurrentTimeAsUsecs(); 
     131 
     132    /** 
     133     * @brief send async read request to a node and wait for response. 
     134     * 
     135     * This does the complete transaction and will return when it's finished. 
     136     * 
     137     * @param node target node (\todo needs 0xffc0 stuff) 
     138     * @param addr address to read from 
     139     * @param length amount of data to read in quadlets 
     140     * @param buffer pointer to buffer where data will be saved 
     141     * 
     142     * @return true on success or false on failure (sets errno) 
     143     */ 
    114144    bool read( fb_nodeid_t nodeId, 
    115145           fb_nodeaddr_t addr, 
     
    221251    bool freeIsoChannel(signed int channel); 
    222252 
    223     IsoHandlerManager& getIsoHandlerManager() {return *m_isoManager;}; 
     253    IsoHandlerManager& getIsoHandlerManager() {return *m_pIsoManager;}; 
    224254private: 
    225255    enum EAllocType { 
     
    267297    raw1394handle_t m_handle; 
    268298    raw1394handle_t m_resetHandle; 
    269     raw1394handle_t m_rtHandle; // a handle for operations from the rt thread 
     299    raw1394handle_t m_util_handle; // a handle for operations from the rt thread 
    270300    int             m_port; 
    271301    std::string     m_portName; 
     
    275305    bool            m_threadRunning; 
    276306 
    277     IsoHandlerManager*      m_isoManager; 
     307    bool            m_realtime; 
     308    int             m_base_priority; 
     309 
     310    IsoHandlerManager*      m_pIsoManager; 
     311    CycleTimerHelper*       m_pCTRHelper; 
     312    bool                    m_have_new_ctr_read; 
     313 
     314    // the time source 
     315    Util::TimeSource*   m_pTimeSource; 
    278316 
    279317    typedef std::vector< Functor* > reset_handler_vec_t; 
  • trunk/libffado/src/libieee1394/IsoHandlerManager.cpp

    r750 r752  
    3535#define PACKETS_PER_INTERRUPT          4U 
    3636 
    37 #define FFADO_ISOHANDLERMANAGER_PRIORITY_INCREASE 7 
    38  
    3937IMPL_DEBUG_MODULE( IsoHandlerManager, IsoHandlerManager, DEBUG_LEVEL_NORMAL ); 
    4038 
     
    4543   , m_service( service ) 
    4644   , m_poll_timeout(100), m_poll_nfds_shadow(0) 
    47    , m_realtime(false), m_priority(0), m_xmit_nb_frames( 20
     45   , m_realtime(false), m_priority(0), m_isoManagerThread ( NULL
    4846{} 
    4947 
    50 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service, bool run_rt, unsigned int rt_prio) 
     48IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service, bool run_rt, int rt_prio) 
    5149   : m_State(E_Created) 
    5250   , m_service( service ) 
    5351   , m_poll_timeout(100), m_poll_nfds_shadow(0) 
    54    , m_realtime(run_rt), m_priority(rt_prio), m_xmit_nb_frames( 20
     52   , m_realtime(run_rt), m_priority(rt_prio), m_isoManagerThread ( NULL
    5553{} 
    5654 
     
    6260bool 
    6361IsoHandlerManager::setThreadParameters(bool rt, int priority) { 
     62    if (priority > 98) priority = 98; // cap the priority 
     63    m_realtime = rt; 
     64    m_priority = priority; 
     65 
    6466    if (m_isoManagerThread) { 
    6567        if (rt) { 
    66             unsigned int prio = priority + FFADO_ISOHANDLERMANAGER_PRIORITY_INCREASE; 
    67             if (prio > 98) prio = 98; 
    68             m_isoManagerThread->AcquireRealTime(prio); 
     68            m_isoManagerThread->AcquireRealTime(m_priority); 
    6969        } else { 
    7070            m_isoManagerThread->DropRealTime(); 
    7171        } 
    7272    } 
    73     m_realtime = rt; 
    74     m_priority = priority; 
    7573    return true; 
    7674} 
     
    8785    // the tread that performs the actual packet transfer 
    8886    // needs high priority 
    89     unsigned int prio = m_priority + FFADO_ISOHANDLERMANAGER_PRIORITY_INCREASE; 
    90     debugOutput( DEBUG_LEVEL_VERBOSE, " thread should have prio %d, base is %d...\n", prio, m_priority); 
    91  
    92     if (prio > 98) prio = 98; 
     87    if (m_priority > 98) m_priority = 98; 
    9388    m_isoManagerThread = new Util::PosixThread( 
    9489        this, 
    95         m_realtime, prio
     90        m_realtime, m_priority
    9691        PTHREAD_CANCEL_DEFERRED); 
    9792 
     
    183178{ 
    184179    int err; 
    185     int i; 
     180    unsigned int i; 
    186181 
    187182    // update the shadow variables if requested 
     
    269264IsoHandlerManager::requestShadowUpdate() { 
    270265    debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n"); 
    271     int i; 
    272266 
    273267    if (m_isoManagerThread == NULL) { 
     
    757751} 
    758752 
    759  
    760753void IsoHandlerManager::setVerboseLevel(int i) { 
    761754    setDebugLevel(i); 
  • trunk/libffado/src/libieee1394/IsoHandlerManager.h

    r750 r752  
    7373 
    7474        IsoHandlerManager(Ieee1394Service& service); 
    75         IsoHandlerManager(Ieee1394Service& service, bool run_rt, unsigned int rt_prio); 
     75        IsoHandlerManager(Ieee1394Service& service, bool run_rt, int rt_prio); 
    7676        virtual ~IsoHandlerManager(); 
    7777 
     
    8080        void setPollTimeout(int t) {m_poll_timeout=t;}; ///< set the timeout used for poll() 
    8181        int getPollTimeout() {return m_poll_timeout;};  ///< get the timeout used for poll() 
    82  
    83         void setTransmitBufferNbFrames(unsigned int t) {m_xmit_nb_frames = t;}; 
    84         int getTransmitBufferNbFrames() {return m_xmit_nb_frames;}; 
    8582 
    8683        void setVerboseLevel(int l); ///< set the verbose level 
     
    177174        // threading 
    178175        bool m_realtime; 
    179         unsigned int m_priority; 
     176        int m_priority; 
    180177        Util::PosixThread *m_isoManagerThread; 
    181  
    182         // the preferred number of packets to buffer on xmit 
    183         unsigned int m_xmit_nb_frames; 
    184178 
    185179        // debug stuff 
  • trunk/libffado/src/SConscript

    r751 r752  
    6060        libieee1394/configrom.cpp \ 
    6161        libieee1394/csr1212.c \ 
     62        libieee1394/CycleTimerHelper.cpp \ 
    6263        libieee1394/ieee1394service.cpp \ 
    6364        libieee1394/IEC61883.cpp \ 
  • trunk/libffado/tests/test-ieee1394service.cpp

    r742 r752  
    3838#include "src/threads.h" 
    3939 
     40#include "src/libieee1394/cycletimer.h" 
    4041#include "src/libieee1394/configrom.h" 
    4142#include "src/libieee1394/ieee1394service.h" 
     
    6566int main(int argc, char *argv[]) 
    6667{ 
     68    setDebugLevel(DEBUG_LEVEL_VERBOSE); 
    6769    signal (SIGINT, sighandler); 
    6870    signal (SIGPIPE, sighandler); 
     71 
     72    const int PORT_TO_USE = 0; 
    6973 
    7074    printf("FFADO Ieee1394Service test application\n"); 
     
    7377 
    7478    m_service=new Ieee1394Service(); 
    75     m_service->initialize(2); 
     79    m_service->setVerboseLevel(DEBUG_LEVEL_VERBOSE ); 
     80    m_service->initialize(PORT_TO_USE); 
     81    m_service->setThreadParameters(true, 20); 
    7682 
    7783    MyFunctor *test_busreset=new MyFunctor(); 
     
    109115    } 
    110116 
     117    raw1394handle_t m_handle = raw1394_new_handle_on_port( PORT_TO_USE ); 
     118    if ( !m_handle ) { 
     119        if ( !errno ) { 
     120            debugFatal("libraw1394 not compatible\n"); 
     121        } else { 
     122            debugFatal("Ieee1394Service::initialize: Could not get 1394 handle: %s\n", 
     123                strerror(errno) ); 
     124            debugFatal("Is ieee1394 and raw1394 driver loaded?\n"); 
     125        } 
     126        exit(-1); 
     127    } 
     128 
    111129    while(run) { 
    112130        fflush(stderr); 
    113131        fflush(stdout); 
    114         sleep(1); 
     132        usleep(900*1000); 
     133 
     134        uint32_t cycle_timer; 
     135        uint64_t local_time; 
     136        // read the CTR 'raw' from a handle 
     137        // and read it from the 1394 service, which uses a DLL 
     138        int err = raw1394_read_cycle_timer(m_handle, &cycle_timer, &local_time); 
     139        uint64_t ctr = CYCLE_TIMER_TO_TICKS( cycle_timer ); 
     140        uint64_t ctr_dll = m_service->getCycleTimerTicks(); 
     141 
     142        if(err) { 
     143            debugError("CTR read error\n"); 
     144        } 
     145        debugOutput ( DEBUG_LEVEL_VERBOSE, 
     146                    "Cycle timer: %011llu (%03us %04ucy %04uticks)\n", 
     147                    ctr, (unsigned int)TICKS_TO_SECS( ctr ), 
     148                    (unsigned int)TICKS_TO_CYCLES( ctr ), (unsigned int)TICKS_TO_OFFSET( ctr ) ); 
     149        debugOutput ( DEBUG_LEVEL_VERBOSE, 
     150                    "   from DLL: %011llu (%03us %04ucy %04uticks)\n", 
     151                    ctr_dll, (unsigned int)TICKS_TO_SECS( ctr_dll ), 
     152                    (unsigned int)TICKS_TO_CYCLES( ctr_dll ), (unsigned int)TICKS_TO_OFFSET( ctr_dll ) ); 
     153        int64_t diff = diffTicks(ctr, ctr_dll); 
     154        uint64_t abs_diff; 
     155        if (diff < 0) { 
     156            abs_diff = -diff; 
     157        } else { 
     158            abs_diff = diff; 
     159        } 
     160        debugOutput ( DEBUG_LEVEL_VERBOSE, 
     161                    "      diff: %s%011llu (%03us %04ucy %04uticks)\n", 
     162                    ((int64_t)abs_diff==diff?" ":"-"), abs_diff, (unsigned int)TICKS_TO_SECS( abs_diff ), 
     163                    (unsigned int)TICKS_TO_CYCLES( abs_diff ), (unsigned int)TICKS_TO_OFFSET( abs_diff ) ); 
     164        if (abs_diff > 1000) { 
     165            debugWarning("Alert, large diff: %lld\n", diff); 
     166        } 
     167        debugOutput ( DEBUG_LEVEL_VERBOSE, 
     168                    " wait...\n"); 
    115169    } 
    116170