root/trunk/libffado/src/libieee1394/IsoHandlerManager.cpp

Revision 1246, 34.6 kB (checked in by ppalmers, 16 years ago)

add dead handler detection

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "config.h"
25 #include "IsoHandlerManager.h"
26 #include "ieee1394service.h"
27 #include "cycletimer.h"
28 #include "libstreaming/generic/StreamProcessor.h"
29
30 #include "libutil/Atomic.h"
31 #include "libutil/PosixThread.h"
32 #include "libutil/SystemTimeSource.h"
33 #include "libutil/Watchdog.h"
34
35 #include <cstring>
36 #include <assert.h>
37
38 IMPL_DEBUG_MODULE( IsoHandlerManager, IsoHandlerManager, DEBUG_LEVEL_NORMAL );
39 IMPL_DEBUG_MODULE( IsoTask, IsoTask, DEBUG_LEVEL_NORMAL );
40
41 using namespace Streaming;
42
43 // --- ISO Thread --- //
44
45 IsoTask::IsoTask(IsoHandlerManager& manager, enum IsoHandler::EHandlerType t)
46     : m_manager( manager )
47     , m_SyncIsoHandler ( NULL )
48     , m_handlerType( t )
49 {
50 }
51
52 IsoTask::~IsoTask()
53 {
54     sem_destroy(&m_activity_semaphore);
55 }
56
57 bool
58 IsoTask::Init()
59 {
60     request_update = 0;
61
62     int i;
63     for (i=0; i < ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT; i++) {
64         m_IsoHandler_map_shadow[i] = NULL;
65         m_poll_fds_shadow[i].events = 0;
66     }
67     m_poll_nfds_shadow = 0;
68
69     #ifdef DEBUG
70     m_last_loop_entry = 0;
71     m_successive_short_loops = 0;
72     #endif
73
74     sem_init(&m_activity_semaphore, 0, 0);
75     return true;
76 }
77
78 bool
79 IsoTask::requestShadowMapUpdate()
80 {
81     debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) enter\n", this);
82     INC_ATOMIC(&request_update);
83     return true;
84 }
85
86 // updates the internal stream map
87 // note that this should be executed with the guarantee that
88 // nobody will modify the parent data structures
89 void
90 IsoTask::updateShadowMapHelper()
91 {
92     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) updating shadow vars...\n", this);
93     unsigned int i, cnt, max;
94     max = m_manager.m_IsoHandlers.size();
95     m_SyncIsoHandler = NULL;
96     for (i = 0, cnt = 0; i < max; i++) {
97         IsoHandler *h = m_manager.m_IsoHandlers.at(i);
98         assert(h);
99
100         // skip the handlers not intended for us
101         if(h->getType() != m_handlerType) continue;
102
103         if (h->isEnabled()) {
104             m_IsoHandler_map_shadow[cnt] = h;
105             m_poll_fds_shadow[cnt].fd = h->getFileDescriptor();
106             m_poll_fds_shadow[cnt].revents = 0;
107             m_poll_fds_shadow[cnt].events = POLLIN;
108             cnt++;
109             // FIXME: need a more generic approach here
110             if(   m_SyncIsoHandler == NULL
111                && h->getType() == IsoHandler::eHT_Transmit) {
112                 m_SyncIsoHandler = h;
113             }
114
115             debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) %s handler %p added\n",
116                                               this, h->getTypeString(), h);
117         } else {
118             debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) %s handler %p skipped (disabled)\n",
119                                               this, h->getTypeString(), h);
120         }
121         if(cnt > ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT) {
122             debugWarning("Too much ISO Handlers in thread...\n");
123             break;
124         }
125     }
126
127     // FIXME: need a more generic approach here
128     // if there are no active transmit handlers,
129     // use the first receive handler
130     if(   m_SyncIsoHandler == NULL
131        && m_poll_nfds_shadow) {
132         m_SyncIsoHandler = m_IsoHandler_map_shadow[0];
133     }
134     m_poll_nfds_shadow = cnt;
135     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) updated shadow vars...\n", this);
136 }
137
138 bool
139 IsoTask::Execute()
140 {
141     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,
142                        "(%p, %s) Execute\n",
143                        this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
144     int err;
145     unsigned int i;
146     unsigned int m_poll_timeout = 10;
147
148     #ifdef DEBUG
149     uint64_t now = Util::SystemTimeSource::getCurrentTimeAsUsecs();
150     int diff = now - m_last_loop_entry;
151     if(diff < 100) {
152         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,
153                            "(%p, %s) short loop detected (%d usec), cnt: %d\n",
154                            this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"),
155                            diff, m_successive_short_loops);
156         m_successive_short_loops++;
157         if(m_successive_short_loops > 10000) {
158             debugError("Shutting down runaway thread\n");
159             return false;
160         }
161     } else {
162         // reset the counter
163         m_successive_short_loops = 0;
164     }
165     m_last_loop_entry = now;
166     #endif
167
168     // if some other thread requested a shadow map update, do it
169     if(request_update) {
170         updateShadowMapHelper();
171         DEC_ATOMIC(&request_update); // ack the update
172         assert(request_update >= 0);
173     }
174
175     // bypass if no handlers are registered
176     if (m_poll_nfds_shadow == 0) {
177         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,
178                            "(%p, %s) bypass iterate since no handlers to poll\n",
179                            this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
180         usleep(m_poll_timeout * 1000);
181         return true;
182     }
183
184     // FIXME: what can happen is that poll() returns, but not all clients are
185     // ready. there might be some busy waiting behavior that still has to be solved.
186
187     // setup the poll here
188     // we should prevent a poll() where no events are specified, since that will only time-out
189     bool no_one_to_poll = true;
190     while(no_one_to_poll) {
191         for (i = 0; i < m_poll_nfds_shadow; i++) {
192             short events = 0;
193             IsoHandler *h = m_IsoHandler_map_shadow[i];
194             // we should only poll on a transmit handler
195             // that has a client that is ready to send
196             // something. Otherwise it will end up in
197             // busy wait looping since the packet function
198             // will defer processing (also avoids the
199             // AGAIN problem)
200             if (h->canIterateClient()) {
201                 events = POLLIN | POLLPRI;
202                 no_one_to_poll = false;
203                 // if we are going to poll() it, let's ensure
204                 // it can run until someone wants it to exit
205                 h->allowIterateLoop();
206             }
207             m_poll_fds_shadow[i].events = events;
208         }
209
210         if(no_one_to_poll) {
211             debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
212                                "(%p, %s) No one to poll, waiting for something to happen\n",
213                                this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
214             // wait for something to happen
215             switch(waitForActivity()) {
216                 case IsoTask::eAR_Error:
217                     debugError("Error while waiting for activity\n");
218                     return false;
219                 case IsoTask::eAR_Interrupted:
220                     // FIXME: what to do here?
221                     debugWarning("Interrupted while waiting for activity\n");
222                     break;
223                 case IsoTask::eAR_Timeout:
224                     // FIXME: what to do here?
225                     debugWarning("Timeout while waiting for activity\n");
226                     no_one_to_poll = false; // exit the loop to be able to detect failing handlers
227                     break;
228                 case IsoTask::eAR_Activity:
229                     // do nothing
230                     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
231                                        "(%p, %s) something happened\n",
232                                        this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
233                     break;
234             }
235         }
236     }
237
238     // Use a shadow map of the fd's such that we don't have to update
239     // the fd map everytime we run poll().
240     err = poll (m_poll_fds_shadow, m_poll_nfds_shadow, m_poll_timeout);
241     uint32_t ctr_at_poll_return = m_manager.get1394Service().getCycleTimer();
242
243     if (err < 0) {
244         if (errno == EINTR) {
245             debugOutput(DEBUG_LEVEL_VERBOSE, "Ignoring poll return due to signal\n");
246             return true;
247         }
248         debugFatal("poll error: %s\n", strerror (errno));
249         return false;
250     }
251
252     // find handlers that have died
253     uint64_t ctr_at_poll_return_ticks = CYCLE_TIMER_TO_TICKS(ctr_at_poll_return);
254     bool handler_died = false;
255     for (i = 0; i < m_poll_nfds_shadow; i++) {
256         // figure out if a handler has died
257         // all handlers in the poll() are active, so they should be iterated
258         // now and then. If they aren't, the handler has died.
259         uint32_t last_call = m_IsoHandler_map_shadow[i]->getLastIterateTime();
260         if (last_call == 0xFFFFFFFF) {
261             // this was not iterated yet, so can't be dead
262             continue;
263         }
264
265         uint64_t last_call_ticks = CYCLE_TIMER_TO_TICKS(last_call);
266         // we use 4 seconds since that should not cause issues with startup
267         int64_t max_diff_ticks = TICKS_PER_SECOND * 4;
268         int64_t measured_diff_ticks = diffTicks(ctr_at_poll_return_ticks, last_call_ticks);
269
270         if(measured_diff_ticks > max_diff_ticks) {
271             debugFatal("(%p, %s) Handler died: now: %08lX, last: %08lX, diff: %lld (max: %lld)\n",
272                        this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"),
273                        ctr_at_poll_return, last_call, measured_diff_ticks, max_diff_ticks);
274             m_IsoHandler_map_shadow[i]->notifyOfDeath();
275             handler_died = true;
276         }
277     }
278     if(handler_died) {
279         return false; // one or more handlers have died
280     }
281
282     // iterate the handlers
283     for (i = 0; i < m_poll_nfds_shadow; i++) {
284         #ifdef DEBUG
285         if(m_poll_fds_shadow[i].revents) {
286             debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,
287                         "(%p, %s) received events: %08X for (%d/%d, %p, %s)\n",
288                         this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"),
289                         m_poll_fds_shadow[i].revents,
290                         i, m_poll_nfds_shadow,
291                         m_IsoHandler_map_shadow[i],
292                         m_IsoHandler_map_shadow[i]->getTypeString());
293         }
294         #endif
295
296         // if we get here, it means two things:
297         // 1) the kernel can accept or provide packets (poll returned POLLIN)
298         // 2) the client can provide or accept packets (since we enabled polling)
299         if(m_poll_fds_shadow[i].revents & (POLLIN)) {
300             m_IsoHandler_map_shadow[i]->iterate(ctr_at_poll_return);
301         } else {
302             // there might be some error condition
303             if (m_poll_fds_shadow[i].revents & POLLERR) {
304                 debugWarning("(%p) error on fd for %d\n", this, i);
305             }
306             if (m_poll_fds_shadow[i].revents & POLLHUP) {
307                 debugWarning("(%p) hangup on fd for %d\n", this, i);
308             }
309         }
310     }
311     return true;
312 }
313
314 enum IsoTask::eActivityResult
315 IsoTask::waitForActivity()
316 {
317     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
318                        "(%p, %s) waiting for activity\n",
319                        this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
320     struct timespec ts;
321     int result;
322
323     if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
324         debugError("clock_gettime failed\n");
325         return eAR_Error;
326     }
327     long long int timeout_nsec=0;
328     int timeout_sec = 0;
329
330     timeout_nsec = ISOHANDLERMANAGER_ISO_TASK_WAIT_TIMEOUT_USECS * 1000LL;
331     timeout_sec = 0;
332     while(timeout_nsec >= 1000000000LL) {
333         timeout_sec += 1;
334         timeout_nsec -= 1000000000LL;
335     }
336     ts.tv_nsec += timeout_nsec;
337     ts.tv_sec += timeout_sec;
338
339     result = sem_timedwait(&m_activity_semaphore, &ts);
340
341     if(result != 0) {
342         if (errno == ETIMEDOUT) {
343             debugOutput(DEBUG_LEVEL_VERBOSE,
344                         "(%p) sem_timedwait() timed out (result=%d)\n",
345                         this, result);
346             return eAR_Timeout;
347         } else if (errno == EINTR) {
348             debugOutput(DEBUG_LEVEL_VERBOSE,
349                         "(%p) sem_timedwait() interrupted by signal (result=%d)\n",
350                         this, result);
351             return eAR_Interrupted;
352         } else {
353             debugError("(%p) sem_timedwait error (result=%d errno=%d)\n",
354                         this, result, errno);
355             debugError("(%p) timeout_sec=%d timeout_nsec=%lld ts.sec=%d ts.nsec=%lld\n",
356                        this, timeout_sec, timeout_nsec, ts.tv_sec, ts.tv_nsec);
357             return eAR_Error;
358         }
359     }
360
361     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
362                        "(%p, %s) got activity\n",
363                        this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
364     return eAR_Activity;
365 }
366
367 void
368 IsoTask::signalActivity()
369 {
370     // signal the activity cond var
371     sem_post(&m_activity_semaphore);
372     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
373                        "(%p, %s) activity\n",
374                        this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
375 }
376
377 void IsoTask::setVerboseLevel(int i) {
378     setDebugLevel(i);
379 }
380
381 // -- the ISO handler manager -- //
382 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service)
383    : m_State(E_Created)
384    , m_service( service )
385    , m_realtime(false), m_priority(0)
386    , m_IsoThreadTransmit ( NULL )
387    , m_IsoTaskTransmit ( NULL )
388    , m_IsoThreadReceive ( NULL )
389    , m_IsoTaskReceive ( NULL )
390 {
391 }
392
393 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service, bool run_rt, int rt_prio)
394    : m_State(E_Created)
395    , m_service( service )
396    , m_realtime(run_rt), m_priority(rt_prio)
397    , m_IsoThreadTransmit ( NULL )
398    , m_IsoTaskTransmit ( NULL )
399    , m_IsoThreadReceive ( NULL )
400    , m_IsoTaskReceive ( NULL )
401 {
402 }
403
404 IsoHandlerManager::~IsoHandlerManager()
405 {
406     stopHandlers();
407     pruneHandlers();
408     if(m_IsoHandlers.size() > 0) {
409         debugError("Still some handlers in use\n");
410     }
411     if (m_IsoThreadTransmit) {
412         m_IsoThreadTransmit->Stop();
413         delete m_IsoThreadTransmit;
414     }
415     if (m_IsoThreadReceive) {
416         m_IsoThreadReceive->Stop();
417         delete m_IsoThreadReceive;
418     }
419     if (m_IsoTaskTransmit) {
420         delete m_IsoTaskTransmit;
421     }
422     if (m_IsoTaskReceive) {
423         delete m_IsoTaskReceive;
424     }
425 }
426
427 void
428 IsoHandlerManager::requestShadowMapUpdate()
429 {
430     if(m_IsoTaskTransmit) m_IsoTaskTransmit->requestShadowMapUpdate();
431     if(m_IsoTaskReceive) m_IsoTaskReceive->requestShadowMapUpdate();
432 }
433
434 bool
435 IsoHandlerManager::setThreadParameters(bool rt, int priority) {
436     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) switch to: (rt=%d, prio=%d)...\n", this, rt, priority);
437     if (priority > THREAD_MAX_RTPRIO) priority = THREAD_MAX_RTPRIO; // cap the priority
438     m_realtime = rt;
439     m_priority = priority;
440
441     if (m_IsoThreadTransmit) {
442         if (m_realtime) {
443             m_IsoThreadTransmit->AcquireRealTime(m_priority
444                                                  + ISOHANDLERMANAGER_ISO_PRIO_INCREASE
445                                                  + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT);
446         } else {
447             m_IsoThreadTransmit->DropRealTime();
448         }
449     }
450     if (m_IsoThreadReceive) {
451         if (m_realtime) {
452             m_IsoThreadReceive->AcquireRealTime(m_priority
453                                                 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE
454                                                 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV);
455         } else {
456             m_IsoThreadReceive->DropRealTime();
457         }
458     }
459
460     return true;
461 }
462
463 bool IsoHandlerManager::init()
464 {
465     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing ISO manager %p...\n", this);
466     // check state
467     if(m_State != E_Created) {
468         debugError("Manager already initialized...\n");
469         return false;
470     }
471
472     // create threads to iterate our ISO handlers
473     debugOutput( DEBUG_LEVEL_VERBOSE, "Create iso thread for %p transmit...\n", this);
474     m_IsoTaskTransmit = new IsoTask( *this, IsoHandler::eHT_Transmit );
475     if(!m_IsoTaskTransmit) {
476         debugFatal("No task\n");
477         return false;
478     }
479     m_IsoTaskTransmit->setVerboseLevel(getDebugLevel());
480     m_IsoThreadTransmit = new Util::PosixThread(m_IsoTaskTransmit, m_realtime,
481                                                 m_priority + ISOHANDLERMANAGER_ISO_PRIO_INCREASE
482                                                 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT,
483                                                 PTHREAD_CANCEL_DEFERRED);
484
485     if(!m_IsoThreadTransmit) {
486         debugFatal("No thread\n");
487         return false;
488     }
489     m_IsoThreadTransmit->setVerboseLevel(getDebugLevel());
490
491     debugOutput( DEBUG_LEVEL_VERBOSE, "Create iso thread for %p receive...\n", this);
492     m_IsoTaskReceive = new IsoTask( *this, IsoHandler::eHT_Receive );
493     if(!m_IsoTaskReceive) {
494         debugFatal("No task\n");
495         return false;
496     }
497     m_IsoTaskReceive->setVerboseLevel(getDebugLevel());
498     m_IsoThreadReceive = new Util::PosixThread(m_IsoTaskReceive, m_realtime,
499                                                m_priority + ISOHANDLERMANAGER_ISO_PRIO_INCREASE
500                                                + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV,
501                                                PTHREAD_CANCEL_DEFERRED);
502
503     if(!m_IsoThreadReceive) {
504         debugFatal("No thread\n");
505         return false;
506     }
507     m_IsoThreadReceive->setVerboseLevel(getDebugLevel());
508     // register the thread with the RT watchdog
509     Util::Watchdog *watchdog = m_service.getWatchdog();
510     if(watchdog) {
511         if(!watchdog->registerThread(m_IsoThreadTransmit)) {
512             debugWarning("could not register iso transmit thread with watchdog\n");
513         }
514         if(!watchdog->registerThread(m_IsoThreadReceive)) {
515             debugWarning("could not register iso receive thread with watchdog\n");
516         }
517     } else {
518         debugWarning("could not find valid watchdog\n");
519     }
520
521     if (m_IsoThreadTransmit->Start() != 0) {
522         debugFatal("Could not start ISO Transmit thread\n");
523         return false;
524     }
525     if (m_IsoThreadReceive->Start() != 0) {
526         debugFatal("Could not start ISO Receive thread\n");
527         return false;
528     }
529
530     m_State=E_Running;
531     return true;
532 }
533
534 bool
535 IsoHandlerManager::disable(IsoHandler *h) {
536     bool result;
537     int i=0;
538     debugOutput(DEBUG_LEVEL_VERBOSE, "Disable on IsoHandler %p\n", h);
539     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
540         it != m_IsoHandlers.end();
541         ++it )
542     {
543         if ((*it) == h) {
544             result = h->disable();
545             if(h->getType() == IsoHandler::eHT_Transmit) {
546                 result &= m_IsoTaskTransmit->requestShadowMapUpdate();
547             } else {
548                 result &= m_IsoTaskReceive->requestShadowMapUpdate();
549             }
550             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " disabled\n");
551             return result;
552         }
553         i++;
554     }
555     debugError("Handler not found\n");
556     return false;
557 }
558
559 bool
560 IsoHandlerManager::enable(IsoHandler *h) {
561     bool result;
562     int i=0;
563     debugOutput(DEBUG_LEVEL_VERBOSE, "Enable on IsoHandler %p\n", h);
564     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
565         it != m_IsoHandlers.end();
566         ++it )
567     {
568         if ((*it) == h) {
569             result = h->enable();
570             if(h->getType() == IsoHandler::eHT_Transmit) {
571                 result &= m_IsoTaskTransmit->requestShadowMapUpdate();
572             } else {
573                 result &= m_IsoTaskReceive->requestShadowMapUpdate();
574             }
575             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " enabled\n");
576             return result;
577         }
578         i++;
579     }
580     debugError("Handler not found\n");
581     return false;
582 }
583
584 void
585 IsoHandlerManager::signalActivityTransmit()
586 {
587     assert(m_IsoTaskTransmit);
588     m_IsoTaskTransmit->signalActivity();
589 }
590
591 void
592 IsoHandlerManager::signalActivityReceive()
593 {
594     assert(m_IsoTaskReceive);
595     m_IsoTaskReceive->signalActivity();
596 }
597
598 bool IsoHandlerManager::registerHandler(IsoHandler *handler)
599 {
600     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
601     assert(handler);
602     handler->setVerboseLevel(getDebugLevel());
603     m_IsoHandlers.push_back(handler);
604     requestShadowMapUpdate();
605     return true;
606 }
607
608 bool IsoHandlerManager::unregisterHandler(IsoHandler *handler)
609 {
610     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
611     assert(handler);
612
613     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
614       it != m_IsoHandlers.end();
615       ++it )
616     {
617         if ( *it == handler ) {
618             m_IsoHandlers.erase(it);
619             requestShadowMapUpdate();
620             return true;
621         }
622     }
623     debugFatal("Could not find handler (%p)\n", handler);
624     return false; //not found
625 }
626
627 /**
628  * Registers an StreamProcessor with the IsoHandlerManager.
629  *
630  * If nescessary, an IsoHandler is created to handle this stream.
631  * Once an StreamProcessor is registered to the handler, it will be included
632  * in the ISO streaming cycle (i.e. receive/transmit of it will occur).
633  *
634  * @param stream the stream to register
635  * @return true if registration succeeds
636  *
637  * \todo : currently there is a one-to-one mapping
638  *        between streams and handlers, this is not ok for
639  *        multichannel receive
640  */
641 bool IsoHandlerManager::registerStream(StreamProcessor *stream)
642 {
643     debugOutput( DEBUG_LEVEL_VERBOSE, "Registering stream %p\n",stream);
644     assert(stream);
645
646     IsoHandler* h = NULL;
647
648     // make sure the stream isn't already attached to a handler
649     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
650       it != m_IsoHandlers.end();
651       ++it )
652     {
653         if((*it)->isStreamRegistered(stream)) {
654             debugError( "stream already registered!\n");
655             return false;
656         }
657     }
658
659     // clean up all handlers that aren't used
660     pruneHandlers();
661
662     // allocate a handler for this stream
663     if (stream->getType()==StreamProcessor::ePT_Receive) {
664         // setup the optimal parameters for the raw1394 ISO buffering
665         unsigned int packets_per_period = stream->getPacketsPerPeriod();
666         unsigned int max_packet_size = stream->getMaxPacketSize();
667         unsigned int page_size = getpagesize() - 2; // for one reason or another this is necessary
668
669         // Ensure we don't request a packet size bigger than the
670         // kernel-enforced maximum which is currently 1 page.
671         if (max_packet_size > page_size) {
672             debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size);
673             return false;
674         }
675
676         unsigned int irq_interval = packets_per_period / MINIMUM_INTERRUPTS_PER_PERIOD;
677         if(irq_interval <= 0) irq_interval=1;
678        
679         // the receive buffer size doesn't matter for the latency,
680         // but it has a minimal value in order for libraw to operate correctly (300)
681         int buffers=400;
682
683         // create the actual handler
684         h = new IsoHandler(*this, IsoHandler::eHT_Receive,
685                            buffers, max_packet_size, irq_interval);
686
687         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoRecvHandler\n");
688
689         if(!h) {
690             debugFatal("Could not create IsoRecvHandler\n");
691             return false;
692         }
693
694     } else if (stream->getType()==StreamProcessor::ePT_Transmit) {
695         // setup the optimal parameters for the raw1394 ISO buffering
696 //        unsigned int packets_per_period = stream->getPacketsPerPeriod();
697         unsigned int max_packet_size = stream->getMaxPacketSize();
698 //         unsigned int page_size = getpagesize();
699
700         // Ensure we don't request a packet size bigger than the
701         // kernel-enforced maximum which is currently 1 page.
702 //         if (max_packet_size > page_size) {
703 //             debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size);
704 //             return false;
705 //         }
706         if (max_packet_size > MAX_XMIT_PACKET_SIZE) {
707             debugError("max packet size (%u) > MAX_XMIT_PACKET_SIZE (%u)\n",
708                        max_packet_size, MAX_XMIT_PACKET_SIZE);
709             return false;
710         }
711
712         // the SP specifies how many packets to ISO-buffer
713         int buffers = stream->getNbPacketsIsoXmitBuffer();
714         if (buffers > MAX_XMIT_NB_BUFFERS) {
715             debugOutput(DEBUG_LEVEL_VERBOSE,
716                         "nb buffers (%u) > MAX_XMIT_NB_BUFFERS (%u)\n",
717                         buffers, MAX_XMIT_NB_BUFFERS);
718             buffers = MAX_XMIT_NB_BUFFERS;
719         }
720         unsigned int irq_interval = buffers / MINIMUM_INTERRUPTS_PER_PERIOD;
721         if(irq_interval <= 0) irq_interval=1;
722
723         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoXmitHandler\n");
724
725         // create the actual handler
726         h = new IsoHandler(*this, IsoHandler::eHT_Transmit,
727                            buffers, max_packet_size, irq_interval);
728
729         if(!h) {
730             debugFatal("Could not create IsoXmitHandler\n");
731             return false;
732         }
733
734     } else {
735         debugFatal("Bad stream type\n");
736         return false;
737     }
738
739     h->setVerboseLevel(getDebugLevel());
740
741     // init the handler
742     if(!h->init()) {
743         debugFatal("Could not initialize receive handler\n");
744         return false;
745     }
746
747     // register the stream with the handler
748     if(!h->registerStream(stream)) {
749         debugFatal("Could not register receive stream with handler\n");
750         return false;
751     }
752
753     // register the handler with the manager
754     if(!registerHandler(h)) {
755         debugFatal("Could not register receive handler with manager\n");
756         return false;
757     }
758     debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n", stream, h);
759
760     m_StreamProcessors.push_back(stream);
761     debugOutput( DEBUG_LEVEL_VERBOSE, " %d streams, %d handlers registered\n",
762                                       m_StreamProcessors.size(), m_IsoHandlers.size());
763     return true;
764 }
765
766 bool IsoHandlerManager::unregisterStream(StreamProcessor *stream)
767 {
768     debugOutput( DEBUG_LEVEL_VERBOSE, "Unregistering stream %p\n",stream);
769     assert(stream);
770
771     // make sure the stream isn't attached to a handler anymore
772     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
773       it != m_IsoHandlers.end();
774       ++it )
775     {
776         if((*it)->isStreamRegistered(stream)) {
777             if(!(*it)->unregisterStream(stream)) {
778                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not unregister stream (%p) from handler (%p)...\n",stream,*it);
779                 return false;
780             }
781             debugOutput( DEBUG_LEVEL_VERBOSE, " unregistered stream (%p) from handler (%p)...\n",stream,*it);
782         }
783     }
784
785     // clean up all handlers that aren't used
786     pruneHandlers();
787
788     // remove the stream from the registered streams list
789     for ( StreamProcessorVectorIterator it = m_StreamProcessors.begin();
790       it != m_StreamProcessors.end();
791       ++it )
792     {
793         if ( *it == stream ) {
794             m_StreamProcessors.erase(it);
795             debugOutput( DEBUG_LEVEL_VERBOSE, " deleted stream (%p) from list...\n", *it);
796             return true;
797         }
798     }
799     return false; //not found
800 }
801
802 /**
803  * @brief unregister a handler from the manager
804  * @note called without the lock held.
805  */
806 void IsoHandlerManager::pruneHandlers() {
807     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
808     IsoHandlerVector toUnregister;
809
810     // find all handlers that are not in use
811     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
812           it != m_IsoHandlers.end();
813           ++it )
814     {
815         if(!((*it)->inUse())) {
816             debugOutput( DEBUG_LEVEL_VERBOSE, " handler (%p) not in use\n",*it);
817             toUnregister.push_back(*it);
818         }
819     }
820     // delete them
821     for ( IsoHandlerVectorIterator it = toUnregister.begin();
822           it != toUnregister.end();
823           ++it )
824     {
825         unregisterHandler(*it);
826
827         debugOutput( DEBUG_LEVEL_VERBOSE, " deleting handler (%p)\n",*it);
828
829         // Now the handler's been unregistered it won't be reused
830         // again.  Therefore it really needs to be formally deleted
831         // to free up the raw1394 handle.  Otherwise things fall
832         // apart after several xrun recoveries as the system runs
833         // out of resources to support all the disused but still
834         // allocated raw1394 handles.  At least this is the current
835         // theory as to why we end up with "memory allocation"
836         // failures after several Xrun recoveries.
837         delete *it;
838     }
839 }
840
841 bool
842 IsoHandlerManager::stopHandlerForStream(Streaming::StreamProcessor *stream) {
843     // check state
844     if(m_State != E_Running) {
845         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
846         return false;
847     }
848     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
849       it != m_IsoHandlers.end();
850       ++it )
851     {
852         if((*it)->isStreamRegistered(stream)) {
853             debugOutput( DEBUG_LEVEL_VERBOSE, " stopping handler %p for stream %p\n", *it, stream);
854             if(!(*it)->disable()) {
855                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not disable handler (%p)\n",*it);
856                 return false;
857             }
858             bool result;
859             if((*it)->getType() == IsoHandler::eHT_Transmit) {
860                 result = m_IsoTaskTransmit->requestShadowMapUpdate();
861             } else {
862                 result = m_IsoTaskReceive->requestShadowMapUpdate();
863             }
864             if(!result) {
865                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
866                 return false;
867             }
868             return true;
869         }
870     }
871     debugError("Stream %p has no attached handler\n", stream);
872     return false;
873 }
874
875 int
876 IsoHandlerManager::getPacketLatencyForStream(Streaming::StreamProcessor *stream) {
877     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
878       it != m_IsoHandlers.end();
879       ++it )
880     {
881         if((*it)->isStreamRegistered(stream)) {
882             return (*it)->getPacketLatency();
883         }
884     }
885     debugError("Stream %p has no attached handler\n", stream);
886     return 0;
887 }
888
889 void
890 IsoHandlerManager::flushHandlerForStream(Streaming::StreamProcessor *stream) {
891     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
892       it != m_IsoHandlers.end();
893       ++it )
894     {
895         if((*it)->isStreamRegistered(stream)) {
896             return (*it)->flush();
897         }
898     }
899     debugError("Stream %p has no attached handler\n", stream);
900     return;
901 }
902
903 bool
904 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream) {
905     return startHandlerForStream(stream, -1);
906 }
907
908 bool
909 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream, int cycle) {
910     // check state
911     if(m_State != E_Running) {
912         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
913         return false;
914     }
915     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
916       it != m_IsoHandlers.end();
917       ++it )
918     {
919         if((*it)->isStreamRegistered(stream)) {
920             debugOutput( DEBUG_LEVEL_VERBOSE, " starting handler %p for stream %p\n", *it, stream);
921             if(!(*it)->enable(cycle)) {
922                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not enable handler (%p)\n",*it);
923                 return false;
924             }
925             bool result;
926             if((*it)->getType() == IsoHandler::eHT_Transmit) {
927                 result = m_IsoTaskTransmit->requestShadowMapUpdate();
928             } else {
929                 result = m_IsoTaskReceive->requestShadowMapUpdate();
930             }
931             if(!result) {
932                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
933                 return false;
934             }
935             return true;
936         }
937     }
938     debugError("Stream %p has no attached handler\n", stream);
939     return false;
940 }
941
942 bool IsoHandlerManager::stopHandlers() {
943     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
944
945     // check state
946     if(m_State != E_Running) {
947         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
948         return false;
949     }
950
951     bool retval=true;
952
953     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
954         it != m_IsoHandlers.end();
955         ++it )
956     {
957         debugOutput( DEBUG_LEVEL_VERBOSE, "Stopping handler (%p)\n",*it);
958         if(!(*it)->disable()){
959             debugOutput( DEBUG_LEVEL_VERBOSE, " could not stop handler (%p)\n",*it);
960             retval=false;
961         }
962         bool result;
963         if((*it)->getType() == IsoHandler::eHT_Transmit) {
964             result = m_IsoTaskTransmit->requestShadowMapUpdate();
965         } else {
966             result = m_IsoTaskReceive->requestShadowMapUpdate();
967         }
968         if(!result) {
969             debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
970             return false;
971         }
972     }
973
974     if (retval) {
975         m_State=E_Prepared;
976     } else {
977         m_State=E_Error;
978     }
979     return retval;
980 }
981
982 bool IsoHandlerManager::reset() {
983     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
984     // check state
985     if(m_State == E_Error) {
986         debugFatal("Resetting from error condition not yet supported...\n");
987         return false;
988     }
989     // if not in an error condition, reset means stop the handlers
990     return stopHandlers();
991 }
992
993 void IsoHandlerManager::setVerboseLevel(int i) {
994     setDebugLevel(i);
995     // propagate the debug level
996     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
997           it != m_IsoHandlers.end();
998           ++it )
999     {
1000         (*it)->setVerboseLevel(i);
1001     }
1002     if(m_IsoThreadTransmit) m_IsoThreadTransmit->setVerboseLevel(i);
1003     if(m_IsoTaskTransmit)   m_IsoTaskTransmit->setVerboseLevel(i);
1004     if(m_IsoThreadReceive)  m_IsoThreadReceive->setVerboseLevel(i);
1005     if(m_IsoTaskReceive)    m_IsoTaskReceive->setVerboseLevel(i);
1006 }
1007
1008 void IsoHandlerManager::dumpInfo() {
1009     #ifdef DEBUG
1010     unsigned int i=0;
1011     debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping IsoHandlerManager Stream handler information...\n");
1012     debugOutputShort( DEBUG_LEVEL_NORMAL, " State: %d\n",(int)m_State);
1013
1014     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1015           it != m_IsoHandlers.end();
1016           ++it )
1017     {
1018         debugOutputShort( DEBUG_LEVEL_NORMAL, " IsoHandler %d (%p)\n",i++,*it);
1019         (*it)->dumpInfo();
1020     }
1021     #endif
1022 }
1023
1024 const char *
1025 IsoHandlerManager::eHSToString(enum eHandlerStates s) {
1026     switch (s) {
1027         default: return "Invalid";
1028         case E_Created: return "Created";
1029         case E_Prepared: return "Prepared";
1030         case E_Running: return "Running";
1031         case E_Error: return "Error";
1032     }
1033 }
Note: See TracBrowser for help on using the browser.