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

Revision 978, 26.6 kB (checked in by ppalmers, 13 years ago)

try to detect and survive ISO thread hangup

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                 return false;
212             }
213
214             #ifdef DEBUG
215             // if this happens we end up in a deadlock!
216             if(!m_SyncIsoHandler->tryWaitForClient()) {
217                 debugFatal("inconsistency in wait functions!\n");
218                 return false;
219             }
220             #endif
221
222             debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,
223                                "(%p) sync handler ready\n",
224                                this);
225         }
226     }
227
228     // Use a shadow map of the fd's such that we don't have to update
229     // the fd map everytime we run poll(). It doesn't change that much
230     // anyway
231     err = poll (m_poll_fds_shadow, m_poll_nfds_shadow, m_poll_timeout);
232
233     if (err < 0) {
234         if (errno == EINTR) {
235             return true;
236         }
237         debugFatal("poll error: %s\n", strerror (errno));
238         return false;
239     }
240
241     for (i = 0; i < m_poll_nfds_shadow; i++) {
242         #ifdef DEBUG
243         if(m_poll_fds_shadow[i].revents) {
244             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
245                         "(%p) received events: %08X for (%d/%d, %p, %s)\n",
246                         this, m_poll_fds_shadow[i].revents,
247                         i, m_poll_nfds_shadow,
248                         m_IsoHandler_map_shadow[i],
249                         m_IsoHandler_map_shadow[i]->getTypeString());
250         }
251         #endif
252
253         // if we get here, it means two things:
254         // 1) the kernel can accept or provide packets (poll returned POLLIN)
255         // 2) the client can provide or accept packets (since we enabled polling)
256         if(m_poll_fds_shadow[i].revents & (POLLIN)) {
257             m_IsoHandler_map_shadow[i]->iterate();
258         } else {
259             // there might be some error condition
260             if (m_poll_fds_shadow[i].revents & POLLERR) {
261                 debugWarning("(%p) error on fd for %d\n", this, i);
262             }
263             if (m_poll_fds_shadow[i].revents & POLLHUP) {
264                 debugWarning("(%p) hangup on fd for %d\n", this, i);
265             }
266         }
267
268 //         #ifdef DEBUG
269 //         // check if the handler is still alive
270 //         if(m_IsoHandler_map_shadow[i]->isDead()) {
271 //             debugError("Iso handler (%p, %s) is dead!\n",
272 //                        m_IsoHandler_map_shadow[i],
273 //                        m_IsoHandler_map_shadow[i]->getTypeString());
274 //             return false; // shutdown the system
275 //         }
276 //         #endif
277
278     }
279     return true;
280
281 }
282
283 void IsoTask::setVerboseLevel(int i) {
284     setDebugLevel(i);
285 }
286
287 // -- the ISO handler manager -- //
288 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service)
289    : m_State(E_Created)
290    , m_service( service )
291    , m_realtime(false), m_priority(0)
292    , m_IsoThread ( NULL )
293    , m_IsoTask ( NULL )
294 {}
295
296 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service, bool run_rt, int rt_prio)
297    : m_State(E_Created)
298    , m_service( service )
299    , m_realtime(run_rt), m_priority(rt_prio)
300    , m_IsoThread ( NULL )
301    , m_IsoTask ( NULL )
302 {}
303
304 IsoHandlerManager::~IsoHandlerManager()
305 {
306     stopHandlers();
307     pruneHandlers();
308     if(m_IsoHandlers.size() > 0) {
309         debugError("Still some handlers in use\n");
310     }
311     if (m_IsoThread) {
312         m_IsoThread->Stop();
313         delete m_IsoThread;
314     }
315     if (m_IsoTask) {
316         delete m_IsoTask;
317     }
318 }
319
320 void
321 IsoHandlerManager::requestShadowMapUpdate()
322 {
323     if(m_IsoTask) m_IsoTask->requestShadowMapUpdate();
324 }
325
326 bool
327 IsoHandlerManager::setThreadParameters(bool rt, int priority) {
328     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) switch to: (rt=%d, prio=%d)...\n", this, rt, priority);
329     if (priority > THREAD_MAX_RTPRIO) priority = THREAD_MAX_RTPRIO; // cap the priority
330     m_realtime = rt;
331     m_priority = priority;
332
333     if (m_IsoThread) {
334         if (m_realtime) {
335             m_IsoThread->AcquireRealTime(m_priority);
336         } else {
337             m_IsoThread->DropRealTime();
338         }
339     }
340
341     return true;
342 }
343
344 bool IsoHandlerManager::init()
345 {
346     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing ISO manager %p...\n", this);
347     // check state
348     if(m_State != E_Created) {
349         debugError("Manager already initialized...\n");
350         return false;
351     }
352
353     // create a thread to iterate our ISO handlers
354     debugOutput( DEBUG_LEVEL_VERBOSE, "Create iso thread for %p...\n", this);
355     m_IsoTask = new IsoTask( *this );
356     if(!m_IsoTask) {
357         debugFatal("No task\n");
358         return false;
359     }
360     m_IsoThread = new Util::PosixThread(m_IsoTask, m_realtime,
361                                         m_priority + ISOHANDLERMANAGER_ISO_PRIO_INCREASE,
362                                         PTHREAD_CANCEL_DEFERRED);
363
364     if(!m_IsoThread) {
365         debugFatal("No thread\n");
366         return false;
367     }
368     // register the thread with the RT watchdog
369     Util::Watchdog *watchdog = m_service.getWatchdog();
370     if(watchdog) {
371         if(!watchdog->registerThread(m_IsoThread)) {
372             debugWarning("could not register iso thread with watchdog\n");
373         }
374     } else {
375         debugWarning("could not find valid watchdog\n");
376     }
377
378     if (m_IsoThread->Start() != 0) {
379         debugFatal("Could not start ISO thread\n");
380         return false;
381     }
382
383     m_State=E_Running;
384     return true;
385 }
386
387 bool
388 IsoHandlerManager::disable(IsoHandler *h) {
389     bool result;
390     int i=0;
391     debugOutput(DEBUG_LEVEL_VERBOSE, "Disable on IsoHandler %p\n", h);
392     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
393         it != m_IsoHandlers.end();
394         ++it )
395     {
396         if ((*it) == h) {
397             result = h->disable();
398             result &= m_IsoTask->requestShadowMapUpdate();
399             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " disabled\n");
400             return result;
401         }
402         i++;
403     }
404     debugError("Handler not found\n");
405     return false;
406 }
407
408 bool
409 IsoHandlerManager::enable(IsoHandler *h) {
410     bool result;
411     int i=0;
412     debugOutput(DEBUG_LEVEL_VERBOSE, "Enable on IsoHandler %p\n", h);
413     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
414         it != m_IsoHandlers.end();
415         ++it )
416     {
417         if ((*it) == h) {
418             result = h->enable();
419             result &= m_IsoTask->requestShadowMapUpdate();
420             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " enabled\n");
421             return result;
422         }
423         i++;
424     }
425     debugError("Handler not found\n");
426     return false;
427 }
428
429 bool IsoHandlerManager::registerHandler(IsoHandler *handler)
430 {
431     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
432     assert(handler);
433     handler->setVerboseLevel(getDebugLevel());
434     m_IsoHandlers.push_back(handler);
435     return m_IsoTask->requestShadowMapUpdate();
436 }
437
438 bool IsoHandlerManager::unregisterHandler(IsoHandler *handler)
439 {
440     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
441     assert(handler);
442
443     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
444       it != m_IsoHandlers.end();
445       ++it )
446     {
447         if ( *it == handler ) {
448             m_IsoHandlers.erase(it);
449             return m_IsoTask->requestShadowMapUpdate();
450         }
451     }
452     debugFatal("Could not find handler (%p)\n", handler);
453     return false; //not found
454 }
455
456 /**
457  * Registers an StreamProcessor with the IsoHandlerManager.
458  *
459  * If nescessary, an IsoHandler is created to handle this stream.
460  * Once an StreamProcessor is registered to the handler, it will be included
461  * in the ISO streaming cycle (i.e. receive/transmit of it will occur).
462  *
463  * @param stream the stream to register
464  * @return true if registration succeeds
465  *
466  * \todo : currently there is a one-to-one mapping
467  *        between streams and handlers, this is not ok for
468  *        multichannel receive
469  */
470 bool IsoHandlerManager::registerStream(StreamProcessor *stream)
471 {
472     debugOutput( DEBUG_LEVEL_VERBOSE, "Registering stream %p\n",stream);
473     assert(stream);
474
475     IsoHandler* h = NULL;
476
477     // make sure the stream isn't already attached to a handler
478     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
479       it != m_IsoHandlers.end();
480       ++it )
481     {
482         if((*it)->isStreamRegistered(stream)) {
483             debugError( "stream already registered!\n");
484             return false;
485         }
486     }
487
488     // clean up all handlers that aren't used
489     pruneHandlers();
490
491     // allocate a handler for this stream
492     if (stream->getType()==StreamProcessor::ePT_Receive) {
493         // setup the optimal parameters for the raw1394 ISO buffering
494         unsigned int packets_per_period = stream->getPacketsPerPeriod();
495         unsigned int max_packet_size = stream->getMaxPacketSize();
496         unsigned int page_size = getpagesize() - 2; // for one reason or another this is necessary
497
498         // Ensure we don't request a packet size bigger than the
499         // kernel-enforced maximum which is currently 1 page.
500         if (max_packet_size > page_size) {
501             debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size);
502             return false;
503         }
504
505         unsigned int irq_interval = packets_per_period / MINIMUM_INTERRUPTS_PER_PERIOD;
506         if(irq_interval <= 0) irq_interval=1;
507        
508         // the receive buffer size doesn't matter for the latency,
509         // but it has a minimal value in order for libraw to operate correctly (300)
510         int buffers=400;
511
512         // create the actual handler
513         h = new IsoHandler(*this, IsoHandler::eHT_Receive,
514                            buffers, max_packet_size, irq_interval);
515
516         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoRecvHandler\n");
517
518         if(!h) {
519             debugFatal("Could not create IsoRecvHandler\n");
520             return false;
521         }
522
523     } else if (stream->getType()==StreamProcessor::ePT_Transmit) {
524         // setup the optimal parameters for the raw1394 ISO buffering
525 //        unsigned int packets_per_period = stream->getPacketsPerPeriod();
526         unsigned int max_packet_size = stream->getMaxPacketSize();
527 //         unsigned int page_size = getpagesize();
528
529         // Ensure we don't request a packet size bigger than the
530         // kernel-enforced maximum which is currently 1 page.
531 //         if (max_packet_size > page_size) {
532 //             debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size);
533 //             return false;
534 //         }
535         if (max_packet_size > MAX_XMIT_PACKET_SIZE) {
536             debugError("max packet size (%u) > MAX_XMIT_PACKET_SIZE (%u)\n",
537                        max_packet_size, MAX_XMIT_PACKET_SIZE);
538             return false;
539         }
540
541         // the SP specifies how many packets to ISO-buffer
542         int buffers = stream->getNbPacketsIsoXmitBuffer();
543         if (buffers > MAX_XMIT_NB_BUFFERS) {
544             debugOutput(DEBUG_LEVEL_VERBOSE,
545                         "nb buffers (%u) > MAX_XMIT_NB_BUFFERS (%u)\n",
546                         buffers, MAX_XMIT_NB_BUFFERS);
547             buffers = MAX_XMIT_NB_BUFFERS;
548         }
549         unsigned int irq_interval = buffers / MINIMUM_INTERRUPTS_PER_PERIOD;
550         if(irq_interval <= 0) irq_interval=1;
551
552         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoXmitHandler\n");
553
554         // create the actual handler
555         h = new IsoHandler(*this, IsoHandler::eHT_Transmit,
556                            buffers, max_packet_size, irq_interval);
557
558         if(!h) {
559             debugFatal("Could not create IsoXmitHandler\n");
560             return false;
561         }
562
563     } else {
564         debugFatal("Bad stream type\n");
565         return false;
566     }
567
568     h->setVerboseLevel(getDebugLevel());
569
570     // init the handler
571     if(!h->init()) {
572         debugFatal("Could not initialize receive handler\n");
573         return false;
574     }
575
576     // register the stream with the handler
577     if(!h->registerStream(stream)) {
578         debugFatal("Could not register receive stream with handler\n");
579         return false;
580     }
581
582     // register the handler with the manager
583     if(!registerHandler(h)) {
584         debugFatal("Could not register receive handler with manager\n");
585         return false;
586     }
587     debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n", stream, h);
588
589     m_StreamProcessors.push_back(stream);
590     debugOutput( DEBUG_LEVEL_VERBOSE, " %d streams, %d handlers registered\n",
591                                       m_StreamProcessors.size(), m_IsoHandlers.size());
592     return true;
593 }
594
595 bool IsoHandlerManager::unregisterStream(StreamProcessor *stream)
596 {
597     debugOutput( DEBUG_LEVEL_VERBOSE, "Unregistering stream %p\n",stream);
598     assert(stream);
599
600     // make sure the stream isn't attached to a handler anymore
601     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
602       it != m_IsoHandlers.end();
603       ++it )
604     {
605         if((*it)->isStreamRegistered(stream)) {
606             if(!(*it)->unregisterStream(stream)) {
607                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not unregister stream (%p) from handler (%p)...\n",stream,*it);
608                 return false;
609             }
610             debugOutput( DEBUG_LEVEL_VERBOSE, " unregistered stream (%p) from handler (%p)...\n",stream,*it);
611         }
612     }
613
614     // clean up all handlers that aren't used
615     pruneHandlers();
616
617     // remove the stream from the registered streams list
618     for ( StreamProcessorVectorIterator it = m_StreamProcessors.begin();
619       it != m_StreamProcessors.end();
620       ++it )
621     {
622         if ( *it == stream ) {
623             m_StreamProcessors.erase(it);
624             debugOutput( DEBUG_LEVEL_VERBOSE, " deleted stream (%p) from list...\n", *it);
625             return true;
626         }
627     }
628     return false; //not found
629 }
630
631 /**
632  * @brief unregister a handler from the manager
633  * @note called without the lock held.
634  */
635 void IsoHandlerManager::pruneHandlers() {
636     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
637     IsoHandlerVector toUnregister;
638
639     // find all handlers that are not in use
640     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
641           it != m_IsoHandlers.end();
642           ++it )
643     {
644         if(!((*it)->inUse())) {
645             debugOutput( DEBUG_LEVEL_VERBOSE, " handler (%p) not in use\n",*it);
646             toUnregister.push_back(*it);
647         }
648     }
649     // delete them
650     for ( IsoHandlerVectorIterator it = toUnregister.begin();
651           it != toUnregister.end();
652           ++it )
653     {
654         unregisterHandler(*it);
655
656         debugOutput( DEBUG_LEVEL_VERBOSE, " deleting handler (%p)\n",*it);
657
658         // Now the handler's been unregistered it won't be reused
659         // again.  Therefore it really needs to be formally deleted
660         // to free up the raw1394 handle.  Otherwise things fall
661         // apart after several xrun recoveries as the system runs
662         // out of resources to support all the disused but still
663         // allocated raw1394 handles.  At least this is the current
664         // theory as to why we end up with "memory allocation"
665         // failures after several Xrun recoveries.
666         delete *it;
667     }
668 }
669
670 bool
671 IsoHandlerManager::stopHandlerForStream(Streaming::StreamProcessor *stream) {
672     // check state
673     if(m_State != E_Running) {
674         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
675         return false;
676     }
677     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
678       it != m_IsoHandlers.end();
679       ++it )
680     {
681         if((*it)->isStreamRegistered(stream)) {
682             debugOutput( DEBUG_LEVEL_VERBOSE, " stopping handler %p for stream %p\n", *it, stream);
683             if(!(*it)->disable()) {
684                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not disable handler (%p)\n",*it);
685                 return false;
686             }
687             if(!m_IsoTask->requestShadowMapUpdate()) {
688                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
689                 return false;
690             }
691             return true;
692         }
693     }
694     debugError("Stream %p has no attached handler\n", stream);
695     return false;
696 }
697
698 int
699 IsoHandlerManager::getPacketLatencyForStream(Streaming::StreamProcessor *stream) {
700     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
701       it != m_IsoHandlers.end();
702       ++it )
703     {
704         if((*it)->isStreamRegistered(stream)) {
705             return (*it)->getPacketLatency();
706         }
707     }
708     debugError("Stream %p has no attached handler\n", stream);
709     return 0;
710 }
711
712 void
713 IsoHandlerManager::flushHandlerForStream(Streaming::StreamProcessor *stream) {
714     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
715       it != m_IsoHandlers.end();
716       ++it )
717     {
718         if((*it)->isStreamRegistered(stream)) {
719             return (*it)->flush();
720         }
721     }
722     debugError("Stream %p has no attached handler\n", stream);
723     return;
724 }
725
726 bool
727 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream) {
728     return startHandlerForStream(stream, -1);
729 }
730
731 bool
732 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream, int cycle) {
733     // check state
734     if(m_State != E_Running) {
735         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
736         return false;
737     }
738     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
739       it != m_IsoHandlers.end();
740       ++it )
741     {
742         if((*it)->isStreamRegistered(stream)) {
743             debugOutput( DEBUG_LEVEL_VERBOSE, " starting handler %p for stream %p\n", *it, stream);
744             if(!(*it)->enable(cycle)) {
745                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not enable handler (%p)\n",*it);
746                 return false;
747             }
748             if(!m_IsoTask->requestShadowMapUpdate()) {
749                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
750                 return false;
751             }
752             return true;
753         }
754     }
755     debugError("Stream %p has no attached handler\n", stream);
756     return false;
757 }
758
759 bool IsoHandlerManager::stopHandlers() {
760     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
761
762     // check state
763     if(m_State != E_Running) {
764         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
765         return false;
766     }
767
768     bool retval=true;
769
770     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
771         it != m_IsoHandlers.end();
772         ++it )
773     {
774         debugOutput( DEBUG_LEVEL_VERBOSE, "Stopping handler (%p)\n",*it);
775         if(!(*it)->disable()){
776             debugOutput( DEBUG_LEVEL_VERBOSE, " could not stop handler (%p)\n",*it);
777             retval=false;
778         }
779         if(!m_IsoTask->requestShadowMapUpdate()) {
780             debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
781             retval=false;
782         }
783     }
784
785     if (retval) {
786         m_State=E_Prepared;
787     } else {
788         m_State=E_Error;
789     }
790     return retval;
791 }
792
793 bool IsoHandlerManager::reset() {
794     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
795     // check state
796     if(m_State == E_Error) {
797         debugFatal("Resetting from error condition not yet supported...\n");
798         return false;
799     }
800     // if not in an error condition, reset means stop the handlers
801     return stopHandlers();
802 }
803
804 void IsoHandlerManager::setVerboseLevel(int i) {
805     setDebugLevel(i);
806     // propagate the debug level
807     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
808           it != m_IsoHandlers.end();
809           ++it )
810     {
811         (*it)->setVerboseLevel(i);
812     }
813     if(m_IsoThread) m_IsoThread->setVerboseLevel(i);
814     if(m_IsoTask)   m_IsoTask->setVerboseLevel(i);
815 }
816
817 void IsoHandlerManager::dumpInfo() {
818     #ifdef DEBUG
819     unsigned int i=0;
820     debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping IsoHandlerManager Stream handler information...\n");
821     debugOutputShort( DEBUG_LEVEL_NORMAL, " State: %d\n",(int)m_State);
822
823     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
824           it != m_IsoHandlers.end();
825           ++it )
826     {
827         debugOutputShort( DEBUG_LEVEL_NORMAL, " IsoHandler %d (%p)\n",i++,*it);
828         (*it)->dumpInfo();
829     }
830     #endif
831 }
832
833 const char *
834 IsoHandlerManager::eHSToString(enum eHandlerStates s) {
835     switch (s) {
836         default: return "Invalid";
837         case E_Created: return "Created";
838         case E_Prepared: return "Prepared";
839         case E_Running: return "Running";
840         case E_Error: return "Error";
841     }
842 }
Note: See TracBrowser for help on using the browser.