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

Revision 776, 23.2 kB (checked in by ppalmers, 16 years ago)

try to fix deadlock / performace issues

Line 
1 /*
2  * Copyright (C) 2005-2007 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 3 of the License, or
12  * (at your option) any later version.
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 "IsoHandlerManager.h"
25 #include "ieee1394service.h"
26 #include "IsoHandler.h"
27 #include "libstreaming/generic/StreamProcessor.h"
28
29 #include "libutil/Atomic.h"
30
31 #include "libutil/PosixThread.h"
32
33 #include <assert.h>
34
35 #define MINIMUM_INTERRUPTS_PER_PERIOD  4U
36
37 IMPL_DEBUG_MODULE( IsoHandlerManager, IsoHandlerManager, DEBUG_LEVEL_NORMAL );
38
39 using namespace Streaming;
40
41 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service)
42    : m_State(E_Created)
43    , m_service( service )
44    , m_realtime(false), m_priority(0)
45    , m_Thread ( NULL )
46 {}
47
48 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service, bool run_rt, int rt_prio)
49    : m_State(E_Created)
50    , m_service( service )
51    , m_realtime(run_rt), m_priority(rt_prio)
52    , m_Thread ( NULL )
53 {}
54
55 IsoHandlerManager::~IsoHandlerManager()
56 {
57     stopHandlers();
58     if (m_Thread) {
59         m_Thread->Stop();
60         delete m_Thread;
61     }
62 }
63
64 bool
65 IsoHandlerManager::setThreadParameters(bool rt, int priority) {
66     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) switch to: (rt=%d, prio=%d)...\n", this, rt, priority);
67     if (priority > 98) priority = 98; // cap the priority
68     m_realtime = rt;
69     m_priority = priority;
70     bool result = true;
71     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
72         it != m_IsoHandlers.end();
73         ++it )
74     {
75         result &= (*it)->setThreadParameters(m_realtime, m_priority);
76     }
77
78     if (m_Thread) {
79         if (m_realtime) {
80             m_Thread->AcquireRealTime(m_priority);
81         } else {
82             m_Thread->DropRealTime();
83         }
84     }
85
86     return result;
87 }
88
89 /**
90  * Update the shadow variables. Should only be called from
91  * the iso handler iteration thread
92  */
93 void
94 IsoHandlerManager::updateShadowVars()
95 {
96     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "updating shadow vars...\n");
97     unsigned int i;
98     m_poll_nfds_shadow = m_IsoHandlers.size();
99     if(m_poll_nfds_shadow > FFADO_MAX_ISO_HANDLERS_PER_PORT) {
100         debugWarning("Too much ISO Handlers in manager...\n");
101         m_poll_nfds_shadow = FFADO_MAX_ISO_HANDLERS_PER_PORT;
102     }
103     for (i = 0; i < m_poll_nfds_shadow; i++) {
104         IsoHandler *h = m_IsoHandlers.at(i);
105         assert(h);
106         m_IsoHandler_map_shadow[i] = h;
107
108         m_poll_fds_shadow[i].fd = h->getFileDescriptor();
109         m_poll_fds_shadow[i].revents = 0;
110         if (h->isEnabled()) {
111             m_poll_fds_shadow[i].events = POLLIN;
112         } else {
113             m_poll_fds_shadow[i].events = 0;
114         }
115     }
116     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, " updated shadow vars...\n");
117 }
118
119 bool
120 IsoHandlerManager::Init() {
121     debugOutput( DEBUG_LEVEL_VERBOSE, "%p: Init thread...\n", this);
122     bool result = true;
123     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
124         it != m_IsoHandlers.end();
125         ++it )
126     {
127         result &= (*it)->Init();
128     }
129     return result;
130 }
131
132 bool
133 IsoHandlerManager::Execute() {
134     int err;
135     unsigned int i;
136
137     unsigned int m_poll_timeout = 100;
138
139     // update the shadow variables if requested
140    // if(m_request_fdmap_update) {
141         updateShadowVars();
142     //    ZERO_ATOMIC((SInt32*)&m_request_fdmap_update);
143     //}
144
145     // bypass if no handlers are registered
146     if (m_poll_nfds_shadow == 0) {
147         usleep(m_poll_timeout * 1000);
148         return true;
149     }
150
151     // Use a shadow map of the fd's such that the poll call is not in a critical section
152     uint64_t poll_enter = m_service.getCurrentTimeAsUsecs();
153     err = poll (m_poll_fds_shadow, m_poll_nfds_shadow, m_poll_timeout);
154     uint64_t poll_exit = m_service.getCurrentTimeAsUsecs();
155
156     if (err == -1) {
157         if (errno == EINTR) {
158             return true;
159         }
160         debugFatal("poll error: %s\n", strerror (errno));
161         return false;
162     }
163
164     int nb_rcv = 0;
165     int nb_xmit = 0;
166     uint64_t iter_enter = m_service.getCurrentTimeAsUsecs();
167     for (i = 0; i < m_poll_nfds_shadow; i++) {
168         if(m_poll_fds_shadow[i].revents) {
169             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "received events: %08X for (%p)\n",
170                 m_poll_fds_shadow[i].revents, m_IsoHandler_map_shadow[i]);
171         }
172         if (m_poll_fds_shadow[i].revents & POLLERR) {
173             debugWarning("error on fd for %d\n",i);
174         }
175
176         if (m_poll_fds_shadow[i].revents & POLLHUP) {
177             debugWarning("hangup on fd for %d\n",i);
178         }
179
180         if(m_poll_fds_shadow[i].revents & (POLLIN)) {
181             m_IsoHandler_map_shadow[i]->iterate();
182             if (m_IsoHandler_map_shadow[i]->getType() == IsoHandler::eHT_Receive) {
183                 nb_rcv++;
184             } else {
185                 nb_xmit++;
186             }
187         }
188     }
189     uint64_t iter_exit = m_service.getCurrentTimeAsUsecs();
190    
191     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " poll took %6lldus, iterate took %6lldus, iterated (R: %2d, X: %2d) handlers\n",
192                 poll_exit-poll_enter, iter_exit-iter_enter,
193                 nb_rcv, nb_xmit);
194
195     return true;
196 }
197
198 bool IsoHandlerManager::init()
199 {
200     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing ISO manager %p...\n", this);
201     // check state
202     if(m_State != E_Created) {
203         debugError("Manager already initialized...\n");
204         return false;
205     }
206
207 #ifndef THREAD_PER_ISOHANDLER
208     // create a thread to iterate our handlers
209     debugOutput( DEBUG_LEVEL_VERBOSE, "Start thread for %p...\n", this);
210     m_Thread = new Util::PosixThread(this, m_realtime, m_priority,
211                                      PTHREAD_CANCEL_DEFERRED);
212     if(!m_Thread) {
213         debugFatal("No thread\n");
214         return false;
215     }
216     if (m_Thread->Start() != 0) {
217         debugFatal("Could not start update thread\n");
218         return false;
219     }
220 #endif
221
222     m_State=E_Running;
223     return true;
224 }
225
226 bool
227 IsoHandlerManager::disable(IsoHandler *h) {
228     bool result;
229     int i=0;
230     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Disable on IsoHandler %p\n", h);
231     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
232         it != m_IsoHandlers.end();
233         ++it )
234     {
235         if ((*it) == h) {
236             result = h->disable();
237             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " disabled\n");
238             return result;
239         }
240         i++;
241     }
242     debugError("Handler not found\n");
243     return false;
244 }
245
246 bool
247 IsoHandlerManager::enable(IsoHandler *h) {
248     bool result;
249     int i=0;
250     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Enable on IsoHandler %p\n", h);
251     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
252         it != m_IsoHandlers.end();
253         ++it )
254     {
255         if ((*it) == h) {
256             result = h->enable();
257             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " enabled\n");
258             return result;
259         }
260         i++;
261     }
262     debugError("Handler not found\n");
263     return false;
264 }
265
266 bool IsoHandlerManager::registerHandler(IsoHandler *handler)
267 {
268     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
269     assert(handler);
270     handler->setVerboseLevel(getDebugLevel());
271     m_IsoHandlers.push_back(handler);
272     return true;
273 }
274
275 bool IsoHandlerManager::unregisterHandler(IsoHandler *handler)
276 {
277     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
278     assert(handler);
279
280     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
281       it != m_IsoHandlers.end();
282       ++it )
283     {
284         if ( *it == handler ) {
285             m_IsoHandlers.erase(it);
286             return true;
287         }
288     }
289     debugFatal("Could not find handler (%p)\n", handler);
290     return false; //not found
291 }
292
293 /**
294  * Registers an StreamProcessor with the IsoHandlerManager.
295  *
296  * If nescessary, an IsoHandler is created to handle this stream.
297  * Once an StreamProcessor is registered to the handler, it will be included
298  * in the ISO streaming cycle (i.e. receive/transmit of it will occur).
299  *
300  * @param stream the stream to register
301  * @return true if registration succeeds
302  *
303  * \todo : currently there is a one-to-one mapping
304  *        between streams and handlers, this is not ok for
305  *        multichannel receive
306  */
307 bool IsoHandlerManager::registerStream(StreamProcessor *stream)
308 {
309     debugOutput( DEBUG_LEVEL_VERBOSE, "Registering stream %p\n",stream);
310     assert(stream);
311
312     IsoHandler* h = NULL;
313
314     // make sure the stream isn't already attached to a handler
315     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
316       it != m_IsoHandlers.end();
317       ++it )
318     {
319         if((*it)->isStreamRegistered(stream)) {
320             debugError( "stream already registered!\n");
321             return false;
322         }
323     }
324
325     // clean up all handlers that aren't used
326     pruneHandlers();
327
328     // allocate a handler for this stream
329     if (stream->getType()==StreamProcessor::ePT_Receive) {
330         // setup the optimal parameters for the raw1394 ISO buffering
331         unsigned int packets_per_period = stream->getPacketsPerPeriod();
332
333 #if 1
334         // hardware interrupts occur when one DMA block is full, and the size of one DMA
335         // block = PAGE_SIZE. Setting the max_packet_size makes sure that the HW irq
336         // occurs at a period boundary (optimal CPU use)
337
338         // NOTE: try and use MINIMUM_INTERRUPTS_PER_PERIOD hardware interrupts
339         //       per period for better latency.
340         unsigned int max_packet_size=(MINIMUM_INTERRUPTS_PER_PERIOD * getpagesize()/2) / packets_per_period;
341
342         if (max_packet_size < stream->getMaxPacketSize()) {
343             debugWarning("calculated max packet size (%u) < stream max packet size (%u)\n",
344                          max_packet_size ,(unsigned int)stream->getMaxPacketSize());
345             max_packet_size = stream->getMaxPacketSize();
346         }
347
348         // Ensure we don't request a packet size bigger than the
349         // kernel-enforced maximum which is currently 1 page.
350         if (max_packet_size > (unsigned int)getpagesize()/2) {
351             debugError("max packet size (%u) > page size (%u)\n", max_packet_size, (unsigned int)getpagesize()/2);
352             return false;
353         }
354
355         unsigned int irq_interval = packets_per_period / MINIMUM_INTERRUPTS_PER_PERIOD;
356         if(irq_interval <= 0) irq_interval=1;
357         // FIXME: test
358 //        irq_interval=1;
359
360 #else
361         // hardware interrupts occur when one DMA block is full, and the size of one DMA
362         // block = PAGE_SIZE. Setting the max_packet_size enables control over the IRQ
363         // frequency, as the controller uses max_packet_size, and not the effective size
364         // when writing to the DMA buffer.
365
366         // configure it such that we have an irq for every PACKETS_PER_INTERRUPT packets
367         unsigned int irq_interval = packets_per_period/MINIMUM_INTERRUPTS_PER_PERIOD;
368         if(irq_interval <= 0) irq_interval = 1;
369
370         unsigned int max_packet_size = getpagesize()/2;
371
372         if (max_packet_size < stream->getMaxPacketSize()) {
373             debugError("Stream max packet size too large: %d\n", stream->getMaxPacketSize());
374             return false;
375         }
376
377 #endif
378         /* the receive buffer size doesn't matter for the latency,
379            but it has a minimal value in order for libraw to operate correctly (300) */
380         int buffers=400;
381         //max_packet_size = getpagesize(); // HACK
382         //irq_interval=2; // HACK
383         // create the actual handler
384         h = new IsoHandler(*this, IsoHandler::eHT_Receive,
385                            buffers, max_packet_size, irq_interval);
386
387         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoRecvHandler\n");
388
389         if(!h) {
390             debugFatal("Could not create IsoRecvHandler\n");
391             return false;
392         }
393
394     } else if (stream->getType()==StreamProcessor::ePT_Transmit) {
395         // setup the optimal parameters for the raw1394 ISO buffering
396         unsigned int packets_per_period = stream->getPacketsPerPeriod();
397
398 #if 0
399         // hardware interrupts occur when one DMA block is full, and the size of one DMA
400         // block = PAGE_SIZE. Setting the max_packet_size makes sure that the HW irq
401         // occurs at a period boundary (optimal CPU use)
402         // NOTE: try and use MINIMUM_INTERRUPTS_PER_PERIOD interrupts per period
403         //       for better latency.
404         unsigned int max_packet_size=MINIMUM_INTERRUPTS_PER_PERIOD * getpagesize() / packets_per_period;
405         if (max_packet_size < stream->getMaxPacketSize()) {
406             max_packet_size = stream->getMaxPacketSize();
407         }
408
409         // Ensure we don't request a packet size bigger than the
410         // kernel-enforced maximum which is currently 1 page.
411         if (max_packet_size > (unsigned int)getpagesize())
412                     max_packet_size = getpagesize();
413
414          unsigned int irq_interval = packets_per_period / MINIMUM_INTERRUPTS_PER_PERIOD;
415          if(irq_interval <= 0) irq_interval = 1;
416
417         // the transmit buffer size should be as low as possible for latency.
418         // note however that the raw1394 subsystem tries to keep this buffer
419         // full, so we have to make sure that we have enough events in our
420         // event buffers
421
422         // FIXME: latency spoiler
423         // every irq_interval packets an interrupt will occur. that is when
424         // buffers get transfered, meaning that we should have at least some
425         // margin here
426         //irq_interval=2;
427         //int buffers=30;
428         //max_packet_size = getpagesize(); // HACK
429 #else
430         // configure it such that we have an irq for every PACKETS_PER_INTERRUPT packets
431         unsigned int irq_interval = packets_per_period/MINIMUM_INTERRUPTS_PER_PERIOD;
432         if(irq_interval <= 0) irq_interval = 1;
433
434         unsigned int max_packet_size=MINIMUM_INTERRUPTS_PER_PERIOD * getpagesize() / packets_per_period;
435         if (max_packet_size < stream->getMaxPacketSize()) {
436             max_packet_size = stream->getMaxPacketSize();
437         }
438
439         if (max_packet_size < stream->getMaxPacketSize()) {
440             debugError("Max packet size too large! (%d)\n", stream->getMaxPacketSize());
441         }
442   //      irq_interval=2;
443 #endif
444         // the SP specifies how many packets to buffer
445         int buffers = stream->getNbPacketsIsoXmitBuffer();
446
447         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoXmitHandler\n");
448
449         // create the actual handler
450         h = new IsoHandler(*this, IsoHandler::eHT_Transmit,
451                            buffers, max_packet_size, irq_interval);
452
453         if(!h) {
454             debugFatal("Could not create IsoXmitHandler\n");
455             return false;
456         }
457     } else {
458         debugFatal("Bad stream type\n");
459         return false;
460     }
461
462     h->setVerboseLevel(getDebugLevel());
463
464     // init the handler
465     if(!h->init()) {
466         debugFatal("Could not initialize receive handler\n");
467         return false;
468     }
469
470     // set the handler's thread parameters
471     if(!h->setThreadParameters(m_realtime, m_priority)) {
472         debugFatal("Could not set handler thread parameters\n");
473         return false;
474     }
475
476     // register the stream with the handler
477     if(!h->registerStream(stream)) {
478         debugFatal("Could not register receive stream with handler\n");
479         return false;
480     }
481
482     // register the handler with the manager
483     if(!registerHandler(h)) {
484         debugFatal("Could not register receive handler with manager\n");
485         return false;
486     }
487     debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n", stream, h);
488
489     m_StreamProcessors.push_back(stream);
490     debugOutput( DEBUG_LEVEL_VERBOSE, " %d streams, %d handlers registered\n",
491                                       m_StreamProcessors.size(), m_IsoHandlers.size());
492     return true;
493 }
494
495 bool IsoHandlerManager::unregisterStream(StreamProcessor *stream)
496 {
497     debugOutput( DEBUG_LEVEL_VERBOSE, "Unregistering stream %p\n",stream);
498     assert(stream);
499
500     // make sure the stream isn't attached to a handler anymore
501     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
502       it != m_IsoHandlers.end();
503       ++it )
504     {
505         if((*it)->isStreamRegistered(stream)) {
506             if(!(*it)->unregisterStream(stream)) {
507                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not unregister stream (%p) from handler (%p)...\n",stream,*it);
508                 return false;
509             }
510             debugOutput( DEBUG_LEVEL_VERBOSE, " unregistered stream (%p) from handler (%p)...\n",stream,*it);
511         }
512     }
513
514     // clean up all handlers that aren't used
515     pruneHandlers();
516
517     // remove the stream from the registered streams list
518     for ( StreamProcessorVectorIterator it = m_StreamProcessors.begin();
519       it != m_StreamProcessors.end();
520       ++it )
521     {
522         if ( *it == stream ) {
523             m_StreamProcessors.erase(it);
524             debugOutput( DEBUG_LEVEL_VERBOSE, " deleted stream (%p) from list...\n", *it);
525             return true;
526         }
527     }
528     return false; //not found
529 }
530
531 /**
532  * @brief unregister a handler from the manager
533  * @note called without the lock held.
534  */
535 void IsoHandlerManager::pruneHandlers() {
536     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
537     IsoHandlerVector toUnregister;
538
539     // find all handlers that are not in use
540     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
541           it != m_IsoHandlers.end();
542           ++it )
543     {
544         if(!((*it)->inUse())) {
545             debugOutput( DEBUG_LEVEL_VERBOSE, " handler (%p) not in use\n",*it);
546             toUnregister.push_back(*it);
547         }
548     }
549     // delete them
550     for ( IsoHandlerVectorIterator it = toUnregister.begin();
551           it != toUnregister.end();
552           ++it )
553     {
554         unregisterHandler(*it);
555
556         debugOutput( DEBUG_LEVEL_VERBOSE, " deleting handler (%p)\n",*it);
557
558         // Now the handler's been unregistered it won't be reused
559         // again.  Therefore it really needs to be formally deleted
560         // to free up the raw1394 handle.  Otherwise things fall
561         // apart after several xrun recoveries as the system runs
562         // out of resources to support all the disused but still
563         // allocated raw1394 handles.  At least this is the current
564         // theory as to why we end up with "memory allocation"
565         // failures after several Xrun recoveries.
566         delete *it;
567     }
568 }
569
570 bool
571 IsoHandlerManager::stopHandlerForStream(Streaming::StreamProcessor *stream) {
572     // check state
573     if(m_State != E_Running) {
574         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
575         return false;
576     }
577     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
578       it != m_IsoHandlers.end();
579       ++it )
580     {
581         if((*it)->isStreamRegistered(stream)) {
582             bool result;
583             debugOutput( DEBUG_LEVEL_VERBOSE, " stopping handler %p for stream %p\n", *it, stream);
584             result = (*it)->disable();
585             if(!result) {
586                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not disable handler (%p)\n",*it);
587                 return false;
588             }
589             return true;
590         }
591     }
592     debugError("Stream %p has no attached handler\n", stream);
593     return false;
594 }
595
596 int
597 IsoHandlerManager::getPacketLatencyForStream(Streaming::StreamProcessor *stream) {
598     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
599       it != m_IsoHandlers.end();
600       ++it )
601     {
602         if((*it)->isStreamRegistered(stream)) {
603             return (*it)->getPacketLatency();
604         }
605     }
606     debugError("Stream %p has no attached handler\n", stream);
607     return 0;
608 }
609
610 void
611 IsoHandlerManager::flushHandlerForStream(Streaming::StreamProcessor *stream) {
612     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
613       it != m_IsoHandlers.end();
614       ++it )
615     {
616         if((*it)->isStreamRegistered(stream)) {
617             return (*it)->flush();
618         }
619     }
620     debugError("Stream %p has no attached handler\n", stream);
621     return;
622 }
623
624 bool
625 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream) {
626     return startHandlerForStream(stream, -1);
627 }
628
629 bool
630 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream, int cycle) {
631     // check state
632     if(m_State != E_Running) {
633         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
634         return false;
635     }
636     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
637       it != m_IsoHandlers.end();
638       ++it )
639     {
640         if((*it)->isStreamRegistered(stream)) {
641             bool result;
642             debugOutput( DEBUG_LEVEL_VERBOSE, " starting handler %p for stream %p\n", *it, stream);
643             result = (*it)->enable(cycle);
644             if(!result) {
645                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not enable handler (%p)\n",*it);
646                 return false;
647             }
648             return true;
649         }
650     }
651     debugError("Stream %p has no attached handler\n", stream);
652     return false;
653 }
654
655 bool IsoHandlerManager::stopHandlers() {
656     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
657
658     // check state
659     if(m_State != E_Running) {
660         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
661         return false;
662     }
663
664     bool retval=true;
665
666     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
667         it != m_IsoHandlers.end();
668         ++it )
669     {
670         debugOutput( DEBUG_LEVEL_VERBOSE, "Stopping handler (%p)\n",*it);
671         if(!(*it)->disable()){
672             debugOutput( DEBUG_LEVEL_VERBOSE, " could not stop handler (%p)\n",*it);
673             retval=false;
674         }
675     }
676
677     if (retval) {
678         m_State=E_Prepared;
679     } else {
680         m_State=E_Error;
681     }
682     return retval;
683 }
684
685 bool IsoHandlerManager::reset() {
686     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
687     // check state
688     if(m_State == E_Error) {
689         debugFatal("Resetting from error condition not yet supported...\n");
690         return false;
691     }
692     // if not in an error condition, reset means stop the handlers
693     return stopHandlers();
694 }
695
696 void IsoHandlerManager::setVerboseLevel(int i) {
697     setDebugLevel(i);
698     // propagate the debug level
699     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
700           it != m_IsoHandlers.end();
701           ++it )
702     {
703         (*it)->setVerboseLevel(i);
704     }
705 }
706
707 void IsoHandlerManager::dumpInfo() {
708     int i=0;
709     debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping IsoHandlerManager Stream handler information...\n");
710     debugOutputShort( DEBUG_LEVEL_NORMAL, " State: %d\n",(int)m_State);
711
712     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
713           it != m_IsoHandlers.end();
714           ++it )
715     {
716         debugOutputShort( DEBUG_LEVEL_NORMAL, " IsoHandler %d (%p)\n",i++,*it);
717         (*it)->dumpInfo();
718     }
719 }
720
721 const char *
722 IsoHandlerManager::eHSToString(enum eHandlerStates s) {
723     switch (s) {
724         default: return "Invalid";
725         case E_Created: return "Created";
726         case E_Prepared: return "Prepared";
727         case E_Running: return "Running";
728         case E_Error: return "Error";
729     }
730 }
Note: See TracBrowser for help on using the browser.