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

Revision 904, 26.5 kB (checked in by ppalmers, 13 years ago)

simplify threading. Each port now gets two threads: one for transmit and one for receive.

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 "IsoHandler.h"
28 #include "libstreaming/generic/StreamProcessor.h"
29
30 #include "libutil/Atomic.h"
31
32 #include "libutil/PosixThread.h"
33
34 #include "libutil/SystemTimeSource.h"
35
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 IsoTask::eTaskType t)
46     : m_manager( manager )
47     , m_type( t )
48 {
49 }
50
51 bool
52 IsoTask::Init()
53 {
54     request_update = 0;
55
56     int i;
57     for (i=0; i < ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT; i++) {
58         m_IsoHandler_map_shadow[i] = NULL;
59         m_poll_fds_shadow[i].events = 0;
60     }
61     m_poll_nfds_shadow = 0;
62     return true;
63 }
64
65 bool
66 IsoTask::requestShadowMapUpdate()
67 {
68     debugOutput(DEBUG_LEVEL_VERBOSE, "enter\n");
69     INC_ATOMIC(&request_update);
70     return true;
71 }
72
73 // updates the internal stream map
74 // note that this should be executed with the guarantee that
75 // nobody will modify
76 void
77 IsoTask::updateShadowMapHelper()
78 {
79     debugOutput( DEBUG_LEVEL_VERBOSE, "updating shadow vars...\n");
80     unsigned int i, cnt, max;
81     max = m_manager.m_IsoHandlers.size();
82     for (i = 0, cnt = 0; i < max; i++) {
83         IsoHandler *h = m_manager.m_IsoHandlers.at(i);
84         assert(h);
85
86         // skip handlers of the wrong type
87         if (h->getType() == IsoHandler::eHT_Receive  && m_type == eTT_Transmit) continue;
88         if (h->getType() == IsoHandler::eHT_Transmit && m_type == eTT_Receive) continue;
89
90         if (h->isEnabled()) {
91             m_IsoHandler_map_shadow[cnt] = h;
92             m_poll_fds_shadow[cnt].fd = h->getFileDescriptor();
93             m_poll_fds_shadow[cnt].revents = 0;
94             m_poll_fds_shadow[cnt].events = POLLIN;
95             cnt++;
96             debugOutput( DEBUG_LEVEL_VERBOSE, "%s handler %p added\n", h->getTypeString(), h);
97         } else {
98             debugOutput( DEBUG_LEVEL_VERBOSE, "%s handler %p skipped (disabled)\n", h->getTypeString(), h);
99         }
100         if(cnt > ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT) {
101             debugWarning("Too much ISO Handlers in thread...\n");
102             break;
103         }
104     }
105     m_poll_nfds_shadow = cnt;
106     debugOutput( DEBUG_LEVEL_VERBOSE, " updated shadow vars...\n");
107 }
108
109 bool
110 IsoTask::Execute()
111 {
112     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Execute\n");
113     int err;
114     unsigned int i;
115     unsigned int m_poll_timeout = 10;
116
117     // if some other thread requested a shadow map update, do it
118     if(request_update) {
119         updateShadowMapHelper();
120         DEC_ATOMIC(&request_update); // ack the update
121     }
122
123     // bypass if no handlers are registered
124     if (m_poll_nfds_shadow == 0) {
125         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "bypass iterate since no handlers to poll\n");
126         usleep(m_poll_timeout * 1000);
127         return true;
128     }
129
130     // setup the poll here
131     if (m_type==eTT_Transmit) {
132         // if we are a transmit thread, we should only poll on
133         // those handlers that have a client that is ready to send
134         // something. poll'ing the others will only cause busy-wait
135         // looping.
136         for (i = 0; i < m_poll_nfds_shadow; i++) {
137             short events = 0;
138             if (m_IsoHandler_map_shadow[i]->tryWaitForClient()) {
139                 events = POLLIN | POLLPRI;
140             }
141             m_poll_fds_shadow[i].events = events;
142         }
143     } else {
144         // for receive handlers, we can do the same. we might not have to though
145         // FIXME: check whether this is necessary
146         for (i = 0; i < m_poll_nfds_shadow; i++) {
147             short events = 0;
148 //             if (m_IsoHandler_map_shadow[i]->tryWaitForClient()) {
149 //                 events = POLLIN | POLLERR | POLLHUP;
150 //             }
151             events = POLLIN | POLLPRI;
152             m_poll_fds_shadow[i].events = events;
153         }
154     }
155
156     // Use a shadow map of the fd's such that the poll call is not in a critical section
157     DEBUG_EXTREME( uint64_t poll_enter = m_service.getCurrentTimeAsUsecs() );
158     err = poll (m_poll_fds_shadow, m_poll_nfds_shadow, m_poll_timeout);
159     DEBUG_EXTREME( uint64_t poll_exit = m_service.getCurrentTimeAsUsecs() );
160
161     if (err < 0) {
162         if (errno == EINTR) {
163             return true;
164         }
165         debugFatal("poll error: %s\n", strerror (errno));
166         return false;
167     }
168
169     DEBUG_EXTREME( uint64_t iter_enter = m_service.getCurrentTimeAsUsecs() );
170     for (i = 0; i < m_poll_nfds_shadow; i++) {
171         #ifdef DEBUG
172         if(m_poll_fds_shadow[i].revents) {
173             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
174                         "received events: %08X for (%d/%d, %p, %s)\n",
175                         m_poll_fds_shadow[i].revents,
176                         i, m_poll_nfds_shadow,
177                         m_IsoHandler_map_shadow[i],
178                         m_IsoHandler_map_shadow[i]->getTypeString());
179         }
180         #endif
181
182         // if we get here, it means two things:
183         // 1) the kernel can accept or provide packets (poll returned POLLIN)
184         // 2) the client can provide or accept packets (we enabled polling)
185         if(m_poll_fds_shadow[i].revents & (POLLIN)) {
186             m_IsoHandler_map_shadow[i]->iterate();
187         } else {
188             // there might be some error condition
189             if (m_poll_fds_shadow[i].revents & POLLERR) {
190                 debugWarning("error on fd for %d\n",i);
191             }
192             if (m_poll_fds_shadow[i].revents & POLLHUP) {
193                 debugWarning("hangup on fd for %d\n",i);
194             }
195         }
196
197 //         #ifdef DEBUG
198 //         // check if the handler is still alive
199 //         if(m_IsoHandler_map_shadow[i]->isDead()) {
200 //             debugError("Iso handler (%p, %s) is dead!\n",
201 //                        m_IsoHandler_map_shadow[i],
202 //                        m_IsoHandler_map_shadow[i]->getTypeString());
203 //             return false; // shutdown the system
204 //         }
205 //         #endif
206
207     }
208     DEBUG_EXTREME( uint64_t iter_exit = m_service.getCurrentTimeAsUsecs() );
209
210     debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE, " poll took %6lldus, iterate took %6lldus, iterated (R: %2d, X: %2d) handlers\n",
211                        poll_exit-poll_enter, iter_exit-iter_enter,
212                        nb_rcv, nb_xmit);
213
214     return true;
215
216 }
217
218 void IsoTask::setVerboseLevel(int i) {
219     setDebugLevel(i);
220 }
221
222 // -- the ISO handler manager -- //
223 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service)
224    : m_State(E_Created)
225    , m_service( service )
226    , m_realtime(false), m_priority(0)
227    , m_ReceiveThread ( NULL )
228    , m_TransmitThread ( NULL )
229    , m_ReceiveTask ( NULL )
230    , m_TransmitTask ( NULL )
231 {}
232
233 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service, bool run_rt, int rt_prio)
234    : m_State(E_Created)
235    , m_service( service )
236    , m_realtime(run_rt), m_priority(rt_prio)
237    , m_ReceiveThread ( NULL )
238    , m_TransmitThread ( NULL )
239    , m_ReceiveTask ( NULL )
240    , m_TransmitTask ( NULL )
241 {}
242
243 IsoHandlerManager::~IsoHandlerManager()
244 {
245     stopHandlers();
246     pruneHandlers();
247     if(m_IsoHandlers.size() > 0) {
248         debugError("Still some handlers in use\n");
249     }
250     if (m_ReceiveThread) {
251         m_ReceiveThread->Stop();
252         delete m_ReceiveThread;
253     }
254     if (m_ReceiveTask) {
255         delete m_ReceiveTask;
256     }
257
258     if (m_TransmitThread) {
259         m_TransmitThread->Stop();
260         delete m_TransmitThread;
261     }
262     if (m_TransmitTask) {
263         delete m_TransmitTask;
264     }
265 }
266
267 bool
268 IsoHandlerManager::setThreadParameters(bool rt, int priority) {
269     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) switch to: (rt=%d, prio=%d)...\n", this, rt, priority);
270     if (priority > THREAD_MAX_RTPRIO) priority = THREAD_MAX_RTPRIO; // cap the priority
271     m_realtime = rt;
272     m_priority = priority;
273     bool result = true;
274
275     if (m_ReceiveThread) {
276         if (m_realtime) {
277             m_ReceiveThread->AcquireRealTime(m_priority);
278         } else {
279             m_ReceiveThread->DropRealTime();
280         }
281     }
282     if (m_TransmitThread) {
283         if (m_realtime) {
284             m_TransmitThread->AcquireRealTime(m_priority);
285         } else {
286             m_TransmitThread->DropRealTime();
287         }
288     }
289
290     return result;
291 }
292
293 bool IsoHandlerManager::init()
294 {
295     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing ISO manager %p...\n", this);
296     // check state
297     if(m_State != E_Created) {
298         debugError("Manager already initialized...\n");
299         return false;
300     }
301
302     // create a thread to iterate our receive handlers
303     debugOutput( DEBUG_LEVEL_VERBOSE, "Create receive thread for %p...\n", this);
304     m_ReceiveTask = new IsoTask( *this, IsoTask::eTT_Receive );
305     if(!m_ReceiveTask) {
306         debugFatal("No task\n");
307         return false;
308     }
309     m_ReceiveThread = new Util::PosixThread(m_ReceiveTask, m_realtime,
310                                             m_priority + ISOHANDLERMANAGER_RECEIVE_PRIO_INCREASE,
311                                             PTHREAD_CANCEL_DEFERRED);
312
313     if(!m_ReceiveThread) {
314         debugFatal("No thread\n");
315         return false;
316     }
317     if (m_ReceiveThread->Start() != 0) {
318         debugFatal("Could not start receive thread\n");
319         return false;
320     }
321
322     // create a thread to iterate our transmit handlers
323     debugOutput( DEBUG_LEVEL_VERBOSE, "Create transmit thread for %p...\n", this);
324     m_TransmitTask = new IsoTask( *this, IsoTask::eTT_Transmit );
325     if(!m_TransmitTask) {
326         debugFatal("No task\n");
327         return false;
328     }
329     m_TransmitThread = new Util::PosixThread(m_TransmitTask, m_realtime,
330                                              m_priority + ISOHANDLERMANAGER_TRANSMIT_PRIO_INCREASE,
331                                              PTHREAD_CANCEL_DEFERRED);
332     if(!m_TransmitThread) {
333         debugFatal("No thread\n");
334         return false;
335     }
336     if (m_TransmitThread->Start() != 0) {
337         debugFatal("Could not start transmit thread\n");
338         return false;
339     }
340
341     m_State=E_Running;
342     return true;
343 }
344
345
346 bool
347 IsoHandlerManager::updateShadowMapFor(IsoHandler *h)
348 {
349     // update the shadow map
350     if(h->getType() == IsoHandler::eHT_Receive) {
351         if(!m_ReceiveTask->requestShadowMapUpdate()) {
352             debugError("failed to update shadow map\n");
353             return false;
354         }
355     } else {
356         if(!m_TransmitTask->requestShadowMapUpdate()) {
357             debugError("failed to update shadow map\n");
358             return false;
359         }
360     }
361     return true;
362 }
363
364 bool
365 IsoHandlerManager::disable(IsoHandler *h) {
366     bool result;
367     int i=0;
368     debugOutput(DEBUG_LEVEL_VERBOSE, "Disable on IsoHandler %p\n", h);
369     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
370         it != m_IsoHandlers.end();
371         ++it )
372     {
373         if ((*it) == h) {
374             result = h->disable();
375             result &= updateShadowMapFor(h);
376             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " disabled\n");
377             return result;
378         }
379         i++;
380     }
381     debugError("Handler not found\n");
382     return false;
383 }
384
385 bool
386 IsoHandlerManager::enable(IsoHandler *h) {
387     bool result;
388     int i=0;
389     debugOutput(DEBUG_LEVEL_VERBOSE, "Enable on IsoHandler %p\n", h);
390     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
391         it != m_IsoHandlers.end();
392         ++it )
393     {
394         if ((*it) == h) {
395             result = h->enable();
396             result &= updateShadowMapFor(h);
397             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " enabled\n");
398             return result;
399         }
400         i++;
401     }
402     debugError("Handler not found\n");
403     return false;
404 }
405
406 bool IsoHandlerManager::registerHandler(IsoHandler *handler)
407 {
408     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
409     assert(handler);
410     handler->setVerboseLevel(getDebugLevel());
411     m_IsoHandlers.push_back(handler);
412     return updateShadowMapFor(handler);
413 }
414
415 bool IsoHandlerManager::unregisterHandler(IsoHandler *handler)
416 {
417     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
418     assert(handler);
419
420     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
421       it != m_IsoHandlers.end();
422       ++it )
423     {
424         if ( *it == handler ) {
425             m_IsoHandlers.erase(it);
426             return updateShadowMapFor(handler);
427         }
428     }
429     debugFatal("Could not find handler (%p)\n", handler);
430     return false; //not found
431 }
432
433 /**
434  * Registers an StreamProcessor with the IsoHandlerManager.
435  *
436  * If nescessary, an IsoHandler is created to handle this stream.
437  * Once an StreamProcessor is registered to the handler, it will be included
438  * in the ISO streaming cycle (i.e. receive/transmit of it will occur).
439  *
440  * @param stream the stream to register
441  * @return true if registration succeeds
442  *
443  * \todo : currently there is a one-to-one mapping
444  *        between streams and handlers, this is not ok for
445  *        multichannel receive
446  */
447 bool IsoHandlerManager::registerStream(StreamProcessor *stream)
448 {
449     debugOutput( DEBUG_LEVEL_VERBOSE, "Registering stream %p\n",stream);
450     assert(stream);
451
452     IsoHandler* h = NULL;
453
454     // make sure the stream isn't already attached to a handler
455     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
456       it != m_IsoHandlers.end();
457       ++it )
458     {
459         if((*it)->isStreamRegistered(stream)) {
460             debugError( "stream already registered!\n");
461             return false;
462         }
463     }
464
465     // clean up all handlers that aren't used
466     pruneHandlers();
467
468     // allocate a handler for this stream
469     if (stream->getType()==StreamProcessor::ePT_Receive) {
470         // setup the optimal parameters for the raw1394 ISO buffering
471         unsigned int packets_per_period = stream->getPacketsPerPeriod();
472         unsigned int max_packet_size = stream->getMaxPacketSize();
473         unsigned int page_size = getpagesize() - 2; // for one reason or another this is necessary
474
475         // Ensure we don't request a packet size bigger than the
476         // kernel-enforced maximum which is currently 1 page.
477         if (max_packet_size > page_size) {
478             debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size);
479             return false;
480         }
481
482         unsigned int irq_interval = packets_per_period / MINIMUM_INTERRUPTS_PER_PERIOD;
483         if(irq_interval <= 0) irq_interval=1;
484        
485         // the receive buffer size doesn't matter for the latency,
486         // but it has a minimal value in order for libraw to operate correctly (300)
487         int buffers=400;
488
489         // create the actual handler
490         h = new IsoHandler(*this, IsoHandler::eHT_Receive,
491                            buffers, max_packet_size, irq_interval);
492
493         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoRecvHandler\n");
494
495         if(!h) {
496             debugFatal("Could not create IsoRecvHandler\n");
497             return false;
498         }
499
500     } else if (stream->getType()==StreamProcessor::ePT_Transmit) {
501         // setup the optimal parameters for the raw1394 ISO buffering
502         unsigned int packets_per_period = stream->getPacketsPerPeriod();
503         unsigned int max_packet_size = stream->getMaxPacketSize();
504 //         unsigned int page_size = getpagesize();
505
506         // Ensure we don't request a packet size bigger than the
507         // kernel-enforced maximum which is currently 1 page.
508 //         if (max_packet_size > page_size) {
509 //             debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size);
510 //             return false;
511 //         }
512         if (max_packet_size > MAX_XMIT_PACKET_SIZE) {
513             debugError("max packet size (%u) > MAX_XMIT_PACKET_SIZE (%u)\n",
514                        max_packet_size, MAX_XMIT_PACKET_SIZE);
515             return false;
516         }
517
518         // the SP specifies how many packets to ISO-buffer
519         int buffers = stream->getNbPacketsIsoXmitBuffer();
520         if (buffers > MAX_XMIT_NB_BUFFERS) {
521             debugOutput(DEBUG_LEVEL_VERBOSE,
522                         "nb buffers (%u) > MAX_XMIT_NB_BUFFERS (%u)\n",
523                         buffers, MAX_XMIT_NB_BUFFERS);
524             buffers = MAX_XMIT_NB_BUFFERS;
525         }
526         unsigned int irq_interval = buffers / MINIMUM_INTERRUPTS_PER_PERIOD;
527         if(irq_interval <= 0) irq_interval=1;
528
529         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoXmitHandler\n");
530
531         // create the actual handler
532         h = new IsoHandler(*this, IsoHandler::eHT_Transmit,
533                            buffers, max_packet_size, irq_interval);
534
535         if(!h) {
536             debugFatal("Could not create IsoXmitHandler\n");
537             return false;
538         }
539
540     } else {
541         debugFatal("Bad stream type\n");
542         return false;
543     }
544
545     h->setVerboseLevel(getDebugLevel());
546
547     // init the handler
548     if(!h->init()) {
549         debugFatal("Could not initialize receive handler\n");
550         return false;
551     }
552
553     // set the handler's thread parameters
554     // receive handlers have lower priority than the client thread
555     // since they have ISO side buffering
556     // xmit handlers have higher priority since we want client side
557     // frames to be put into the ISO buffers ASAP
558     int thread_prio;
559     if (stream->getType()==StreamProcessor::ePT_Receive) {
560         thread_prio = m_priority - 1;
561         if (thread_prio < THREAD_MIN_RTPRIO) thread_prio = THREAD_MIN_RTPRIO;
562     } else {
563         thread_prio = m_priority + 1;
564         if (thread_prio > THREAD_MAX_RTPRIO) thread_prio = THREAD_MAX_RTPRIO;
565     }
566
567     // register the stream with the handler
568     if(!h->registerStream(stream)) {
569         debugFatal("Could not register receive stream with handler\n");
570         return false;
571     }
572
573     // register the handler with the manager
574     if(!registerHandler(h)) {
575         debugFatal("Could not register receive handler with manager\n");
576         return false;
577     }
578     debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n", stream, h);
579
580     m_StreamProcessors.push_back(stream);
581     debugOutput( DEBUG_LEVEL_VERBOSE, " %d streams, %d handlers registered\n",
582                                       m_StreamProcessors.size(), m_IsoHandlers.size());
583     return true;
584 }
585
586 bool IsoHandlerManager::unregisterStream(StreamProcessor *stream)
587 {
588     debugOutput( DEBUG_LEVEL_VERBOSE, "Unregistering stream %p\n",stream);
589     assert(stream);
590
591     // make sure the stream isn't attached to a handler anymore
592     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
593       it != m_IsoHandlers.end();
594       ++it )
595     {
596         if((*it)->isStreamRegistered(stream)) {
597             if(!(*it)->unregisterStream(stream)) {
598                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not unregister stream (%p) from handler (%p)...\n",stream,*it);
599                 return false;
600             }
601             debugOutput( DEBUG_LEVEL_VERBOSE, " unregistered stream (%p) from handler (%p)...\n",stream,*it);
602         }
603     }
604
605     // clean up all handlers that aren't used
606     pruneHandlers();
607
608     // remove the stream from the registered streams list
609     for ( StreamProcessorVectorIterator it = m_StreamProcessors.begin();
610       it != m_StreamProcessors.end();
611       ++it )
612     {
613         if ( *it == stream ) {
614             m_StreamProcessors.erase(it);
615             debugOutput( DEBUG_LEVEL_VERBOSE, " deleted stream (%p) from list...\n", *it);
616             return true;
617         }
618     }
619     return false; //not found
620 }
621
622 /**
623  * @brief unregister a handler from the manager
624  * @note called without the lock held.
625  */
626 void IsoHandlerManager::pruneHandlers() {
627     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
628     IsoHandlerVector toUnregister;
629
630     // find all handlers that are not in use
631     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
632           it != m_IsoHandlers.end();
633           ++it )
634     {
635         if(!((*it)->inUse())) {
636             debugOutput( DEBUG_LEVEL_VERBOSE, " handler (%p) not in use\n",*it);
637             toUnregister.push_back(*it);
638         }
639     }
640     // delete them
641     for ( IsoHandlerVectorIterator it = toUnregister.begin();
642           it != toUnregister.end();
643           ++it )
644     {
645         unregisterHandler(*it);
646
647         debugOutput( DEBUG_LEVEL_VERBOSE, " deleting handler (%p)\n",*it);
648
649         // Now the handler's been unregistered it won't be reused
650         // again.  Therefore it really needs to be formally deleted
651         // to free up the raw1394 handle.  Otherwise things fall
652         // apart after several xrun recoveries as the system runs
653         // out of resources to support all the disused but still
654         // allocated raw1394 handles.  At least this is the current
655         // theory as to why we end up with "memory allocation"
656         // failures after several Xrun recoveries.
657         delete *it;
658     }
659 }
660
661 bool
662 IsoHandlerManager::stopHandlerForStream(Streaming::StreamProcessor *stream) {
663     // check state
664     if(m_State != E_Running) {
665         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
666         return false;
667     }
668     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
669       it != m_IsoHandlers.end();
670       ++it )
671     {
672         if((*it)->isStreamRegistered(stream)) {
673             debugOutput( DEBUG_LEVEL_VERBOSE, " stopping handler %p for stream %p\n", *it, stream);
674             if(!(*it)->disable()) {
675                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not disable handler (%p)\n",*it);
676                 return false;
677             }
678             if(!updateShadowMapFor(*it)) {
679                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
680                 return false;
681             }
682             return true;
683         }
684     }
685     debugError("Stream %p has no attached handler\n", stream);
686     return false;
687 }
688
689 int
690 IsoHandlerManager::getPacketLatencyForStream(Streaming::StreamProcessor *stream) {
691     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
692       it != m_IsoHandlers.end();
693       ++it )
694     {
695         if((*it)->isStreamRegistered(stream)) {
696             return (*it)->getPacketLatency();
697         }
698     }
699     debugError("Stream %p has no attached handler\n", stream);
700     return 0;
701 }
702
703 void
704 IsoHandlerManager::flushHandlerForStream(Streaming::StreamProcessor *stream) {
705     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
706       it != m_IsoHandlers.end();
707       ++it )
708     {
709         if((*it)->isStreamRegistered(stream)) {
710             return (*it)->flush();
711         }
712     }
713     debugError("Stream %p has no attached handler\n", stream);
714     return;
715 }
716
717 bool
718 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream) {
719     return startHandlerForStream(stream, -1);
720 }
721
722 bool
723 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream, int cycle) {
724     // check state
725     if(m_State != E_Running) {
726         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
727         return false;
728     }
729     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
730       it != m_IsoHandlers.end();
731       ++it )
732     {
733         if((*it)->isStreamRegistered(stream)) {
734             debugOutput( DEBUG_LEVEL_VERBOSE, " starting handler %p for stream %p\n", *it, stream);
735             if(!(*it)->enable(cycle)) {
736                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not enable handler (%p)\n",*it);
737                 return false;
738             }
739             if(!updateShadowMapFor(*it)) {
740                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
741                 return false;
742             }
743             return true;
744         }
745     }
746     debugError("Stream %p has no attached handler\n", stream);
747     return false;
748 }
749
750 bool IsoHandlerManager::stopHandlers() {
751     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
752
753     // check state
754     if(m_State != E_Running) {
755         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
756         return false;
757     }
758
759     bool retval=true;
760
761     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
762         it != m_IsoHandlers.end();
763         ++it )
764     {
765         debugOutput( DEBUG_LEVEL_VERBOSE, "Stopping handler (%p)\n",*it);
766         if(!(*it)->disable()){
767             debugOutput( DEBUG_LEVEL_VERBOSE, " could not stop handler (%p)\n",*it);
768             retval=false;
769         }
770         if(!updateShadowMapFor(*it)) {
771             debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
772             retval=false;
773         }
774     }
775
776     if (retval) {
777         m_State=E_Prepared;
778     } else {
779         m_State=E_Error;
780     }
781     return retval;
782 }
783
784 bool IsoHandlerManager::reset() {
785     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
786     // check state
787     if(m_State == E_Error) {
788         debugFatal("Resetting from error condition not yet supported...\n");
789         return false;
790     }
791     // if not in an error condition, reset means stop the handlers
792     return stopHandlers();
793 }
794
795 void IsoHandlerManager::setVerboseLevel(int i) {
796     setDebugLevel(i);
797     // propagate the debug level
798     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
799           it != m_IsoHandlers.end();
800           ++it )
801     {
802         (*it)->setVerboseLevel(i);
803     }
804     if(m_ReceiveThread) m_ReceiveThread->setVerboseLevel(i);
805     if(m_ReceiveTask) m_ReceiveTask->setVerboseLevel(i);
806     if(m_TransmitThread) m_TransmitThread->setVerboseLevel(i);
807     if(m_TransmitTask) m_TransmitTask->setVerboseLevel(i);
808 }
809
810 void IsoHandlerManager::dumpInfo() {
811     int i=0;
812     debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping IsoHandlerManager Stream handler information...\n");
813     debugOutputShort( DEBUG_LEVEL_NORMAL, " State: %d\n",(int)m_State);
814
815     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
816           it != m_IsoHandlers.end();
817           ++it )
818     {
819         debugOutputShort( DEBUG_LEVEL_NORMAL, " IsoHandler %d (%p)\n",i++,*it);
820         (*it)->dumpInfo();
821     }
822 }
823
824 const char *
825 IsoHandlerManager::eHSToString(enum eHandlerStates s) {
826     switch (s) {
827         default: return "Invalid";
828         case E_Created: return "Created";
829         case E_Prepared: return "Prepared";
830         case E_Running: return "Running";
831         case E_Error: return "Error";
832     }
833 }
Note: See TracBrowser for help on using the browser.