Changeset 904 for trunk/libffado/src
- Timestamp:
- 03/05/08 14:24:49 (16 years ago)
- Files:
-
- trunk/libffado/src/libieee1394/CycleTimerHelper.cpp (modified) (3 diffs)
- trunk/libffado/src/libieee1394/ieee1394service.cpp (modified) (2 diffs)
- trunk/libffado/src/libieee1394/IsoHandler.cpp (modified) (15 diffs)
- trunk/libffado/src/libieee1394/IsoHandler.h (modified) (5 diffs)
- trunk/libffado/src/libieee1394/IsoHandlerManager.cpp (modified) (16 diffs)
- trunk/libffado/src/libieee1394/IsoHandlerManager.h (modified) (4 diffs)
- trunk/libffado/src/libstreaming/generic/Port.cpp (modified) (2 diffs)
- trunk/libffado/src/libstreaming/generic/StreamProcessor.cpp (modified) (2 diffs)
- trunk/libffado/src/libutil/SystemTimeSource.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/libffado/src/libieee1394/CycleTimerHelper.cpp
r894 r904 233 233 debugOutput(DEBUG_LEVEL_VERBOSE, "have to retry, diff = %f\n",diff_ticks); 234 234 } 235 235 236 236 } while(diff_ticks < -((double)TICKS_PER_HALFCYCLE) && --ntries && !m_first_run); 237 237 … … 471 471 472 472 if (diffTicks(cycle_timer_ticks, m_cycle_timer_ticks_prev) < 0) { 473 debugOutput( DEBUG_LEVEL_VER BOSE,473 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, 474 474 "non-monotonic CTR (try %02d): %llu -> %llu\n", 475 475 maxtries, m_cycle_timer_ticks_prev, cycle_timer_ticks); 476 debugOutput( DEBUG_LEVEL_VER BOSE,476 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, 477 477 " : %08X -> %08X\n", 478 478 m_cycle_timer_prev, *cycle_timer); 479 debugOutput( DEBUG_LEVEL_VER BOSE,479 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, 480 480 " current: %011llu (%03us %04ucy %04uticks)\n", 481 481 cycle_timer_ticks, … … 483 483 (unsigned int)TICKS_TO_CYCLES( cycle_timer_ticks ), 484 484 (unsigned int)TICKS_TO_OFFSET( cycle_timer_ticks ) ); 485 debugOutput( DEBUG_LEVEL_VER BOSE,485 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, 486 486 " prev : %011llu (%03us %04ucy %04uticks)\n", 487 487 m_cycle_timer_ticks_prev, trunk/libffado/src/libieee1394/ieee1394service.cpp
r864 r904 76 76 , m_realtime ( rt ) 77 77 , m_base_priority ( prio ) 78 , m_pIsoManager( new IsoHandlerManager( *this, rt, prio + IEEE1394SERVICE_ISOMANAGER_PRIO_INCREASE) )78 , m_pIsoManager( new IsoHandlerManager( *this, rt, prio ) ) 79 79 , m_pCTRHelper ( new CycleTimerHelper( *this, IEEE1394SERVICE_CYCLETIMER_DLL_UPDATE_INTERVAL_USEC, 80 80 rt, prio + IEEE1394SERVICE_CYCLETIMER_HELPER_PRIO_INCREASE ) ) … … 277 277 if (m_pIsoManager) { 278 278 debugOutput(DEBUG_LEVEL_VERBOSE, "Switching IsoManager to (rt=%d, prio=%d)\n", 279 rt, priority + IEEE1394SERVICE_ISOMANAGER_PRIO_INCREASE);280 result &= m_pIsoManager->setThreadParameters(rt, priority + IEEE1394SERVICE_ISOMANAGER_PRIO_INCREASE);279 rt, priority); 280 result &= m_pIsoManager->setThreadParameters(rt, priority); 281 281 } 282 282 if (m_pCTRHelper) { trunk/libffado/src/libieee1394/IsoHandler.cpp
r870 r904 83 83 , m_max_packet_size( 1024 ) 84 84 , m_irq_interval( -1 ) 85 , m_last_wakeup( -1 )86 85 , m_Client( 0 ) 87 , m_poll_timeout( 100 )88 , m_realtime ( false )89 , m_priority ( 0 )90 , m_Thread ( NULL )91 86 , m_speed( RAW1394_ISO_SPEED_400 ) 92 87 , m_prebuffers( 0 ) … … 103 98 , m_max_packet_size( max_packet_size ) 104 99 , m_irq_interval( irq ) 105 , m_last_wakeup( -1 )106 100 , m_Client( 0 ) 107 , m_poll_timeout( 100 )108 , m_realtime ( false )109 , m_priority ( 0 )110 , m_Thread ( NULL )111 101 , m_speed( RAW1394_ISO_SPEED_400 ) 112 102 , m_prebuffers( 0 ) … … 124 114 , m_max_packet_size( max_packet_size ) 125 115 , m_irq_interval( irq ) 126 , m_last_wakeup( -1 )127 116 , m_Client( 0 ) 128 , m_poll_timeout( 100 )129 , m_realtime ( false )130 , m_priority ( 0 )131 , m_Thread ( NULL )132 117 , m_speed( speed ) 133 118 , m_prebuffers( 0 ) … … 137 122 138 123 IsoHandler::~IsoHandler() { 139 if (m_Thread) {140 m_Thread->Stop();141 delete m_Thread;142 }143 124 // Don't call until libraw1394's raw1394_new_handle() function has been 144 125 // fixed to correctly initialise the iso_packet_infos field. Bug is … … 155 136 156 137 bool 157 IsoHandler::Init()158 {159 debugOutput( DEBUG_LEVEL_VERBOSE, "%p: Init thread...\n", this);160 m_poll_fd.fd = getFileDescriptor();161 m_poll_fd.revents = 0;162 if (isEnabled()) {163 m_poll_fd.events = POLLIN;164 } else {165 m_poll_fd.events = 0;166 }167 return true;168 }169 170 bool171 IsoHandler::isDead()172 {173 if(m_last_wakeup < 0) return false; // startup artifacts174 if(m_State != E_Running) return false; // not running can't be dead175 int64_t now = m_manager.get1394Service().getCurrentTimeAsUsecs();176 int64_t last_call = m_last_wakeup + ISOHANDLER_DEATH_DETECT_TIMEOUT_USECS;177 if(now > last_call) {178 debugOutput(DEBUG_LEVEL_VERBOSE,179 "(%p, %s) Handler timed out: %lld usecs since last wakeup\n",180 this, getTypeString(), now-m_last_wakeup);181 return true;182 } else {183 return false;184 }185 }186 187 bool188 138 IsoHandler::waitForClient() 189 139 { … … 222 172 return false; 223 173 } 224 174 /* 225 175 bool 226 176 IsoHandler::Execute() … … 287 237 return false; 288 238 } 289 } 239 }*/ 290 240 291 241 bool … … 313 263 314 264 bool 315 IsoHandler::setThreadParameters(bool rt, int priority) {316 debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) switch to: (rt=%d, prio=%d)...\n", this, rt, priority);317 if (priority > THREAD_MAX_RTPRIO) priority = THREAD_MAX_RTPRIO; // cap the priority318 m_realtime = rt;319 m_priority = priority;320 321 if (m_Thread) {322 if (m_realtime) {323 m_Thread->AcquireRealTime(m_priority);324 } else {325 m_Thread->DropRealTime();326 }327 }328 return true;329 }330 331 bool332 265 IsoHandler::init() 333 266 { … … 362 295 } 363 296 364 #if ISOHANDLER_PER_HANDLER_THREAD365 // create a thread to iterate ourselves366 debugOutput( DEBUG_LEVEL_VERBOSE, "Start thread for %p...\n", this);367 m_Thread = new Util::PosixThread(this, m_realtime, m_priority,368 PTHREAD_CANCEL_DEFERRED);369 if(!m_Thread) {370 debugFatal("No thread\n");371 return false;372 }373 if (m_Thread->Start() != 0) {374 debugFatal("Could not start update thread\n");375 return false;376 }377 #endif378 379 297 // update the internal state 380 298 m_State=E_Initialized; … … 393 311 return false; 394 312 } 395 396 m_poll_fd.events = 0;397 313 398 314 // this is put here to try and avoid the … … 446 362 { 447 363 setDebugLevel(l); 448 if(m_Thread) m_Thread->setVerboseLevel(l);449 364 } 450 365 … … 494 409 length, channel, cycle); 495 410 #ifdef DEBUG 496 m_last_wakeup = m_manager.get1394Service().getCurrentTimeAsUsecs();497 411 if (length > m_max_packet_size) { 498 412 debugWarning("(%p, %s) packet too large: len=%u max=%u\n", … … 516 430 "sending packet: length=%d, cycle=%d\n", 517 431 *length, cycle); 518 #ifdef DEBUG519 m_last_wakeup = m_manager.get1394Service().getCurrentTimeAsUsecs();520 #endif521 522 432 if(m_Client) { 523 433 enum raw1394_iso_disposition retval; … … 550 460 // raw1394_iso_shutdown(m_handle); 551 461 m_State = E_Prepared; 552 m_last_wakeup = -1;553 462 554 463 debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso handler (%p, client=%p)\n", this, m_Client); … … 622 531 } 623 532 624 m_poll_fd.events = POLLIN;625 533 m_State = E_Running; 626 534 return true; trunk/libffado/src/libieee1394/IsoHandler.h
r868 r904 45 45 */ 46 46 47 class IsoHandler : public Util::RunnableInterface47 class IsoHandler 48 48 { 49 49 public: … … 82 82 public: 83 83 // runnable interface 84 bool Init();85 bool Execute();86 84 bool iterate(); 87 85 88 86 int getFileDescriptor() { return raw1394_get_fd(m_handle);}; 89 bool setThreadParameters(bool rt, int priority);90 87 91 88 bool init(); … … 97 94 bool enable(int cycle); 98 95 bool disable(); 99 100 bool isDead();101 96 102 97 void flush(); … … 137 132 int m_irq_interval; 138 133 139 int64_t m_last_wakeup;140 141 134 Streaming::StreamProcessor *m_Client; 142 135 … … 144 137 145 138 static int busreset_handler(raw1394handle_t handle, unsigned int generation); 146 147 struct pollfd m_poll_fd;148 int m_poll_timeout;149 // threading150 bool m_realtime;151 int m_priority;152 Util::Thread * m_Thread;153 139 154 140 enum raw1394_iso_speed m_speed; trunk/libffado/src/libieee1394/IsoHandlerManager.cpp
r870 r904 32 32 #include "libutil/PosixThread.h" 33 33 34 #include "libutil/SystemTimeSource.h" 35 34 36 #include <assert.h> 35 37 36 38 IMPL_DEBUG_MODULE( IsoHandlerManager, IsoHandlerManager, DEBUG_LEVEL_NORMAL ); 39 IMPL_DEBUG_MODULE( IsoTask, IsoTask, DEBUG_LEVEL_NORMAL ); 37 40 38 41 using namespace Streaming; 39 42 43 // --- ISO Thread --- // 44 45 IsoTask::IsoTask(IsoHandlerManager& manager, enum IsoTask::eTaskType t) 46 : m_manager( manager ) 47 , m_type( t ) 48 { 49 } 50 51 bool 52 IsoTask::Init() 53 { 54 request_update = 0; 55 56 int i; 57 for (i=0; i < ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT; i++) { 58 m_IsoHandler_map_shadow[i] = NULL; 59 m_poll_fds_shadow[i].events = 0; 60 } 61 m_poll_nfds_shadow = 0; 62 return true; 63 } 64 65 bool 66 IsoTask::requestShadowMapUpdate() 67 { 68 debugOutput(DEBUG_LEVEL_VERBOSE, "enter\n"); 69 INC_ATOMIC(&request_update); 70 return true; 71 } 72 73 // updates the internal stream map 74 // note that this should be executed with the guarantee that 75 // nobody will modify 76 void 77 IsoTask::updateShadowMapHelper() 78 { 79 debugOutput( DEBUG_LEVEL_VERBOSE, "updating shadow vars...\n"); 80 unsigned int i, cnt, max; 81 max = m_manager.m_IsoHandlers.size(); 82 for (i = 0, cnt = 0; i < max; i++) { 83 IsoHandler *h = m_manager.m_IsoHandlers.at(i); 84 assert(h); 85 86 // skip handlers of the wrong type 87 if (h->getType() == IsoHandler::eHT_Receive && m_type == eTT_Transmit) continue; 88 if (h->getType() == IsoHandler::eHT_Transmit && m_type == eTT_Receive) continue; 89 90 if (h->isEnabled()) { 91 m_IsoHandler_map_shadow[cnt] = h; 92 m_poll_fds_shadow[cnt].fd = h->getFileDescriptor(); 93 m_poll_fds_shadow[cnt].revents = 0; 94 m_poll_fds_shadow[cnt].events = POLLIN; 95 cnt++; 96 debugOutput( DEBUG_LEVEL_VERBOSE, "%s handler %p added\n", h->getTypeString(), h); 97 } else { 98 debugOutput( DEBUG_LEVEL_VERBOSE, "%s handler %p skipped (disabled)\n", h->getTypeString(), h); 99 } 100 if(cnt > ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT) { 101 debugWarning("Too much ISO Handlers in thread...\n"); 102 break; 103 } 104 } 105 m_poll_nfds_shadow = cnt; 106 debugOutput( DEBUG_LEVEL_VERBOSE, " updated shadow vars...\n"); 107 } 108 109 bool 110 IsoTask::Execute() 111 { 112 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Execute\n"); 113 int err; 114 unsigned int i; 115 unsigned int m_poll_timeout = 10; 116 117 // if some other thread requested a shadow map update, do it 118 if(request_update) { 119 updateShadowMapHelper(); 120 DEC_ATOMIC(&request_update); // ack the update 121 } 122 123 // bypass if no handlers are registered 124 if (m_poll_nfds_shadow == 0) { 125 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "bypass iterate since no handlers to poll\n"); 126 usleep(m_poll_timeout * 1000); 127 return true; 128 } 129 130 // setup the poll here 131 if (m_type==eTT_Transmit) { 132 // if we are a transmit thread, we should only poll on 133 // those handlers that have a client that is ready to send 134 // something. poll'ing the others will only cause busy-wait 135 // looping. 136 for (i = 0; i < m_poll_nfds_shadow; i++) { 137 short events = 0; 138 if (m_IsoHandler_map_shadow[i]->tryWaitForClient()) { 139 events = POLLIN | POLLPRI; 140 } 141 m_poll_fds_shadow[i].events = events; 142 } 143 } else { 144 // for receive handlers, we can do the same. we might not have to though 145 // FIXME: check whether this is necessary 146 for (i = 0; i < m_poll_nfds_shadow; i++) { 147 short events = 0; 148 // if (m_IsoHandler_map_shadow[i]->tryWaitForClient()) { 149 // events = POLLIN | POLLERR | POLLHUP; 150 // } 151 events = POLLIN | POLLPRI; 152 m_poll_fds_shadow[i].events = events; 153 } 154 } 155 156 // Use a shadow map of the fd's such that the poll call is not in a critical section 157 DEBUG_EXTREME( uint64_t poll_enter = m_service.getCurrentTimeAsUsecs() ); 158 err = poll (m_poll_fds_shadow, m_poll_nfds_shadow, m_poll_timeout); 159 DEBUG_EXTREME( uint64_t poll_exit = m_service.getCurrentTimeAsUsecs() ); 160 161 if (err < 0) { 162 if (errno == EINTR) { 163 return true; 164 } 165 debugFatal("poll error: %s\n", strerror (errno)); 166 return false; 167 } 168 169 DEBUG_EXTREME( uint64_t iter_enter = m_service.getCurrentTimeAsUsecs() ); 170 for (i = 0; i < m_poll_nfds_shadow; i++) { 171 #ifdef DEBUG 172 if(m_poll_fds_shadow[i].revents) { 173 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, 174 "received events: %08X for (%d/%d, %p, %s)\n", 175 m_poll_fds_shadow[i].revents, 176 i, m_poll_nfds_shadow, 177 m_IsoHandler_map_shadow[i], 178 m_IsoHandler_map_shadow[i]->getTypeString()); 179 } 180 #endif 181 182 // if we get here, it means two things: 183 // 1) the kernel can accept or provide packets (poll returned POLLIN) 184 // 2) the client can provide or accept packets (we enabled polling) 185 if(m_poll_fds_shadow[i].revents & (POLLIN)) { 186 m_IsoHandler_map_shadow[i]->iterate(); 187 } else { 188 // there might be some error condition 189 if (m_poll_fds_shadow[i].revents & POLLERR) { 190 debugWarning("error on fd for %d\n",i); 191 } 192 if (m_poll_fds_shadow[i].revents & POLLHUP) { 193 debugWarning("hangup on fd for %d\n",i); 194 } 195 } 196 197 // #ifdef DEBUG 198 // // check if the handler is still alive 199 // if(m_IsoHandler_map_shadow[i]->isDead()) { 200 // debugError("Iso handler (%p, %s) is dead!\n", 201 // m_IsoHandler_map_shadow[i], 202 // m_IsoHandler_map_shadow[i]->getTypeString()); 203 // return false; // shutdown the system 204 // } 205 // #endif 206 207 } 208 DEBUG_EXTREME( uint64_t iter_exit = m_service.getCurrentTimeAsUsecs() ); 209 210 debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, " poll took %6lldus, iterate took %6lldus, iterated (R: %2d, X: %2d) handlers\n", 211 poll_exit-poll_enter, iter_exit-iter_enter, 212 nb_rcv, nb_xmit); 213 214 return true; 215 216 } 217 218 void IsoTask::setVerboseLevel(int i) { 219 setDebugLevel(i); 220 } 221 222 // -- the ISO handler manager -- // 40 223 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service) 41 224 : m_State(E_Created) 42 225 , m_service( service ) 43 226 , m_realtime(false), m_priority(0) 44 , m_Thread ( NULL ) 227 , m_ReceiveThread ( NULL ) 228 , m_TransmitThread ( NULL ) 229 , m_ReceiveTask ( NULL ) 230 , m_TransmitTask ( NULL ) 45 231 {} 46 232 … … 49 235 , m_service( service ) 50 236 , m_realtime(run_rt), m_priority(rt_prio) 51 , m_Thread ( NULL ) 237 , m_ReceiveThread ( NULL ) 238 , m_TransmitThread ( NULL ) 239 , m_ReceiveTask ( NULL ) 240 , m_TransmitTask ( NULL ) 52 241 {} 53 242 … … 59 248 debugError("Still some handlers in use\n"); 60 249 } 61 if (m_Thread) { 62 m_Thread->Stop(); 63 delete m_Thread; 250 if (m_ReceiveThread) { 251 m_ReceiveThread->Stop(); 252 delete m_ReceiveThread; 253 } 254 if (m_ReceiveTask) { 255 delete m_ReceiveTask; 256 } 257 258 if (m_TransmitThread) { 259 m_TransmitThread->Stop(); 260 delete m_TransmitThread; 261 } 262 if (m_TransmitTask) { 263 delete m_TransmitTask; 64 264 } 65 265 } … … 72 272 m_priority = priority; 73 273 bool result = true; 74 for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin(); 75 it != m_IsoHandlers.end(); 76 ++it ) 77 { 78 result &= (*it)->setThreadParameters(m_realtime, m_priority); 79 } 80 81 if (m_Thread) { 274 275 if (m_ReceiveThread) { 82 276 if (m_realtime) { 83 m_ Thread->AcquireRealTime(m_priority);277 m_ReceiveThread->AcquireRealTime(m_priority); 84 278 } else { 85 m_Thread->DropRealTime(); 279 m_ReceiveThread->DropRealTime(); 280 } 281 } 282 if (m_TransmitThread) { 283 if (m_realtime) { 284 m_TransmitThread->AcquireRealTime(m_priority); 285 } else { 286 m_TransmitThread->DropRealTime(); 86 287 } 87 288 } 88 289 89 290 return result; 90 }91 92 /**93 * Update the shadow variables. Should only be called from94 * the iso handler iteration thread95 */96 void97 IsoHandlerManager::updateShadowVars()98 {99 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "updating shadow vars...\n");100 unsigned int i, cnt, max;101 max = m_IsoHandlers.size();102 for (i = 0, cnt = 0; i < max; i++) {103 IsoHandler *h = m_IsoHandlers.at(i);104 assert(h);105 if (h->isEnabled()) {106 // receive handlers are always poll'ed107 // transmit handlers only when the client is ready108 if (h->tryWaitForClient()) {109 m_IsoHandler_map_shadow[cnt] = h;110 m_poll_fds_shadow[cnt].fd = h->getFileDescriptor();111 m_poll_fds_shadow[cnt].revents = 0;112 m_poll_fds_shadow[cnt].events = POLLIN;113 cnt++;114 } else {115 debugOutput(DEBUG_LEVEL_VERBOSE, "skipped handler %p\n", h);116 }117 }118 if(cnt > ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT) {119 debugWarning("Too much ISO Handlers in manager...\n");120 break;121 }122 }123 m_poll_nfds_shadow = cnt;124 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, " updated shadow vars...\n");125 }126 127 bool128 IsoHandlerManager::Init() {129 debugOutput( DEBUG_LEVEL_VERBOSE, "%p: Init thread...\n", this);130 bool result = true;131 for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();132 it != m_IsoHandlers.end();133 ++it )134 {135 result &= (*it)->Init();136 }137 return result;138 }139 140 bool141 IsoHandlerManager::Execute() {142 int err;143 unsigned int i;144 145 unsigned int m_poll_timeout = 100;146 147 updateShadowVars();148 // bypass if no handlers are registered149 if (m_poll_nfds_shadow == 0) {150 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "bypass iterate since no handlers to poll\n");151 usleep(m_poll_timeout * 1000);152 return true;153 }154 155 // Use a shadow map of the fd's such that the poll call is not in a critical section156 DEBUG_EXTREME( uint64_t poll_enter = m_service.getCurrentTimeAsUsecs() );157 err = poll (m_poll_fds_shadow, m_poll_nfds_shadow, m_poll_timeout);158 DEBUG_EXTREME( uint64_t poll_exit = m_service.getCurrentTimeAsUsecs() );159 160 if (err == -1) {161 if (errno == EINTR) {162 return true;163 }164 debugFatal("poll error: %s\n", strerror (errno));165 return false;166 }167 168 int nb_rcv = 0;169 int nb_xmit = 0;170 DEBUG_EXTREME( uint64_t iter_enter = m_service.getCurrentTimeAsUsecs() );171 for (i = 0; i < m_poll_nfds_shadow; i++) {172 if(m_poll_fds_shadow[i].revents) {173 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,174 "received events: %08X for (%d/%d, %p, %s)\n",175 m_poll_fds_shadow[i].revents,176 i, m_poll_nfds_shadow,177 m_IsoHandler_map_shadow[i],178 m_IsoHandler_map_shadow[i]->getTypeString());179 }180 if (m_poll_fds_shadow[i].revents & POLLERR) {181 debugWarning("error on fd for %d\n",i);182 }183 184 if (m_poll_fds_shadow[i].revents & POLLHUP) {185 debugWarning("hangup on fd for %d\n",i);186 }187 188 if(m_poll_fds_shadow[i].revents & (POLLIN)) {189 if (m_IsoHandler_map_shadow[i]->getType() == IsoHandler::eHT_Receive) {190 m_IsoHandler_map_shadow[i]->iterate();191 nb_rcv++;192 } else {193 // only iterate the xmit handler if it makes sense194 if(m_IsoHandler_map_shadow[i]->tryWaitForClient()) {195 m_IsoHandler_map_shadow[i]->iterate();196 nb_xmit++;197 }198 }199 }200 201 #ifdef DEBUG202 // check if the handler is still alive203 if(m_IsoHandler_map_shadow[i]->isDead()) {204 debugError("Iso handler (%p, %s) is dead!\n",205 m_IsoHandler_map_shadow[i],206 m_IsoHandler_map_shadow[i]->getTypeString());207 return false; // shutdown the system208 }209 #endif210 211 }212 DEBUG_EXTREME( uint64_t iter_exit = m_service.getCurrentTimeAsUsecs() );213 214 debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, " poll took %6lldus, iterate took %6lldus, iterated (R: %2d, X: %2d) handlers\n",215 poll_exit-poll_enter, iter_exit-iter_enter,216 nb_rcv, nb_xmit);217 218 return true;219 291 } 220 292 … … 228 300 } 229 301 230 #if ISOHANDLER_PER_HANDLER_THREAD 231 // the IsoHandlers will create their own thread. 232 #else 233 // create a thread to iterate our handlers 234 debugOutput( DEBUG_LEVEL_VERBOSE, "Start thread for %p...\n", this); 235 m_Thread = new Util::PosixThread(this, m_realtime, m_priority, 236 PTHREAD_CANCEL_DEFERRED); 237 if(!m_Thread) { 302 // create a thread to iterate our receive handlers 303 debugOutput( DEBUG_LEVEL_VERBOSE, "Create receive thread for %p...\n", this); 304 m_ReceiveTask = new IsoTask( *this, IsoTask::eTT_Receive ); 305 if(!m_ReceiveTask) { 306 debugFatal("No task\n"); 307 return false; 308 } 309 m_ReceiveThread = new Util::PosixThread(m_ReceiveTask, m_realtime, 310 m_priority + ISOHANDLERMANAGER_RECEIVE_PRIO_INCREASE, 311 PTHREAD_CANCEL_DEFERRED); 312 313 if(!m_ReceiveThread) { 238 314 debugFatal("No thread\n"); 239 315 return false; 240 316 } 241 if (m_Thread->Start() != 0) { 242 debugFatal("Could not start update thread\n"); 243 return false; 244 } 245 #endif 317 if (m_ReceiveThread->Start() != 0) { 318 debugFatal("Could not start receive thread\n"); 319 return false; 320 } 321 322 // create a thread to iterate our transmit handlers 323 debugOutput( DEBUG_LEVEL_VERBOSE, "Create transmit thread for %p...\n", this); 324 m_TransmitTask = new IsoTask( *this, IsoTask::eTT_Transmit ); 325 if(!m_TransmitTask) { 326 debugFatal("No task\n"); 327 return false; 328 } 329 m_TransmitThread = new Util::PosixThread(m_TransmitTask, m_realtime, 330 m_priority + ISOHANDLERMANAGER_TRANSMIT_PRIO_INCREASE, 331 PTHREAD_CANCEL_DEFERRED); 332 if(!m_TransmitThread) { 333 debugFatal("No thread\n"); 334 return false; 335 } 336 if (m_TransmitThread->Start() != 0) { 337 debugFatal("Could not start transmit thread\n"); 338 return false; 339 } 246 340 247 341 m_State=E_Running; 342 return true; 343 } 344 345 346 bool 347 IsoHandlerManager::updateShadowMapFor(IsoHandler *h) 348 { 349 // update the shadow map 350 if(h->getType() == IsoHandler::eHT_Receive) { 351 if(!m_ReceiveTask->requestShadowMapUpdate()) { 352 debugError("failed to update shadow map\n"); 353 return false; 354 } 355 } else { 356 if(!m_TransmitTask->requestShadowMapUpdate()) { 357 debugError("failed to update shadow map\n"); 358 return false; 359 } 360 } 248 361 return true; 249 362 } … … 253 366 bool result; 254 367 int i=0; 255 debugOutput(DEBUG_LEVEL_VER Y_VERBOSE, "Disable on IsoHandler %p\n", h);368 debugOutput(DEBUG_LEVEL_VERBOSE, "Disable on IsoHandler %p\n", h); 256 369 for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin(); 257 370 it != m_IsoHandlers.end(); … … 260 373 if ((*it) == h) { 261 374 result = h->disable(); 375 result &= updateShadowMapFor(h); 262 376 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " disabled\n"); 263 377 return result; … … 273 387 bool result; 274 388 int i=0; 275 debugOutput(DEBUG_LEVEL_VER Y_VERBOSE, "Enable on IsoHandler %p\n", h);389 debugOutput(DEBUG_LEVEL_VERBOSE, "Enable on IsoHandler %p\n", h); 276 390 for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin(); 277 391 it != m_IsoHandlers.end(); … … 280 394 if ((*it) == h) { 281 395 result = h->enable(); 396 result &= updateShadowMapFor(h); 282 397 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " enabled\n"); 283 398 return result; … … 295 410 handler->setVerboseLevel(getDebugLevel()); 296 411 m_IsoHandlers.push_back(handler); 297 updateShadowVars(); 298 return true; 412 return updateShadowMapFor(handler); 299 413 } 300 414 … … 310 424 if ( *it == handler ) { 311 425 m_IsoHandlers.erase(it); 312 updateShadowVars(); 313 return true; 426 return updateShadowMapFor(handler); 314 427 } 315 428 } … … 452 565 } 453 566 454 if(!h->setThreadParameters(m_realtime, thread_prio)) {455 debugFatal("Could not set handler thread parameters\n");456 return false;457 }458 459 567 // register the stream with the handler 460 568 if(!h->registerStream(stream)) { … … 563 671 { 564 672 if((*it)->isStreamRegistered(stream)) { 565 bool result;566 673 debugOutput( DEBUG_LEVEL_VERBOSE, " stopping handler %p for stream %p\n", *it, stream); 567 result = (*it)->disable(); 568 if(!result) { 674 if(!(*it)->disable()) { 569 675 debugOutput( DEBUG_LEVEL_VERBOSE, " could not disable handler (%p)\n",*it); 676 return false; 677 } 678 if(!updateShadowMapFor(*it)) { 679 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it); 570 680 return false; 571 681 } … … 622 732 { 623 733 if((*it)->isStreamRegistered(stream)) { 624 bool result;625 734 debugOutput( DEBUG_LEVEL_VERBOSE, " starting handler %p for stream %p\n", *it, stream); 626 result = (*it)->enable(cycle); 627 if(!result) { 735 if(!(*it)->enable(cycle)) { 628 736 debugOutput( DEBUG_LEVEL_VERBOSE, " could not enable handler (%p)\n",*it); 629 737 return false; 630 738 } 739 if(!updateShadowMapFor(*it)) { 740 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it); 741 return false; 742 } 631 743 return true; 632 744 } … … 654 766 if(!(*it)->disable()){ 655 767 debugOutput( DEBUG_LEVEL_VERBOSE, " could not stop handler (%p)\n",*it); 768 retval=false; 769 } 770 if(!updateShadowMapFor(*it)) { 771 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it); 656 772 retval=false; 657 773 } … … 686 802 (*it)->setVerboseLevel(i); 687 803 } 804 if(m_ReceiveThread) m_ReceiveThread->setVerboseLevel(i); 805 if(m_ReceiveTask) m_ReceiveTask->setVerboseLevel(i); 806 if(m_TransmitThread) m_TransmitThread->setVerboseLevel(i); 807 if(m_TransmitTask) m_TransmitTask->setVerboseLevel(i); 688 808 } 689 809 trunk/libffado/src/libieee1394/IsoHandlerManager.h
r864 r904 37 37 38 38 class Ieee1394Service; 39 40 39 class IsoHandler; 40 41 41 namespace Streaming { 42 42 class StreamProcessor; … … 49 49 typedef std::vector<IsoHandler *>::iterator IsoHandlerVectorIterator; 50 50 51 class IsoHandlerManager; 52 53 // threads that will handle the packet framing 54 // one thread per direction, as a compromise for one per 55 // channel and one for all 56 class IsoTask : public Util::RunnableInterface 57 { 58 public: 59 enum eTaskType { 60 eTT_Receive, 61 eTT_Transmit, 62 }; 63 IsoTask(IsoHandlerManager& manager, enum IsoTask::eTaskType t); 64 virtual ~IsoTask() {}; 65 66 public: 67 bool Init(); 68 bool Execute(); 69 70 /** 71 * requests the thread to sync it's stream map with the manager 72 */ 73 bool requestShadowMapUpdate(); 74 75 void setVerboseLevel(int i); 76 protected: 77 IsoHandlerManager& m_manager; 78 enum eTaskType m_type; 79 80 // the event request structure 81 SInt32 request_update; 82 83 // static allocation due to RT constraints 84 // this is the map used by the actual thread 85 // it is a shadow of the m_StreamProcessors vector 86 struct pollfd m_poll_fds_shadow[ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT]; 87 IsoHandler *m_IsoHandler_map_shadow[ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT]; 88 unsigned int m_poll_nfds_shadow; 89 90 // updates the streams map 91 void updateShadowMapHelper(); 92 93 // debug stuff 94 DECLARE_DEBUG_MODULE; 95 }; 96 51 97 /*! 52 98 \brief The ISO Handler management class … … 60 106 61 107 */ 62 class IsoHandlerManager : public Util::RunnableInterface 108 109 class IsoHandlerManager 63 110 { 64 111 friend class Streaming::StreamProcessorManager; 65 public: 66 bool Init(); 67 bool Execute(); 68 void updateShadowVars(); 69 private: 70 // shadow variables 71 struct pollfd m_poll_fds_shadow[ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT]; 72 IsoHandler *m_IsoHandler_map_shadow[ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT]; 73 unsigned int m_poll_nfds_shadow; 112 friend class IsoTask; 74 113 75 114 public: … … 151 190 bool m_realtime; 152 191 int m_priority; 153 Util::Thread * m_Thread; 192 // handler threads 193 Util::Thread * m_ReceiveThread; 194 Util::Thread * m_TransmitThread; 195 196 // actual tasks 197 IsoTask * m_ReceiveTask; 198 IsoTask * m_TransmitTask; 199 200 bool updateShadowMapFor(IsoHandler *h); 154 201 155 202 // debug stuff trunk/libffado/src/libstreaming/generic/Port.cpp
r864 r904 125 125 void 126 126 Port::enable() { 127 debugOutput(DEBUG_LEVEL_VER BOSE, "Enabling port %s...\n",m_Name.c_str());127 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Enabling port %s...\n",m_Name.c_str()); 128 128 m_disabled=false; 129 129 } … … 132 132 void 133 133 Port::disable() { 134 debugOutput(DEBUG_LEVEL_VER BOSE, "Disabling port %s...\n",m_Name.c_str());134 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Disabling port %s...\n",m_Name.c_str()); 135 135 m_disabled=false; 136 136 } trunk/libffado/src/libstreaming/generic/StreamProcessor.cpp
r885 r904 132 132 StreamProcessor::getNbPacketsIsoXmitBuffer() 133 133 { 134 #if ISOHANDLER_PER_HANDLER_THREAD135 134 // if we use one thread per packet, we can put every frame directly into the ISO buffer 136 135 // the waitForClient in IsoHandler will take care of the fact that the frames are … … 139 138 debugOutput(DEBUG_LEVEL_VERBOSE, "Nominal prebuffer: %u\n", packets_to_prebuffer); 140 139 return packets_to_prebuffer; 141 #else142 // the target is to have all of the transmit buffer (at period transfer) as ISO packets143 // when one period is received, there will be approx (NbBuffers - 1) * period_size frames144 // in the transmit buffer (the others are still to be put into the xmit frame buffer)145 unsigned int packets_to_prebuffer = (getPacketsPerPeriod() * (m_StreamProcessorManager.getNbBuffers()-1));146 debugOutput(DEBUG_LEVEL_VERBOSE, "Nominal prebuffer: %u\n", packets_to_prebuffer);147 148 // however we have to take into account the fact that there is some sync delay149 // we assume that the SPM has indicated150 // HACK: this counts on the fact that the latency for this stream will be the same as the151 // latency for the receive sync source152 unsigned int est_sync_delay = getPacketsPerPeriod() / MINIMUM_INTERRUPTS_PER_PERIOD;153 est_sync_delay += STREAMPROCESSORMANAGER_SIGNAL_DELAY_TICKS / TICKS_PER_CYCLE;154 packets_to_prebuffer -= est_sync_delay;155 debugOutput(DEBUG_LEVEL_VERBOSE, " correct for sync delay (%d): %u\n",156 est_sync_delay,157 packets_to_prebuffer);158 159 // only queue a part of the theoretical max in order not to have too much 'not ready' cycles160 packets_to_prebuffer = (packets_to_prebuffer * MAX_ISO_XMIT_BUFFER_FILL_PCT * 1000) / 100000;161 debugOutput(DEBUG_LEVEL_VERBOSE, " reduce to %d%%: %u\n",162 MAX_ISO_XMIT_BUFFER_FILL_PCT, packets_to_prebuffer);163 164 return packets_to_prebuffer;165 #endif166 140 } 167 141 trunk/libffado/src/libutil/SystemTimeSource.h
r864 r904 44 44 inline ffado_microsecs_t unWrapTime(ffado_microsecs_t t) {return t;}; 45 45 inline ffado_microsecs_t wrapTime(ffado_microsecs_t t) {return t;}; 46 46 47 47 static void SleepUsecRelative(ffado_microsecs_t usecs); 48 48 static void SleepUsecAbsolute(ffado_microsecs_t wake_time);