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

Revision 1535, 41.3 kB (checked in by ppalmers, 12 years ago)

add support for the FCA-202, and possibly other Oxford FW-92x devices

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