root/branches/streaming-rework/src/libstreaming/IsoHandlerManager.cpp

Revision 386, 19.2 kB (checked in by pieterpalmers, 17 years ago)

- moved files around to the place they belong
- fixed all compile warnings

Line 
1 /* $Id$ */
2
3 /*
4  *   FreeBob Streaming API
5  *   FreeBob = Firewire (pro-)audio for linux
6  *
7  *   http://freebob.sf.net
8  *
9  *   Copyright (C) 2006 Pieter Palmers <pieterpalmers@users.sourceforge.net>
10  *
11  *   This program is free software {} you can redistribute it and/or modify
12  *   it under the terms of the GNU General Public License as published by
13  *   the Free Software Foundation {} either version 2 of the License, or
14  *   (at your option) any later version.
15  *
16  *   This program is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY {} without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with this program {} if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  *
26  *
27  */
28
29 #include "IsoHandlerManager.h"
30 #include "IsoHandler.h"
31 #include "IsoStream.h"
32 #include <assert.h>
33
34 #define MINIMUM_INTERRUPTS_PER_PERIOD  4U
35 #define PACKETS_PER_INTERRUPT          4U
36
37 namespace FreebobStreaming
38 {
39
40 IMPL_DEBUG_MODULE( IsoHandlerManager, IsoHandlerManager, DEBUG_LEVEL_NORMAL );
41
42 IsoHandlerManager::IsoHandlerManager() :
43    m_State(E_Created),
44    m_poll_timeout(1), m_poll_fds(0), m_poll_nfds(0)
45 {
46
47 }
48
49
50 IsoHandlerManager::~IsoHandlerManager()
51 {
52
53 }
54
55 bool IsoHandlerManager::Init()
56 {
57         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
58
59         return true;
60 }
61
62 /**
63  * the IsoHandlerManager thread execute function iterates the handlers.
64  *
65  * This means that once the thread is running, streams are
66  * transmitted and received (if present on the bus). Make sure
67  * that the clients are registered & ready before starting the
68  * thread!
69  *
70  * The register and unregister functions are thread unsafe, so
71  * should not be used when the thread is running.
72  *
73  * @return false if the handlers could not be iterated.
74  */
75 bool IsoHandlerManager::Execute()
76 {
77 //     updateCycleTimers();
78    
79     if(!iterate()) {
80         debugFatal("Could not iterate the isoManager\n");
81         return false;
82     }   
83    
84     return true;
85 }
86
87 /**
88  * Poll the handlers managed by this manager, and iterate them
89  * when ready
90  *
91  * @return true when successful
92  */
93 bool IsoHandlerManager::iterate()
94 {
95         int err;
96         int i=0;
97         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "enter...\n");
98        
99         err = poll (m_poll_fds, m_poll_nfds, m_poll_timeout);
100        
101         if (err == -1) {
102                 if (errno == EINTR) {
103                         return true;
104                 }
105                 debugFatal("poll error: %s\n", strerror (errno));
106                 return false;
107         }
108
109         for (i = 0; i < m_poll_nfds; i++) {
110                 if (m_poll_fds[i].revents & POLLERR) {
111                         debugWarning("error on fd for %d\n",i);
112                 }
113
114                 if (m_poll_fds[i].revents & POLLHUP) {
115                         debugWarning("hangup on fd for %d\n",i);
116                 }
117                
118                 if(m_poll_fds[i].revents & (POLLIN)) {
119                         IsoHandler *s=m_IsoHandlers.at(i);
120                         assert(s);
121                        
122                         s->iterate();
123                 }
124         }
125
126         return true;
127
128 }
129
130 // updates the internal cycle timer caches of the handlers
131 void IsoHandlerManager::updateCycleTimers() {
132     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "enter...\n");
133    
134     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
135           it != m_IsoHandlers.end();
136           ++it )
137     {
138         int cnt=0;
139         while (!(*it)->updateCycleTimer() && (cnt++ < MAX_UPDATE_TRIES)) {
140             usleep(USLEEP_AFTER_UPDATE_FAILURE);
141         }
142     }
143    
144 }
145
146 bool IsoHandlerManager::registerHandler(IsoHandler *handler)
147 {
148     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
149     assert(handler);
150    
151     m_IsoHandlers.push_back(handler);
152    
153     handler->setVerboseLevel(getDebugLevel());
154
155     // rebuild the fd map for poll()'ing.
156     return rebuildFdMap();     
157
158 }
159
160 bool IsoHandlerManager::unregisterHandler(IsoHandler *handler)
161 {
162         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
163         assert(handler);
164
165         for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
166           it != m_IsoHandlers.end();
167           ++it )
168         {
169                 if ( *it == handler ) {
170                         // erase the iso handler from the list
171                         m_IsoHandlers.erase(it);
172                         // rebuild the fd map for poll()'ing.
173                         return rebuildFdMap();
174                 }
175         }
176         debugFatal("Could not find handler (%p)\n", handler);
177        
178         return false; //not found
179
180 }
181
182 bool IsoHandlerManager::rebuildFdMap() {
183         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
184         int i=0;
185
186         m_poll_nfds=0;
187         if(m_poll_fds) free(m_poll_fds);
188
189         // count the number of handlers
190         m_poll_nfds=m_IsoHandlers.size();
191
192         // allocate the fd array
193         m_poll_fds   = (struct pollfd *) calloc (m_poll_nfds, sizeof (struct pollfd));
194         if(!m_poll_fds) {
195                 debugFatal("Could not allocate memory for poll FD array\n");
196                 return false;
197         }
198
199         // fill the fd map
200         for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
201           it != m_IsoHandlers.end();
202           ++it )
203         {
204                 m_poll_fds[i].fd=(*it)->getFileDescriptor();
205                 m_poll_fds[i].events = POLLIN;
206                 i++;
207         }
208
209         return true;
210 }
211
212 void IsoHandlerManager::disablePolling(IsoStream *stream) {
213     int i=0;
214    
215     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Disable polling on stream %p\n",stream);
216
217     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
218         it != m_IsoHandlers.end();
219         ++it )
220     {
221         if ((*it)->isStreamRegistered(stream)) {
222             m_poll_fds[i].events = 0;
223             m_poll_fds[i].revents = 0;
224             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "polling disabled\n");
225         }
226        
227         i++;
228     }
229 }
230
231 void IsoHandlerManager::enablePolling(IsoStream *stream) {
232     int i=0;
233    
234     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Enable polling on stream %p\n",stream);
235    
236     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
237         it != m_IsoHandlers.end();
238         ++it )
239     {
240         if ((*it)->isStreamRegistered(stream)) {
241             m_poll_fds[i].events = POLLIN;
242             m_poll_fds[i].revents = 0;
243             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "polling enabled\n");
244         }
245        
246         i++;
247     }
248 }
249
250
251 /**
252  * Registers an IsoStream with the IsoHandlerManager.
253  *
254  * If nescessary, an IsoHandler is created to handle this stream.
255  * Once an IsoStream is registered to the handler, it will be included
256  * in the ISO streaming cycle (i.e. receive/transmit of it will occur).
257  *
258  * @param stream the stream to register
259  * @return true if registration succeeds
260  *
261  * \todo : currently there is a one-to-one mapping
262  *        between streams and handlers, this is not ok for
263  *        multichannel receive
264  */
265 bool IsoHandlerManager::registerStream(IsoStream *stream)
266 {
267         debugOutput( DEBUG_LEVEL_VERBOSE, "Registering stream %p\n",stream);
268         assert(stream);
269
270         // make sure the stream isn't already attached to a handler
271         for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
272           it != m_IsoHandlers.end();
273           ++it )
274         {
275                 if((*it)->isStreamRegistered(stream)) {
276                         debugWarning( "stream already registered!\n");
277                         (*it)->unregisterStream(stream);
278                        
279                 }
280         }
281        
282         // clean up all handlers that aren't used
283         pruneHandlers();
284
285         // allocate a handler for this stream
286         if (stream->getType()==IsoStream::EST_Receive) {
287                 // setup the optimal parameters for the raw1394 ISO buffering
288                 unsigned int packets_per_period=stream->getPacketsPerPeriod();
289                
290 #if 0
291                 // hardware interrupts occur when one DMA block is full, and the size of one DMA
292                 // block = PAGE_SIZE. Setting the max_packet_size makes sure that the HW irq is
293                 // occurs at a period boundary (optimal CPU use)
294                
295                 // NOTE: try and use MINIMUM_INTERRUPTS_PER_PERIOD hardware interrupts
296                 //       per period for better latency.
297                 unsigned int max_packet_size=MINIMUM_INTERRUPTS_PER_PERIOD * getpagesize() / packets_per_period;
298                 if (max_packet_size < stream->getMaxPacketSize()) {
299                         max_packet_size=stream->getMaxPacketSize();
300                 }
301
302                 // Ensure we don't request a packet size bigger than the
303                 // kernel-enforced maximum which is currently 1 page.
304                 if (max_packet_size > (unsigned int)getpagesize())
305                         max_packet_size = getpagesize();
306
307                 unsigned int irq_interval=packets_per_period / MINIMUM_INTERRUPTS_PER_PERIOD;
308                 if(irq_interval <= 0) irq_interval=1;
309 #else
310                 // hardware interrupts occur when one DMA block is full, and the size of one DMA
311                 // block = PAGE_SIZE. Setting the max_packet_size enables control over the IRQ
312                 // frequency, as the controller uses max_packet_size, and not the effective size
313                 // when writing to the DMA buffer.
314                
315                 // configure it such that we have an irq for every PACKETS_PER_INTERRUPT packets
316                 unsigned int irq_interval=PACKETS_PER_INTERRUPT;
317                
318                 // unless the period size doesn't allow this
319                 if ((packets_per_period/MINIMUM_INTERRUPTS_PER_PERIOD) < irq_interval) {
320                         irq_interval=1;
321                 }
322                
323                 // FIXME: test
324                 irq_interval=1;
325                
326                 unsigned int max_packet_size=getpagesize() / irq_interval;
327
328                 if (max_packet_size < stream->getMaxPacketSize()) {
329                         max_packet_size=stream->getMaxPacketSize();
330                 }
331
332                 // Ensure we don't request a packet size bigger than the
333                 // kernel-enforced maximum which is currently 1 page.
334                 if (max_packet_size > (unsigned int)getpagesize())
335                         max_packet_size = getpagesize();
336
337 #endif
338                 /* the receive buffer size doesn't matter for the latency,
339                    but it has a minimal value in order for libraw to operate correctly (300) */
340                 int buffers=400;
341                
342                 // create the actual handler
343                 IsoRecvHandler *h = new IsoRecvHandler(stream->getPort(), buffers,
344                                                        max_packet_size, irq_interval);
345
346                 debugOutput( DEBUG_LEVEL_VERBOSE, " registering IsoRecvHandler\n");
347
348                 if(!h) {
349                         debugFatal("Could not create IsoRecvHandler\n");
350                         return false;
351                 }
352
353                 h->setVerboseLevel(getDebugLevel());
354
355                 // init the handler
356                 if(!h->init()) {
357                         debugFatal("Could not initialize receive handler\n");
358                         return false;
359                 }
360
361                 // register the stream with the handler
362                 if(!h->registerStream(stream)) {
363                         debugFatal("Could not register receive stream with handler\n");
364                         return false;
365                 }
366
367                 // register the handler with the manager
368                 if(!registerHandler(h)) {
369                         debugFatal("Could not register receive handler with manager\n");
370                         return false;
371                 }
372                 debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n",stream,h);
373         }
374        
375         if (stream->getType()==IsoStream::EST_Transmit) {
376                 // setup the optimal parameters for the raw1394 ISO buffering
377                 unsigned int packets_per_period=stream->getPacketsPerPeriod();
378
379 #if 0
380                 // hardware interrupts occur when one DMA block is full, and the size of one DMA
381                 // block = PAGE_SIZE. Setting the max_packet_size makes sure that the HW irq 
382                 // occurs at a period boundary (optimal CPU use)
383                 // NOTE: try and use MINIMUM_INTERRUPTS_PER_PERIOD interrupts per period
384                 //       for better latency.
385                 unsigned int max_packet_size=MINIMUM_INTERRUPTS_PER_PERIOD * getpagesize() / packets_per_period;
386                 if (max_packet_size < stream->getMaxPacketSize()) {
387                         max_packet_size=stream->getMaxPacketSize();
388                 }
389
390                 // Ensure we don't request a packet size bigger than the
391                 // kernel-enforced maximum which is currently 1 page.
392                 if (max_packet_size > (unsigned int)getpagesize())
393                         max_packet_size = getpagesize();
394
395                 unsigned int irq_interval=packets_per_period / MINIMUM_INTERRUPTS_PER_PERIOD;
396                 if(irq_interval <= 0) irq_interval=1;
397 #else
398                 // hardware interrupts occur when one DMA block is full, and the size of one DMA
399                 // block = PAGE_SIZE. Setting the max_packet_size enables control over the IRQ
400                 // frequency, as the controller uses max_packet_size, and not the effective size
401                 // when writing to the DMA buffer.
402                
403                 // configure it such that we have an irq for every PACKETS_PER_INTERRUPT packets
404                 unsigned int irq_interval=PACKETS_PER_INTERRUPT;
405                
406                 // unless the period size doesn't allow this
407                 if ((packets_per_period/MINIMUM_INTERRUPTS_PER_PERIOD) < irq_interval) {
408                         irq_interval=1;
409                 }
410                
411                 // FIXME: test
412                 irq_interval=1;
413
414                 unsigned int max_packet_size=getpagesize() / irq_interval;
415
416                 if (max_packet_size < stream->getMaxPacketSize()) {
417                         max_packet_size=stream->getMaxPacketSize();
418                 }
419
420                 // Ensure we don't request a packet size bigger than the
421                 // kernel-enforced maximum which is currently 1 page.
422                 if (max_packet_size > (unsigned int)getpagesize())
423                         max_packet_size = getpagesize();
424 #endif
425                 // the transmit buffer size should be as low as possible for latency.
426                 // note however that the raw1394 subsystem tries to keep this buffer
427                 // full, so we have to make sure that we have enough events in our
428                 // event buffers
429                
430                 // every irq_interval packets an interrupt will occur. that is when
431                 // buffers get transfered, meaning that we should have at least some
432                 // margin here
433 //              int buffers=irq_interval * 2;
434
435                 // half a period. the xmit handler will take care of this
436                 int buffers=packets_per_period/2;
437                
438                 // NOTE: this is dangerous: what if there is not enough prefill?
439 //              if (buffers<10) buffers=10;     
440                
441                 // create the actual handler
442                 IsoXmitHandler *h = new IsoXmitHandler(stream->getPort(), buffers,
443                                                        max_packet_size, irq_interval);
444
445                 debugOutput( DEBUG_LEVEL_VERBOSE, " registering IsoXmitHandler\n");
446
447                 if(!h) {
448                         debugFatal("Could not create IsoXmitHandler\n");
449                         return false;
450                 }
451
452                 h->setVerboseLevel(getDebugLevel());
453
454                 // init the handler
455                 if(!h->init()) {
456                         debugFatal("Could not initialize transmit handler\n");
457                         return false;
458                 }
459
460                 // register the stream with the handler
461                 if(!h->registerStream(stream)) {
462                         debugFatal("Could not register transmit stream with handler\n");
463                         return false;
464                 }
465
466                 // register the handler with the manager
467                 if(!registerHandler(h)) {
468                         debugFatal("Could not register transmit handler with manager\n");
469                         return false;
470                 }
471                 debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n",stream,h);
472         }
473
474         m_IsoStreams.push_back(stream);
475         debugOutput( DEBUG_LEVEL_VERBOSE, " %d streams, %d handlers registered\n",
476                                           m_IsoStreams.size(), m_IsoHandlers.size());
477
478         return true;
479 }
480
481 bool IsoHandlerManager::unregisterStream(IsoStream *stream)
482 {
483         debugOutput( DEBUG_LEVEL_VERBOSE, "Unregistering stream %p\n",stream);
484         assert(stream);
485
486         // make sure the stream isn't attached to a handler anymore
487         for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
488           it != m_IsoHandlers.end();
489           ++it )
490         {
491                 if((*it)->isStreamRegistered(stream)) {
492                         if(!(*it)->unregisterStream(stream)) {
493                                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not unregister stream (%p) from handler (%p)...\n",stream,*it);
494                                 return false;
495                         }
496                        
497                         debugOutput( DEBUG_LEVEL_VERBOSE, " unregistered stream (%p) from handler (%p)...\n",stream,*it);
498                 }
499         }
500
501         // clean up all handlers that aren't used
502         pruneHandlers();
503
504         // remove the stream from the registered streams list
505         for ( IsoStreamVectorIterator it = m_IsoStreams.begin();
506           it != m_IsoStreams.end();
507           ++it )
508         {
509                 if ( *it == stream ) {
510                         m_IsoStreams.erase(it);
511                        
512                         debugOutput( DEBUG_LEVEL_VERBOSE, " deleted stream (%p) from list...\n", *it);
513                         return true;
514                 }
515         }
516
517         return false; //not found
518
519 }
520
521 void IsoHandlerManager::pruneHandlers() {
522     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
523     IsoHandlerVector toUnregister;
524
525     // find all handlers that are not in use
526     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
527           it != m_IsoHandlers.end();
528           ++it )
529     {
530         if(!((*it)->inUse())) {
531             debugOutput( DEBUG_LEVEL_VERBOSE, " handler (%p) not in use\n",*it);
532             toUnregister.push_back(*it);
533         }
534     }
535     // delete them
536     for ( IsoHandlerVectorIterator it = toUnregister.begin();
537           it != toUnregister.end();
538           ++it )
539     {
540         unregisterHandler(*it);
541         debugOutput( DEBUG_LEVEL_VERBOSE, " deleting handler (%p)\n",*it);
542
543         // Now the handler's been unregistered it won't be reused
544         // again.  Therefore it really needs to be formally deleted
545         // to free up the raw1394 handle.  Otherwise things fall
546         // apart after several xrun recoveries as the system runs
547         // out of resources to support all the disused but still
548         // allocated raw1394 handles.  At least this is the current
549         // theory as to why we end up with "memory allocation"
550         // failures after several Xrun recoveries.
551         delete *it;
552     }
553
554 }
555
556
557 bool IsoHandlerManager::prepare()
558 {
559     bool retval=true;
560    
561     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
562    
563     // check state
564     if(m_State != E_Created) {
565         debugError("Incorrect state, expected E_Created, got %d\n",(int)m_State);
566         return false;
567     }
568    
569     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
570           it != m_IsoHandlers.end();
571           ++it )
572     {
573         if(!(*it)->prepare()) {
574             debugFatal("Could not prepare handlers\n");
575             retval=false;
576         }
577     }
578
579     if (retval) {
580         m_State=E_Prepared;
581     } else {
582         m_State=E_Error;
583     }
584
585     return retval;
586 }
587
588 bool IsoHandlerManager::startHandlers() {
589     return startHandlers(-1);
590 }
591
592 bool IsoHandlerManager::startHandlers(int cycle) {
593     bool retval=true;
594    
595     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
596    
597     // check state
598     if(m_State != E_Prepared) {
599         debugError("Incorrect state, expected E_Prepared, got %d\n",(int)m_State);
600         return false;
601     }
602    
603     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
604         it != m_IsoHandlers.end();
605         ++it )
606     {
607         debugOutput( DEBUG_LEVEL_VERBOSE, " starting handler (%p)\n",*it);
608         if(!(*it)->start(cycle)) {
609             debugOutput( DEBUG_LEVEL_VERBOSE, " could not start handler (%p)\n",*it);
610             retval=false;
611         }
612     }
613    
614     if (retval) {
615         m_State=E_Running;
616     } else {
617         m_State=E_Error;
618     }
619
620     return retval;
621 }
622
623 bool IsoHandlerManager::stopHandlers() {
624     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
625    
626     // check state
627     if(m_State != E_Running) {
628         debugError("Incorrect state, expected E_Running, got %d\n",(int)m_State);
629         return false;
630     }
631    
632     bool retval=true;
633    
634     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
635         it != m_IsoHandlers.end();
636         ++it )
637     {
638         debugOutput( DEBUG_LEVEL_VERBOSE, " stopping handler (%p)\n",*it);
639         if(!(*it)->stop()){
640             debugOutput( DEBUG_LEVEL_VERBOSE, " could not stop handler (%p)\n",*it);
641             retval=false;
642         }
643     }
644    
645     if (retval) {
646         m_State=E_Prepared;
647     } else {
648         m_State=E_Error;
649     }
650    
651     return retval;
652 }
653
654 bool IsoHandlerManager::reset() {
655     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
656    
657     // check state
658     if(m_State == E_Error) {
659         debugFatal("Resetting from error condition not yet supported...\n");
660         return false;
661     }
662    
663     // if not in an error condition, reset means stop the handlers
664     return stopHandlers();
665 }
666
667
668 void IsoHandlerManager::setVerboseLevel(int i) {
669     setDebugLevel(i);
670
671     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
672           it != m_IsoHandlers.end();
673           ++it )
674     {
675         (*it)->setVerboseLevel(i);
676     }
677 }
678
679 void IsoHandlerManager::dumpInfo() {
680     int i=0;
681    
682     debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping IsoHandlerManager Stream handler information...\n");
683     debugOutputShort( DEBUG_LEVEL_NORMAL, " State: %d\n",(int)m_State);
684
685     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
686           it != m_IsoHandlers.end();
687           ++it )
688     {
689         debugOutputShort( DEBUG_LEVEL_NORMAL, " IsoHandler %d (%p)\n",i++,*it);
690
691         (*it)->dumpInfo();
692     }
693
694 }
695
696 } // end of namespace FreebobStreaming
697
Note: See TracBrowser for help on using the browser.