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

Revision 1336, 38.2 kB (checked in by ppalmers, 12 years ago)

Bring trunk up to date with branches/libffado-2.0:

"""
svn merge -r 1254:1299 svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0
svn merge -r 1301:1320 svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0
svn merge -r 1322:1323 svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0
svn merge -r 1329:HEAD svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0
"""

Add getSupportedSamplingFrequencies() to DICE, RME and Metric Halo AvDevices?

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
26 #include "IsoHandlerManager.h"
27 #include "ieee1394service.h"
28 #include "cycletimer.h"
29 #include "libstreaming/generic/StreamProcessor.h"
30
31 #include "libutil/Atomic.h"
32 #include "libutil/PosixThread.h"
33 #include "libutil/SystemTimeSource.h"
34 #include "libutil/Watchdog.h"
35
36 #include <cstring>
37 #include <assert.h>
38
39 IMPL_DEBUG_MODULE( IsoHandlerManager, IsoHandlerManager, DEBUG_LEVEL_NORMAL );
40 IMPL_DEBUG_MODULE( IsoTask, IsoTask, DEBUG_LEVEL_NORMAL );
41
42 using namespace Streaming;
43
44 // --- ISO Thread --- //
45
46 IsoTask::IsoTask(IsoHandlerManager& manager, enum IsoHandler::EHandlerType t)
47     : m_manager( manager )
48     , m_SyncIsoHandler ( NULL )
49     , m_handlerType( t )
50     , m_running( false )
51     , m_in_busreset( false )
52 {
53 }
54
55 IsoTask::~IsoTask()
56 {
57     sem_destroy(&m_activity_semaphore);
58 }
59
60 bool
61 IsoTask::Init()
62 {
63     request_update = 0;
64
65     int i;
66     for (i=0; i < ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT; i++) {
67         m_IsoHandler_map_shadow[i] = NULL;
68         m_poll_fds_shadow[i].events = 0;
69     }
70     m_poll_nfds_shadow = 0;
71
72     #ifdef DEBUG
73     m_last_loop_entry = 0;
74     m_successive_short_loops = 0;
75     #endif
76
77     sem_init(&m_activity_semaphore, 0, 0);
78     m_running = true;
79     return true;
80 }
81
82 bool
83 IsoTask::requestShadowMapUpdate()
84 {
85     debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) enter\n", this);
86     INC_ATOMIC(&request_update);
87
88     // get the thread going again
89     signalActivity();
90
91     if (m_running) {
92         int timeout = 1000;
93         while(request_update && timeout--) {
94             Util::SystemTimeSource::SleepUsecRelative(1000);
95         }
96         if(timeout == 0) {
97             debugError("timeout waiting for shadow map update\n");
98         }
99     }
100     debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) exit\n", this);
101     return true;
102 }
103
104 bool
105 IsoTask::handleBusReset()
106 {
107     bool retval = true;
108     m_in_busreset = true;
109     requestShadowMapUpdate();
110     if(request_update) {
111         debugError("shadow map update request not honored\n");
112         return false;
113     }
114
115     unsigned int i, max;
116     max = m_manager.m_IsoHandlers.size();
117     for (i = 0; i < max; i++) {
118         IsoHandler *h = m_manager.m_IsoHandlers.at(i);
119         assert(h);
120
121         // skip the handlers not intended for us
122         if(h->getType() != m_handlerType) continue;
123
124         if (!h->handleBusReset()) {
125             debugWarning("Failed to handle busreset on %p\n");
126             retval = false;
127         }
128     }
129
130     // re-enable processing
131     m_in_busreset = false;
132     requestShadowMapUpdate();
133     if(request_update) {
134         debugError("shadow map update request not honored\n");
135         return false;
136     }
137     return retval;
138 }
139
140 // updates the internal stream map
141 // note that this should be executed with the guarantee that
142 // nobody will modify the parent data structures
143 void
144 IsoTask::updateShadowMapHelper()
145 {
146     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) updating shadow vars...\n", this);
147     // we are handling a busreset
148     if(m_in_busreset) {
149         m_poll_nfds_shadow = 0;
150         return;
151     }
152     unsigned int i, cnt, max;
153     max = m_manager.m_IsoHandlers.size();
154     m_SyncIsoHandler = NULL;
155     for (i = 0, cnt = 0; i < max; i++) {
156         IsoHandler *h = m_manager.m_IsoHandlers.at(i);
157         assert(h);
158
159         // skip the handlers not intended for us
160         if(h->getType() != m_handlerType) continue;
161
162         if (h->isEnabled()) {
163             m_IsoHandler_map_shadow[cnt] = h;
164             m_poll_fds_shadow[cnt].fd = h->getFileDescriptor();
165             m_poll_fds_shadow[cnt].revents = 0;
166             m_poll_fds_shadow[cnt].events = POLLIN;
167             cnt++;
168             // FIXME: need a more generic approach here
169             if(   m_SyncIsoHandler == NULL
170                && h->getType() == IsoHandler::eHT_Transmit) {
171                 m_SyncIsoHandler = h;
172             }
173
174             debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) %s handler %p added\n",
175                                               this, h->getTypeString(), h);
176         } else {
177             debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) %s handler %p skipped (disabled)\n",
178                                               this, h->getTypeString(), h);
179         }
180         if(cnt > ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT) {
181             debugWarning("Too much ISO Handlers in thread...\n");
182             break;
183         }
184     }
185
186     // FIXME: need a more generic approach here
187     // if there are no active transmit handlers,
188     // use the first receive handler
189     if(   m_SyncIsoHandler == NULL
190        && m_poll_nfds_shadow) {
191         m_SyncIsoHandler = m_IsoHandler_map_shadow[0];
192     }
193     m_poll_nfds_shadow = cnt;
194     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) updated shadow vars...\n", this);
195 }
196
197 bool
198 IsoTask::Execute()
199 {
200     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,
201                 "(%p, %s) Execute\n",
202                 this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
203     int err;
204     unsigned int i;
205     unsigned int m_poll_timeout = 10;
206
207     #ifdef DEBUG
208     uint64_t now = Util::SystemTimeSource::getCurrentTimeAsUsecs();
209     int diff = now - m_last_loop_entry;
210     if(diff < 100) {
211         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,
212                            "(%p, %s) short loop detected (%d usec), cnt: %d\n",
213                            this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"),
214                            diff, m_successive_short_loops);
215         m_successive_short_loops++;
216         if(m_successive_short_loops > 10000) {
217             debugError("Shutting down runaway thread\n");
218             m_running = false;
219             return false;
220         }
221     } else {
222         // reset the counter
223         m_successive_short_loops = 0;
224     }
225     m_last_loop_entry = now;
226     #endif
227
228     // if some other thread requested a shadow map update, do it
229     if(request_update) {
230         updateShadowMapHelper();
231         DEC_ATOMIC(&request_update); // ack the update
232         assert(request_update >= 0);
233     }
234
235     // bypass if no handlers are registered
236     if (m_poll_nfds_shadow == 0) {
237         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,
238                            "(%p, %s) bypass iterate since no handlers to poll\n",
239                            this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
240         usleep(m_poll_timeout * 1000);
241         return true;
242     }
243
244     // FIXME: what can happen is that poll() returns, but not all clients are
245     // ready. there might be some busy waiting behavior that still has to be solved.
246
247     // setup the poll here
248     // we should prevent a poll() where no events are specified, since that will only time-out
249     bool no_one_to_poll = true;
250     while(no_one_to_poll) {
251         for (i = 0; i < m_poll_nfds_shadow; i++) {
252             short events = 0;
253             IsoHandler *h = m_IsoHandler_map_shadow[i];
254             // we should only poll on a transmit handler
255             // that has a client that is ready to send
256             // something. Otherwise it will end up in
257             // busy wait looping since the packet function
258             // will defer processing (also avoids the
259             // AGAIN problem)
260             if (h->canIterateClient()) {
261                 events = POLLIN | POLLPRI;
262                 no_one_to_poll = false;
263                 // if we are going to poll() it, let's ensure
264                 // it can run until someone wants it to exit
265                 h->allowIterateLoop();
266             }
267             m_poll_fds_shadow[i].events = events;
268         }
269
270         if(no_one_to_poll) {
271             debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,
272                         "(%p, %s) No one to poll, waiting for something to happen\n",
273                         this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
274             // wait for something to happen
275             switch(waitForActivity()) {
276                 case IsoTask::eAR_Error:
277                     debugError("Error while waiting for activity\n");
278                     return false;
279                 case IsoTask::eAR_Interrupted:
280                     // FIXME: what to do here?
281                     debugWarning("Interrupted while waiting for activity\n");
282                     break;
283                 case IsoTask::eAR_Timeout:
284                     // FIXME: what to do here?
285                     debugWarning("Timeout while waiting for activity\n");
286                     no_one_to_poll = false; // exit the loop to be able to detect failing handlers
287                     break;
288                 case IsoTask::eAR_Activity:
289                     // do nothing
290                     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
291                                        "(%p, %s) something happened\n",
292                                        this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
293                     break;
294             }
295         }
296     }
297
298     // Use a shadow map of the fd's such that we don't have to update
299     // the fd map everytime we run poll().
300     err = poll (m_poll_fds_shadow, m_poll_nfds_shadow, m_poll_timeout);
301     uint32_t ctr_at_poll_return = m_manager.get1394Service().getCycleTimer();
302
303     if (err < 0) {
304         if (errno == EINTR) {
305             debugOutput(DEBUG_LEVEL_VERBOSE, "Ignoring poll return due to signal\n");
306             return true;
307         }
308         debugFatal("poll error: %s\n", strerror (errno));
309         m_running = false;
310         return false;
311     }
312
313     // find handlers that have died
314     uint64_t ctr_at_poll_return_ticks = CYCLE_TIMER_TO_TICKS(ctr_at_poll_return);
315     bool handler_died = false;
316     for (i = 0; i < m_poll_nfds_shadow; i++) {
317         // figure out if a handler has died
318
319         // this is the time of the last packet we saw in the iterate() handler
320         uint32_t last_packet_seen = m_IsoHandler_map_shadow[i]->getLastPacketTime();
321         if (last_packet_seen == 0xFFFFFFFF) {
322             // this was not iterated yet, so can't be dead
323             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
324                         "(%p, %s) handler %d didn't see any packets yet\n",
325                         this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"), i);
326             continue;
327         }
328
329         uint64_t last_packet_seen_ticks = CYCLE_TIMER_TO_TICKS(last_packet_seen);
330         // we use a relatively large value to distinguish between "death" and xrun
331         int64_t max_diff_ticks = TICKS_PER_SECOND * 2;
332         int64_t measured_diff_ticks = diffTicks(ctr_at_poll_return_ticks, last_packet_seen_ticks);
333
334         debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
335                            "(%p, %s) check handler %d: diff = %lld, max = %lld, now: %08lX, last: %08lX\n",
336                            this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"),
337                            i, measured_diff_ticks, max_diff_ticks, ctr_at_poll_return, last_packet_seen);
338         if(measured_diff_ticks > max_diff_ticks) {
339             debugFatal("(%p, %s) Handler died: now: %08lX, last: %08lX, diff: %lld (max: %lld)\n",
340                        this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"),
341                        ctr_at_poll_return, last_packet_seen, measured_diff_ticks, max_diff_ticks);
342             m_IsoHandler_map_shadow[i]->notifyOfDeath();
343             handler_died = true;
344         }
345     }
346     if(handler_died) {
347         m_running = false;
348         return false; // one or more handlers have died
349     }
350
351     // iterate the handlers
352     for (i = 0; i < m_poll_nfds_shadow; i++) {
353         #ifdef DEBUG
354         if(m_poll_fds_shadow[i].revents) {
355             debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,
356                         "(%p, %s) received events: %08X for (%d/%d, %p, %s)\n",
357                         this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"),
358                         m_poll_fds_shadow[i].revents,
359                         i, m_poll_nfds_shadow,
360                         m_IsoHandler_map_shadow[i],
361                         m_IsoHandler_map_shadow[i]->getTypeString());
362         }
363         #endif
364
365         // if we get here, it means two things:
366         // 1) the kernel can accept or provide packets (poll returned POLLIN)
367         // 2) the client can provide or accept packets (since we enabled polling)
368         if(m_poll_fds_shadow[i].revents & (POLLIN)) {
369             m_IsoHandler_map_shadow[i]->iterate(ctr_at_poll_return);
370         } else {
371             // there might be some error condition
372             if (m_poll_fds_shadow[i].revents & POLLERR) {
373                 debugWarning("(%p) error on fd for %d\n", this, i);
374             }
375             if (m_poll_fds_shadow[i].revents & POLLHUP) {
376                 debugWarning("(%p) hangup on fd for %d\n", this, i);
377             }
378         }
379     }
380     return true;
381 }
382
383 enum IsoTask::eActivityResult
384 IsoTask::waitForActivity()
385 {
386     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
387                        "(%p, %s) waiting for activity\n",
388                        this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
389     struct timespec ts;
390     int result;
391     long long int timeout_nsec = ISOHANDLERMANAGER_ISO_TASK_WAIT_TIMEOUT_USECS * 1000LL;
392
393     if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
394         debugError("clock_gettime failed\n");
395         return eAR_Error;
396     }
397
398     ts.tv_nsec += timeout_nsec;
399     while(ts.tv_nsec >= 1000000000LL) {
400         ts.tv_sec += 1;
401         ts.tv_nsec -= 1000000000LL;
402     }
403
404     result = sem_timedwait(&m_activity_semaphore, &ts);
405
406     if(result != 0) {
407         if (errno == ETIMEDOUT) {
408             debugOutput(DEBUG_LEVEL_VERBOSE,
409                         "(%p) sem_timedwait() timed out (result=%d)\n",
410                         this, result);
411             return eAR_Timeout;
412         } else if (errno == EINTR) {
413             debugOutput(DEBUG_LEVEL_VERBOSE,
414                         "(%p) sem_timedwait() interrupted by signal (result=%d)\n",
415                         this, result);
416             return eAR_Interrupted;
417         } else if (errno == EINVAL) {
418             debugError("(%p) sem_timedwait error (result=%d errno=EINVAL)\n",
419                         this, result);
420             debugError("(%p) timeout_nsec=%lld ts.sec=%d ts.nsec=%lld\n",
421                        this, timeout_nsec, ts.tv_sec, ts.tv_nsec);
422             return eAR_Error;
423         } else {
424             debugError("(%p) sem_timedwait error (result=%d errno=%d)\n",
425                         this, result, errno);
426             debugError("(%p) timeout_nsec=%lld ts.sec=%d ts.nsec=%lld\n",
427                        this, timeout_nsec, ts.tv_sec, ts.tv_nsec);
428             return eAR_Error;
429         }
430     }
431
432     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,
433                 "(%p, %s) got activity\n",
434                 this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
435     return eAR_Activity;
436 }
437
438 void
439 IsoTask::signalActivity()
440 {
441     // signal the activity cond var
442     sem_post(&m_activity_semaphore);
443     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE,
444                 "(%p, %s) activity\n",
445                 this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
446 }
447
448 void IsoTask::setVerboseLevel(int i) {
449     setDebugLevel(i);
450     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", i );
451 }
452
453 // -- the ISO handler manager -- //
454 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service)
455    : m_State(E_Created)
456    , m_service( service )
457    , m_realtime(false), m_priority(0)
458    , m_IsoThreadTransmit ( NULL )
459    , m_IsoTaskTransmit ( NULL )
460    , m_IsoThreadReceive ( NULL )
461    , m_IsoTaskReceive ( NULL )
462 {
463 }
464
465 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service, bool run_rt, int rt_prio)
466    : m_State(E_Created)
467    , m_service( service )
468    , m_realtime(run_rt), m_priority(rt_prio)
469    , m_IsoThreadTransmit ( NULL )
470    , m_IsoTaskTransmit ( NULL )
471    , m_IsoThreadReceive ( NULL )
472    , m_IsoTaskReceive ( NULL )
473 {
474 }
475
476 IsoHandlerManager::~IsoHandlerManager()
477 {
478     stopHandlers();
479     pruneHandlers();
480     if(m_IsoHandlers.size() > 0) {
481         debugError("Still some handlers in use\n");
482     }
483     if (m_IsoThreadTransmit) {
484         m_IsoThreadTransmit->Stop();
485         delete m_IsoThreadTransmit;
486     }
487     if (m_IsoThreadReceive) {
488         m_IsoThreadReceive->Stop();
489         delete m_IsoThreadReceive;
490     }
491     if (m_IsoTaskTransmit) {
492         delete m_IsoTaskTransmit;
493     }
494     if (m_IsoTaskReceive) {
495         delete m_IsoTaskReceive;
496     }
497 }
498
499 bool
500 IsoHandlerManager::handleBusReset()
501 {
502     debugOutput( DEBUG_LEVEL_NORMAL, "bus reset...\n");
503     // A few things can happen on bus reset:
504     // 1) no devices added/removed => streams are still valid, but might have to be restarted
505     // 2) a device was removed => some streams become invalid
506     // 3) a device was added => same as 1, new device is ignored
507     if (!m_IsoTaskTransmit) {
508         debugError("No xmit task\n");
509         return false;
510     }
511     if (!m_IsoTaskReceive) {
512         debugError("No receive task\n");
513         return false;
514     }
515     if (!m_IsoTaskTransmit->handleBusReset()) {
516         debugWarning("could no handle busreset on xmit\n");
517     }
518     if (!m_IsoTaskReceive->handleBusReset()) {
519         debugWarning("could no handle busreset on recv\n");
520     }
521     return true;
522 }
523
524 void
525 IsoHandlerManager::requestShadowMapUpdate()
526 {
527     if(m_IsoTaskTransmit) m_IsoTaskTransmit->requestShadowMapUpdate();
528     if(m_IsoTaskReceive) m_IsoTaskReceive->requestShadowMapUpdate();
529 }
530
531 bool
532 IsoHandlerManager::setThreadParameters(bool rt, int priority) {
533     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) switch to: (rt=%d, prio=%d)...\n", this, rt, priority);
534     if (priority > THREAD_MAX_RTPRIO) priority = THREAD_MAX_RTPRIO; // cap the priority
535     m_realtime = rt;
536     m_priority = priority;
537
538     if (m_IsoThreadTransmit) {
539         if (m_realtime) {
540             m_IsoThreadTransmit->AcquireRealTime(m_priority
541                                                  + ISOHANDLERMANAGER_ISO_PRIO_INCREASE
542                                                  + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT);
543         } else {
544             m_IsoThreadTransmit->DropRealTime();
545         }
546     }
547     if (m_IsoThreadReceive) {
548         if (m_realtime) {
549             m_IsoThreadReceive->AcquireRealTime(m_priority
550                                                 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE
551                                                 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV);
552         } else {
553             m_IsoThreadReceive->DropRealTime();
554         }
555     }
556
557     return true;
558 }
559
560 bool IsoHandlerManager::init()
561 {
562     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing ISO manager %p...\n", this);
563     // check state
564     if(m_State != E_Created) {
565         debugError("Manager already initialized...\n");
566         return false;
567     }
568
569     // create threads to iterate our ISO handlers
570     debugOutput( DEBUG_LEVEL_VERBOSE, "Create iso thread for %p transmit...\n", this);
571     m_IsoTaskTransmit = new IsoTask( *this, IsoHandler::eHT_Transmit );
572     if(!m_IsoTaskTransmit) {
573         debugFatal("No task\n");
574         return false;
575     }
576     m_IsoTaskTransmit->setVerboseLevel(getDebugLevel());
577     m_IsoThreadTransmit = new Util::PosixThread(m_IsoTaskTransmit, "ISOXMT", m_realtime,
578                                                 m_priority + ISOHANDLERMANAGER_ISO_PRIO_INCREASE
579                                                 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT,
580                                                 PTHREAD_CANCEL_DEFERRED);
581
582     if(!m_IsoThreadTransmit) {
583         debugFatal("No thread\n");
584         return false;
585     }
586     m_IsoThreadTransmit->setVerboseLevel(getDebugLevel());
587
588     debugOutput( DEBUG_LEVEL_VERBOSE, "Create iso thread for %p receive...\n", this);
589     m_IsoTaskReceive = new IsoTask( *this, IsoHandler::eHT_Receive );
590     if(!m_IsoTaskReceive) {
591         debugFatal("No task\n");
592         return false;
593     }
594     m_IsoTaskReceive->setVerboseLevel(getDebugLevel());
595     m_IsoThreadReceive = new Util::PosixThread(m_IsoTaskReceive, "ISORCV", m_realtime,
596                                                m_priority + ISOHANDLERMANAGER_ISO_PRIO_INCREASE
597                                                + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV,
598                                                PTHREAD_CANCEL_DEFERRED);
599
600     if(!m_IsoThreadReceive) {
601         debugFatal("No thread\n");
602         return false;
603     }
604     m_IsoThreadReceive->setVerboseLevel(getDebugLevel());
605     // register the thread with the RT watchdog
606     Util::Watchdog *watchdog = m_service.getWatchdog();
607     if(watchdog) {
608         if(!watchdog->registerThread(m_IsoThreadTransmit)) {
609             debugWarning("could not register iso transmit thread with watchdog\n");
610         }
611         if(!watchdog->registerThread(m_IsoThreadReceive)) {
612             debugWarning("could not register iso receive thread with watchdog\n");
613         }
614     } else {
615         debugWarning("could not find valid watchdog\n");
616     }
617
618     if (m_IsoThreadTransmit->Start() != 0) {
619         debugFatal("Could not start ISO Transmit thread\n");
620         return false;
621     }
622     if (m_IsoThreadReceive->Start() != 0) {
623         debugFatal("Could not start ISO Receive thread\n");
624         return false;
625     }
626
627     m_State=E_Running;
628     return true;
629 }
630
631 bool
632 IsoHandlerManager::disable(IsoHandler *h) {
633     bool result;
634     int i=0;
635     debugOutput(DEBUG_LEVEL_VERBOSE, "Disable on IsoHandler %p\n", h);
636     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
637         it != m_IsoHandlers.end();
638         ++it )
639     {
640         if ((*it) == h) {
641             result = h->disable();
642             if(h->getType() == IsoHandler::eHT_Transmit) {
643                 result &= m_IsoTaskTransmit->requestShadowMapUpdate();
644             } else {
645                 result &= m_IsoTaskReceive->requestShadowMapUpdate();
646             }
647             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " disabled\n");
648             return result;
649         }
650         i++;
651     }
652     debugError("Handler not found\n");
653     return false;
654 }
655
656 bool
657 IsoHandlerManager::enable(IsoHandler *h) {
658     bool result;
659     int i=0;
660     debugOutput(DEBUG_LEVEL_VERBOSE, "Enable on IsoHandler %p\n", h);
661     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
662         it != m_IsoHandlers.end();
663         ++it )
664     {
665         if ((*it) == h) {
666             result = h->enable();
667             if(h->getType() == IsoHandler::eHT_Transmit) {
668                 result &= m_IsoTaskTransmit->requestShadowMapUpdate();
669             } else {
670                 result &= m_IsoTaskReceive->requestShadowMapUpdate();
671             }
672             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " enabled\n");
673             return result;
674         }
675         i++;
676     }
677     debugError("Handler not found\n");
678     return false;
679 }
680
681 void
682 IsoHandlerManager::signalActivityTransmit()
683 {
684     assert(m_IsoTaskTransmit);
685     m_IsoTaskTransmit->signalActivity();
686 }
687
688 void
689 IsoHandlerManager::signalActivityReceive()
690 {
691     assert(m_IsoTaskReceive);
692     m_IsoTaskReceive->signalActivity();
693 }
694
695 bool IsoHandlerManager::registerHandler(IsoHandler *handler)
696 {
697     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
698     assert(handler);
699     handler->setVerboseLevel(getDebugLevel());
700     m_IsoHandlers.push_back(handler);
701     requestShadowMapUpdate();
702     return true;
703 }
704
705 bool IsoHandlerManager::unregisterHandler(IsoHandler *handler)
706 {
707     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
708     assert(handler);
709
710     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
711       it != m_IsoHandlers.end();
712       ++it )
713     {
714         if ( *it == handler ) {
715             m_IsoHandlers.erase(it);
716             requestShadowMapUpdate();
717             return true;
718         }
719     }
720     debugFatal("Could not find handler (%p)\n", handler);
721     return false; //not found
722 }
723
724 /**
725  * Registers an StreamProcessor with the IsoHandlerManager.
726  *
727  * If nescessary, an IsoHandler is created to handle this stream.
728  * Once an StreamProcessor is registered to the handler, it will be included
729  * in the ISO streaming cycle (i.e. receive/transmit of it will occur).
730  *
731  * @param stream the stream to register
732  * @return true if registration succeeds
733  *
734  * \todo : currently there is a one-to-one mapping
735  *        between streams and handlers, this is not ok for
736  *        multichannel receive
737  */
738 bool IsoHandlerManager::registerStream(StreamProcessor *stream)
739 {
740     debugOutput( DEBUG_LEVEL_VERBOSE, "Registering %s stream %p\n", stream->getTypeString(), stream);
741     assert(stream);
742
743     IsoHandler* h = NULL;
744
745     // make sure the stream isn't already attached to a handler
746     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
747       it != m_IsoHandlers.end();
748       ++it )
749     {
750         if((*it)->isStreamRegistered(stream)) {
751             debugError( "stream already registered!\n");
752             return false;
753         }
754     }
755
756     // clean up all handlers that aren't used
757     pruneHandlers();
758
759     // allocate a handler for this stream
760     if (stream->getType()==StreamProcessor::ePT_Receive) {
761         // setup the optimal parameters for the raw1394 ISO buffering
762         unsigned int packets_per_period = stream->getPacketsPerPeriod();
763         unsigned int max_packet_size = stream->getMaxPacketSize();
764         unsigned int page_size = getpagesize() - 2; // for one reason or another this is necessary
765
766         // Ensure we don't request a packet size bigger than the
767         // kernel-enforced maximum which is currently 1 page.
768         if (max_packet_size > page_size) {
769             debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size);
770             return false;
771         }
772
773         unsigned int irq_interval = packets_per_period / MINIMUM_INTERRUPTS_PER_PERIOD;
774         if(irq_interval <= 0) irq_interval=1;
775        
776         // the receive buffer size doesn't matter for the latency,
777         // but it has a minimal value in order for libraw to operate correctly (300)
778         int buffers=400;
779
780         // create the actual handler
781         h = new IsoHandler(*this, IsoHandler::eHT_Receive,
782                            buffers, max_packet_size, irq_interval);
783
784         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoRecvHandler\n");
785
786         if(!h) {
787             debugFatal("Could not create IsoRecvHandler\n");
788             return false;
789         }
790
791     } else if (stream->getType()==StreamProcessor::ePT_Transmit) {
792         // setup the optimal parameters for the raw1394 ISO buffering
793 //        unsigned int packets_per_period = stream->getPacketsPerPeriod();
794         unsigned int max_packet_size = stream->getMaxPacketSize();
795 //         unsigned int page_size = getpagesize();
796
797         // Ensure we don't request a packet size bigger than the
798         // kernel-enforced maximum which is currently 1 page.
799 //         if (max_packet_size > page_size) {
800 //             debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size);
801 //             return false;
802 //         }
803         if (max_packet_size > MAX_XMIT_PACKET_SIZE) {
804             debugError("max packet size (%u) > MAX_XMIT_PACKET_SIZE (%u)\n",
805                        max_packet_size, MAX_XMIT_PACKET_SIZE);
806             return false;
807         }
808
809         // the SP specifies how many packets to ISO-buffer
810         int buffers = stream->getNbPacketsIsoXmitBuffer();
811         if (buffers > MAX_XMIT_NB_BUFFERS) {
812             debugOutput(DEBUG_LEVEL_VERBOSE,
813                         "nb buffers (%u) > MAX_XMIT_NB_BUFFERS (%u)\n",
814                         buffers, MAX_XMIT_NB_BUFFERS);
815             buffers = MAX_XMIT_NB_BUFFERS;
816         }
817         unsigned int irq_interval = buffers / MINIMUM_INTERRUPTS_PER_PERIOD;
818         if(irq_interval <= 0) irq_interval=1;
819
820         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoXmitHandler\n");
821
822         // create the actual handler
823         h = new IsoHandler(*this, IsoHandler::eHT_Transmit,
824                            buffers, max_packet_size, irq_interval);
825
826         if(!h) {
827             debugFatal("Could not create IsoXmitHandler\n");
828             return false;
829         }
830
831     } else {
832         debugFatal("Bad stream type\n");
833         return false;
834     }
835
836     h->setVerboseLevel(getDebugLevel());
837
838     // init the handler
839     if(!h->init()) {
840         debugFatal("Could not initialize receive handler\n");
841         return false;
842     }
843
844     // register the stream with the handler
845     if(!h->registerStream(stream)) {
846         debugFatal("Could not register receive stream with handler\n");
847         return false;
848     }
849
850     // register the handler with the manager
851     if(!registerHandler(h)) {
852         debugFatal("Could not register receive handler with manager\n");
853         return false;
854     }
855     debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n", stream, h);
856
857     m_StreamProcessors.push_back(stream);
858     debugOutput( DEBUG_LEVEL_VERBOSE, " %d streams, %d handlers registered\n",
859                                       m_StreamProcessors.size(), m_IsoHandlers.size());
860     return true;
861 }
862
863 bool IsoHandlerManager::unregisterStream(StreamProcessor *stream)
864 {
865     debugOutput( DEBUG_LEVEL_VERBOSE, "Unregistering %s stream %p\n", stream->getTypeString(), stream);
866     assert(stream);
867
868     // make sure the stream isn't attached to a handler anymore
869     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
870       it != m_IsoHandlers.end();
871       ++it )
872     {
873         if((*it)->isStreamRegistered(stream)) {
874             if(!(*it)->unregisterStream(stream)) {
875                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not unregister stream (%p) from handler (%p)...\n",stream,*it);
876                 return false;
877             }
878             debugOutput( DEBUG_LEVEL_VERBOSE, " unregistered stream (%p) from handler (%p)...\n",stream,*it);
879         }
880     }
881
882     // clean up all handlers that aren't used
883     pruneHandlers();
884
885     // remove the stream from the registered streams list
886     for ( StreamProcessorVectorIterator it = m_StreamProcessors.begin();
887       it != m_StreamProcessors.end();
888       ++it )
889     {
890         if ( *it == stream ) {
891             m_StreamProcessors.erase(it);
892             debugOutput( DEBUG_LEVEL_VERBOSE, " deleted stream (%p) from list...\n", *it);
893             return true;
894         }
895     }
896     return false; //not found
897 }
898
899 /**
900  * @brief unregister a handler from the manager
901  * @note called without the lock held.
902  */
903 void IsoHandlerManager::pruneHandlers() {
904     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
905     IsoHandlerVector toUnregister;
906
907     // find all handlers that are not in use
908     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
909           it != m_IsoHandlers.end();
910           ++it )
911     {
912         if(!((*it)->inUse())) {
913             debugOutput( DEBUG_LEVEL_VERBOSE, " handler (%p) not in use\n",*it);
914             toUnregister.push_back(*it);
915         }
916     }
917     // delete them
918     for ( IsoHandlerVectorIterator it = toUnregister.begin();
919           it != toUnregister.end();
920           ++it )
921     {
922         unregisterHandler(*it);
923
924         debugOutput( DEBUG_LEVEL_VERBOSE, " deleting handler (%p)\n",*it);
925
926         // Now the handler's been unregistered it won't be reused
927         // again.  Therefore it really needs to be formally deleted
928         // to free up the raw1394 handle.  Otherwise things fall
929         // apart after several xrun recoveries as the system runs
930         // out of resources to support all the disused but still
931         // allocated raw1394 handles.  At least this is the current
932         // theory as to why we end up with "memory allocation"
933         // failures after several Xrun recoveries.
934         delete *it;
935     }
936 }
937
938 bool
939 IsoHandlerManager::stopHandlerForStream(Streaming::StreamProcessor *stream) {
940     // check state
941     if(m_State != E_Running) {
942         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
943         return false;
944     }
945     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
946       it != m_IsoHandlers.end();
947       ++it )
948     {
949         if((*it)->isStreamRegistered(stream)) {
950             debugOutput( DEBUG_LEVEL_VERBOSE, " stopping handler %p for stream %p\n", *it, stream);
951             if(!(*it)->disable()) {
952                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not disable handler (%p)\n",*it);
953                 return false;
954             }
955             bool result;
956             if((*it)->getType() == IsoHandler::eHT_Transmit) {
957                 result = m_IsoTaskTransmit->requestShadowMapUpdate();
958             } else {
959                 result = m_IsoTaskReceive->requestShadowMapUpdate();
960             }
961             if(!result) {
962                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
963                 return false;
964             }
965             return true;
966         }
967     }
968     debugError("Stream %p has no attached handler\n", stream);
969     return false;
970 }
971
972 int
973 IsoHandlerManager::getPacketLatencyForStream(Streaming::StreamProcessor *stream) {
974     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
975       it != m_IsoHandlers.end();
976       ++it )
977     {
978         if((*it)->isStreamRegistered(stream)) {
979             return (*it)->getPacketLatency();
980         }
981     }
982     debugError("Stream %p has no attached handler\n", stream);
983     return 0;
984 }
985
986 void
987 IsoHandlerManager::flushHandlerForStream(Streaming::StreamProcessor *stream) {
988     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
989       it != m_IsoHandlers.end();
990       ++it )
991     {
992         if((*it)->isStreamRegistered(stream)) {
993             (*it)->flush();
994         }
995     }
996     debugError("Stream %p has no attached handler\n", stream);
997     return;
998 }
999
1000 IsoHandler *
1001 IsoHandlerManager::getHandlerForStream(Streaming::StreamProcessor *stream) {
1002     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1003       it != m_IsoHandlers.end();
1004       ++it )
1005     {
1006         if((*it)->isStreamRegistered(stream)) {
1007             return (*it);
1008         }
1009     }
1010     debugError("Stream %p has no attached handler\n", stream);
1011     return NULL;
1012 }
1013
1014 bool
1015 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream) {
1016     return startHandlerForStream(stream, -1);
1017 }
1018
1019 bool
1020 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream, int cycle) {
1021     // check state
1022     if(m_State != E_Running) {
1023         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
1024         return false;
1025     }
1026     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1027       it != m_IsoHandlers.end();
1028       ++it )
1029     {
1030         if((*it)->isStreamRegistered(stream)) {
1031             debugOutput( DEBUG_LEVEL_VERBOSE, " starting handler %p for stream %p\n", *it, stream);
1032             if(!(*it)->enable(cycle)) {
1033                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not enable handler (%p)\n",*it);
1034                 return false;
1035             }
1036             bool result;
1037             if((*it)->getType() == IsoHandler::eHT_Transmit) {
1038                 result = m_IsoTaskTransmit->requestShadowMapUpdate();
1039             } else {
1040                 result = m_IsoTaskReceive->requestShadowMapUpdate();
1041             }
1042             if(!result) {
1043                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
1044                 return false;
1045             }
1046             return true;
1047         }
1048     }
1049     debugError("Stream %p has no attached handler\n", stream);
1050     return false;
1051 }
1052
1053 bool IsoHandlerManager::stopHandlers() {
1054     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
1055
1056     // check state
1057     if(m_State != E_Running) {
1058         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
1059         return false;
1060     }
1061
1062     bool retval=true;
1063
1064     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1065         it != m_IsoHandlers.end();
1066         ++it )
1067     {
1068         debugOutput( DEBUG_LEVEL_VERBOSE, "Stopping handler (%p)\n",*it);
1069         if(!(*it)->disable()){
1070             debugOutput( DEBUG_LEVEL_VERBOSE, " could not stop handler (%p)\n",*it);
1071             retval=false;
1072         }
1073         bool result;
1074         if((*it)->getType() == IsoHandler::eHT_Transmit) {
1075             result = m_IsoTaskTransmit->requestShadowMapUpdate();
1076         } else {
1077             result = m_IsoTaskReceive->requestShadowMapUpdate();
1078         }
1079         if(!result) {
1080             debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
1081             return false;
1082         }
1083     }
1084
1085     if (retval) {
1086         m_State=E_Prepared;
1087     } else {
1088         m_State=E_Error;
1089     }
1090     return retval;
1091 }
1092
1093 bool IsoHandlerManager::reset() {
1094     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
1095     // check state
1096     if(m_State == E_Error) {
1097         debugFatal("Resetting from error condition not yet supported...\n");
1098         return false;
1099     }
1100     // if not in an error condition, reset means stop the handlers
1101     return stopHandlers();
1102 }
1103
1104 void IsoHandlerManager::setVerboseLevel(int i) {
1105     setDebugLevel(i);
1106     // propagate the debug level
1107     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1108           it != m_IsoHandlers.end();
1109           ++it )
1110     {
1111         (*it)->setVerboseLevel(i);
1112     }
1113     if(m_IsoThreadTransmit) m_IsoThreadTransmit->setVerboseLevel(i);
1114     if(m_IsoTaskTransmit)   m_IsoTaskTransmit->setVerboseLevel(i);
1115     if(m_IsoThreadReceive)  m_IsoThreadReceive->setVerboseLevel(i);
1116     if(m_IsoTaskReceive)    m_IsoTaskReceive->setVerboseLevel(i);
1117     setDebugLevel(i);
1118     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", i );
1119 }
1120
1121 void IsoHandlerManager::dumpInfo() {
1122     #ifdef DEBUG
1123     unsigned int i=0;
1124     debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping IsoHandlerManager Stream handler information...\n");
1125     debugOutputShort( DEBUG_LEVEL_NORMAL, " State: %d\n",(int)m_State);
1126
1127     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1128           it != m_IsoHandlers.end();
1129           ++it )
1130     {
1131         debugOutputShort( DEBUG_LEVEL_NORMAL, " IsoHandler %d (%p)\n",i++,*it);
1132         (*it)->dumpInfo();
1133     }
1134     #endif
1135 }
1136
1137 const char *
1138 IsoHandlerManager::eHSToString(enum eHandlerStates s) {
1139     switch (s) {
1140         default: return "Invalid";
1141         case E_Created: return "Created";
1142         case E_Prepared: return "Prepared";
1143         case E_Running: return "Running";
1144         case E_Error: return "Error";
1145     }
1146 }
Note: See TracBrowser for help on using the browser.