Index: /trunk/libffado/src/libieee1394/cycletimer.h =================================================================== --- /trunk/libffado/src/libieee1394/cycletimer.h (revision 1090) +++ /trunk/libffado/src/libieee1394/cycletimer.h (revision 1246) @@ -46,4 +46,10 @@ #define CYCLE_TIMER_GET_CYCLES(x) ((((x) & 0x01FFF000UL) >> 12)) #define CYCLE_TIMER_GET_OFFSET(x) ((((x) & 0x00000FFFUL))) + +#define CYCLE_TIMER_SET_SECS(v, x) (((v) & ~0xFE000000UL) | (((x) & 0x7F) << 25)) +#define CYCLE_TIMER_SET_CYCLES(v, x) ((((v) & ~0x01FFF000UL) | (((x) & 0x1FFF) << 12))) +#define CYCLE_TIMER_SET_OFFSET(v, x) ((((v) & ~0x00000FFFUL) | ((x) & 0xFFF))) + + #define CYCLE_TIMER_TO_TICKS(x) ((CYCLE_TIMER_GET_SECS(x) * TICKS_PER_SECOND) +\ (CYCLE_TIMER_GET_CYCLES(x) * TICKS_PER_CYCLE ) +\ Index: /trunk/libffado/src/libieee1394/IsoHandlerManager.cpp =================================================================== --- /trunk/libffado/src/libieee1394/IsoHandlerManager.cpp (revision 1234) +++ /trunk/libffado/src/libieee1394/IsoHandlerManager.cpp (revision 1246) @@ -24,5 +24,6 @@ #include "config.h" #include "IsoHandlerManager.h" -#include "ieee1394service.h" +#include "ieee1394service.h" +#include "cycletimer.h" #include "libstreaming/generic/StreamProcessor.h" @@ -223,4 +224,5 @@ // FIXME: what to do here? debugWarning("Timeout while waiting for activity\n"); + no_one_to_poll = false; // exit the loop to be able to detect failing handlers break; case IsoTask::eAR_Activity: @@ -237,4 +239,5 @@ // the fd map everytime we run poll(). err = poll (m_poll_fds_shadow, m_poll_nfds_shadow, m_poll_timeout); + uint32_t ctr_at_poll_return = m_manager.get1394Service().getCycleTimer(); if (err < 0) { @@ -247,4 +250,35 @@ } + // find handlers that have died + uint64_t ctr_at_poll_return_ticks = CYCLE_TIMER_TO_TICKS(ctr_at_poll_return); + bool handler_died = false; + for (i = 0; i < m_poll_nfds_shadow; i++) { + // figure out if a handler has died + // all handlers in the poll() are active, so they should be iterated + // now and then. If they aren't, the handler has died. + uint32_t last_call = m_IsoHandler_map_shadow[i]->getLastIterateTime(); + if (last_call == 0xFFFFFFFF) { + // this was not iterated yet, so can't be dead + continue; + } + + uint64_t last_call_ticks = CYCLE_TIMER_TO_TICKS(last_call); + // we use 4 seconds since that should not cause issues with startup + int64_t max_diff_ticks = TICKS_PER_SECOND * 4; + int64_t measured_diff_ticks = diffTicks(ctr_at_poll_return_ticks, last_call_ticks); + + if(measured_diff_ticks > max_diff_ticks) { + debugFatal("(%p, %s) Handler died: now: %08lX, last: %08lX, diff: %lld (max: %lld)\n", + this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"), + ctr_at_poll_return, last_call, measured_diff_ticks, max_diff_ticks); + m_IsoHandler_map_shadow[i]->notifyOfDeath(); + handler_died = true; + } + } + if(handler_died) { + return false; // one or more handlers have died + } + + // iterate the handlers for (i = 0; i < m_poll_nfds_shadow; i++) { #ifdef DEBUG @@ -264,5 +298,5 @@ // 2) the client can provide or accept packets (since we enabled polling) if(m_poll_fds_shadow[i].revents & (POLLIN)) { - m_IsoHandler_map_shadow[i]->iterate(); + m_IsoHandler_map_shadow[i]->iterate(ctr_at_poll_return); } else { // there might be some error condition @@ -274,15 +308,4 @@ } } - -// #ifdef DEBUG -// // check if the handler is still alive -// if(m_IsoHandler_map_shadow[i]->isDead()) { -// debugError("Iso handler (%p, %s) is dead!\n", -// m_IsoHandler_map_shadow[i], -// m_IsoHandler_map_shadow[i]->getTypeString()); -// return false; // shutdown the system -// } -// #endif - } return true; Index: /trunk/libffado/src/libieee1394/IsoHandler.cpp =================================================================== --- /trunk/libffado/src/libieee1394/IsoHandler.cpp (revision 1172) +++ /trunk/libffado/src/libieee1394/IsoHandler.cpp (revision 1246) @@ -184,11 +184,16 @@ bool IsoHandler::iterate() { - debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) Iterating ISO handler...\n", - this, getTypeString()); + return iterate(m_manager.get1394Service().getCycleTimer()); +} + +bool +IsoHandler::iterate(uint32_t cycle_timer_now) { + debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) Iterating ISO handler at %08X...\n", + this, getTypeString(), cycle_timer_now); + m_last_now = cycle_timer_now; if(m_State == E_Running) { #if ISOHANDLER_FLUSH_BEFORE_ITERATE flush(); #endif - m_last_now = m_manager.get1394Service().getCycleTimer(); if(raw1394_loop_iterate(m_handle)) { debugError( "IsoHandler (%p): Failed to iterate handler: %s\n", @@ -294,4 +299,15 @@ m_manager.requestShadowMapUpdate(); return 0; +} + +/** + * Call this if you find out that this handler has died for some + * external reason. + */ +void +IsoHandler::notifyOfDeath() +{ + // notify the client of the fact that we have died + m_Client->handlerDied(); } @@ -717,4 +733,8 @@ m_min_ahead = 7999; #endif + + // indicate that the first iterate() still has to occur. + m_last_now = 0xFFFFFFFF; + m_State = E_Running; return true; Index: /trunk/libffado/src/libieee1394/IsoHandler.h =================================================================== --- /trunk/libffado/src/libieee1394/IsoHandler.h (revision 1038) +++ /trunk/libffado/src/libieee1394/IsoHandler.h (revision 1246) @@ -81,6 +81,17 @@ public: - // runnable interface + + /** + * Iterate the handler, transporting ISO packets to the client(s) + * @return true if success + */ bool iterate(); + + /** + * Iterate the handler, transporting ISO packets to the client(s) + * @param ctr_now the CTR time at which the iterate call is done. + * @return true if success + */ + bool iterate(uint32_t ctr_now); int getFileDescriptor() { return raw1394_get_fd(m_handle);}; @@ -145,4 +156,11 @@ int getLastCycle() {return m_last_cycle;}; + /** + * @brief returns the CTR value saved at the last iterate() call + * @return CTR value saved at last iterate() call + */ + uint32_t getLastIterateTime() {return m_last_now;}; + + void notifyOfDeath(); private: IsoHandlerManager& m_manager;