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

Revision 1254, 34.6 kB (checked in by ppalmers, 13 years ago)

split config.h into config/version/debug_config to allow for faster compilation (splits dependencies)

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