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

Revision 1145, 33.4 kB (checked in by holin, 16 years ago)

error types are returned in errno not the return value

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