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

Revision 993, 26.8 kB (checked in by ppalmers, 13 years ago)

fix deadlock (hackish but working)

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