root/branches/libffado-2.0/src/libieee1394/IsoHandlerManager.cpp

Revision 1342, 38.8 kB (checked in by ppalmers, 16 years ago)

improve interrupt scheduling

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "config.h"
25 #include "IsoHandlerManager.h"
26 #include "ieee1394service.h"
27 #include "cycletimer.h"
28 #include "libstreaming/generic/StreamProcessor.h"
29
30 #include "libutil/Atomic.h"
31 #include "libutil/PosixThread.h"
32 #include "libutil/SystemTimeSource.h"
33 #include "libutil/Watchdog.h"
34
35 #include <cstring>
36 #include <assert.h>
37
38 IMPL_DEBUG_MODULE( IsoHandlerManager, IsoHandlerManager, DEBUG_LEVEL_NORMAL );
39 IMPL_DEBUG_MODULE( IsoTask, IsoTask, DEBUG_LEVEL_NORMAL );
40
41 using namespace Streaming;
42
43 // --- ISO Thread --- //
44
45 IsoTask::IsoTask(IsoHandlerManager& manager, enum IsoHandler::EHandlerType t)
46     : m_manager( manager )
47     , m_SyncIsoHandler ( NULL )
48     , m_handlerType( t )
49     , m_running( false )
50     , m_in_busreset( false )
51 {
52 }
53
54 IsoTask::~IsoTask()
55 {
56     sem_destroy(&m_activity_semaphore);
57 }
58
59 bool
60 IsoTask::Init()
61 {
62     request_update = 0;
63
64     int i;
65     for (i=0; i < ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT; i++) {
66         m_IsoHandler_map_shadow[i] = NULL;
67         m_poll_fds_shadow[i].events = 0;
68     }
69     m_poll_nfds_shadow = 0;
70
71     #ifdef DEBUG
72     m_last_loop_entry = 0;
73     m_successive_short_loops = 0;
74     #endif
75
76     sem_init(&m_activity_semaphore, 0, 0);
77     m_running = true;
78     return true;
79 }
80
81 bool
82 IsoTask::requestShadowMapUpdate()
83 {
84     debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) enter\n", this);
85     INC_ATOMIC(&request_update);
86
87     // get the thread going again
88     signalActivity();
89
90     if (m_running) {
91         int timeout = 1000;
92         while(request_update && timeout--) {
93             Util::SystemTimeSource::SleepUsecRelative(1000);
94         }
95         if(timeout == 0) {
96             debugError("timeout waiting for shadow map update\n");
97         }
98     }
99     debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) exit\n", this);
100     return true;
101 }
102
103 bool
104 IsoTask::handleBusReset()
105 {
106     bool retval = true;
107     m_in_busreset = true;
108     requestShadowMapUpdate();
109     if(request_update) {
110         debugError("shadow map update request not honored\n");
111         return false;
112     }
113
114     unsigned int i, max;
115     max = m_manager.m_IsoHandlers.size();
116     for (i = 0; i < max; i++) {
117         IsoHandler *h = m_manager.m_IsoHandlers.at(i);
118         assert(h);
119
120         // skip the handlers not intended for us
121         if(h->getType() != m_handlerType) continue;
122
123         if (!h->handleBusReset()) {
124             debugWarning("Failed to handle busreset on %p\n");
125             retval = false;
126         }
127     }
128
129     // re-enable processing
130     m_in_busreset = false;
131     requestShadowMapUpdate();
132     if(request_update) {
133         debugError("shadow map update request not honored\n");
134         return false;
135     }
136     return retval;
137 }
138
139 // updates the internal stream map
140 // note that this should be executed with the guarantee that
141 // nobody will modify the parent data structures
142 void
143 IsoTask::updateShadowMapHelper()
144 {
145     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) updating shadow vars...\n", this);
146     // we are handling a busreset
147     if(m_in_busreset) {
148         m_poll_nfds_shadow = 0;
149         return;
150     }
151     unsigned int i, cnt, max;
152     max = m_manager.m_IsoHandlers.size();
153     m_SyncIsoHandler = NULL;
154     for (i = 0, cnt = 0; i < max; i++) {
155         IsoHandler *h = m_manager.m_IsoHandlers.at(i);
156         assert(h);
157
158         // skip the handlers not intended for us
159         if(h->getType() != m_handlerType) continue;
160
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     if(handler_died) {
346         m_running = false;
347         return false; // one or more handlers have died
348     }
349
350     // iterate the handlers
351     for (i = 0; i < m_poll_nfds_shadow; i++) {
352         #ifdef DEBUG
353         if(m_poll_fds_shadow[i].revents) {
354             debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
355                         "(%p, %s) received events: %08X for (%d/%d, %p, %s)\n",
356                         this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"),
357                         m_poll_fds_shadow[i].revents,
358                         i, m_poll_nfds_shadow,
359                         m_IsoHandler_map_shadow[i],
360                         m_IsoHandler_map_shadow[i]->getTypeString());
361         }
362         #endif
363
364         // if we get here, it means two things:
365         // 1) the kernel can accept or provide packets (poll returned POLLIN)
366         // 2) the client can provide or accept packets (since we enabled polling)
367         if(m_poll_fds_shadow[i].revents & (POLLIN)) {
368             m_IsoHandler_map_shadow[i]->iterate(ctr_at_poll_return);
369         } else {
370             // there might be some error condition
371             if (m_poll_fds_shadow[i].revents & POLLERR) {
372                 debugWarning("(%p) error on fd for %d\n", this, i);
373             }
374             if (m_poll_fds_shadow[i].revents & POLLHUP) {
375                 debugWarning("(%p) hangup on fd for %d\n", this, i);
376             }
377         }
378     }
379     return true;
380 }
381
382 enum IsoTask::eActivityResult
383 IsoTask::waitForActivity()
384 {
385     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
386                        "(%p, %s) waiting for activity\n",
387                        this, (m_handlerType == IsoHandler::eHT_Transmit? "Transmit": "Receive"));
388     struct timespec ts;
389     int result;
390     long long int timeout_nsec = ISOHANDLERMANAGER_ISO_TASK_WAIT_TIMEOUT_USECS * 1000LL;
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 += 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, 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, 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     m_realtime = rt;
535     m_priority = priority;
536
537     if (m_IsoThreadTransmit) {
538         if (m_realtime) {
539             m_IsoThreadTransmit->AcquireRealTime(m_priority
540                                                  + ISOHANDLERMANAGER_ISO_PRIO_INCREASE
541                                                  + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT);
542         } else {
543             m_IsoThreadTransmit->DropRealTime();
544         }
545     }
546     if (m_IsoThreadReceive) {
547         if (m_realtime) {
548             m_IsoThreadReceive->AcquireRealTime(m_priority
549                                                 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE
550                                                 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV);
551         } else {
552             m_IsoThreadReceive->DropRealTime();
553         }
554     }
555
556     return true;
557 }
558
559 bool IsoHandlerManager::init()
560 {
561     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing ISO manager %p...\n", this);
562     // check state
563     if(m_State != E_Created) {
564         debugError("Manager already initialized...\n");
565         return false;
566     }
567
568     // create threads to iterate our ISO handlers
569     debugOutput( DEBUG_LEVEL_VERBOSE, "Create iso thread for %p transmit...\n", this);
570     m_IsoTaskTransmit = new IsoTask( *this, IsoHandler::eHT_Transmit );
571     if(!m_IsoTaskTransmit) {
572         debugFatal("No task\n");
573         return false;
574     }
575     m_IsoTaskTransmit->setVerboseLevel(getDebugLevel());
576     m_IsoThreadTransmit = new Util::PosixThread(m_IsoTaskTransmit, "ISOXMT", m_realtime,
577                                                 m_priority + ISOHANDLERMANAGER_ISO_PRIO_INCREASE
578                                                 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT,
579                                                 PTHREAD_CANCEL_DEFERRED);
580
581     if(!m_IsoThreadTransmit) {
582         debugFatal("No thread\n");
583         return false;
584     }
585     m_IsoThreadTransmit->setVerboseLevel(getDebugLevel());
586
587     debugOutput( DEBUG_LEVEL_VERBOSE, "Create iso thread for %p receive...\n", this);
588     m_IsoTaskReceive = new IsoTask( *this, IsoHandler::eHT_Receive );
589     if(!m_IsoTaskReceive) {
590         debugFatal("No task\n");
591         return false;
592     }
593     m_IsoTaskReceive->setVerboseLevel(getDebugLevel());
594     m_IsoThreadReceive = new Util::PosixThread(m_IsoTaskReceive, "ISORCV", m_realtime,
595                                                m_priority + ISOHANDLERMANAGER_ISO_PRIO_INCREASE
596                                                + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV,
597                                                PTHREAD_CANCEL_DEFERRED);
598
599     if(!m_IsoThreadReceive) {
600         debugFatal("No thread\n");
601         return false;
602     }
603     m_IsoThreadReceive->setVerboseLevel(getDebugLevel());
604     // register the thread with the RT watchdog
605     Util::Watchdog *watchdog = m_service.getWatchdog();
606     if(watchdog) {
607         if(!watchdog->registerThread(m_IsoThreadTransmit)) {
608             debugWarning("could not register iso transmit thread with watchdog\n");
609         }
610         if(!watchdog->registerThread(m_IsoThreadReceive)) {
611             debugWarning("could not register iso receive thread with watchdog\n");
612         }
613     } else {
614         debugWarning("could not find valid watchdog\n");
615     }
616
617     if (m_IsoThreadTransmit->Start() != 0) {
618         debugFatal("Could not start ISO Transmit thread\n");
619         return false;
620     }
621     if (m_IsoThreadReceive->Start() != 0) {
622         debugFatal("Could not start ISO Receive thread\n");
623         return false;
624     }
625
626     m_State=E_Running;
627     return true;
628 }
629
630 bool
631 IsoHandlerManager::disable(IsoHandler *h) {
632     bool result;
633     int i=0;
634     debugOutput(DEBUG_LEVEL_VERBOSE, "Disable on IsoHandler %p\n", h);
635     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
636         it != m_IsoHandlers.end();
637         ++it )
638     {
639         if ((*it) == h) {
640             result = h->disable();
641             if(h->getType() == IsoHandler::eHT_Transmit) {
642                 result &= m_IsoTaskTransmit->requestShadowMapUpdate();
643             } else {
644                 result &= m_IsoTaskReceive->requestShadowMapUpdate();
645             }
646             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " disabled\n");
647             return result;
648         }
649         i++;
650     }
651     debugError("Handler not found\n");
652     return false;
653 }
654
655 bool
656 IsoHandlerManager::enable(IsoHandler *h) {
657     bool result;
658     int i=0;
659     debugOutput(DEBUG_LEVEL_VERBOSE, "Enable on IsoHandler %p\n", h);
660     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
661         it != m_IsoHandlers.end();
662         ++it )
663     {
664         if ((*it) == h) {
665             result = h->enable();
666             if(h->getType() == IsoHandler::eHT_Transmit) {
667                 result &= m_IsoTaskTransmit->requestShadowMapUpdate();
668             } else {
669                 result &= m_IsoTaskReceive->requestShadowMapUpdate();
670             }
671             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " enabled\n");
672             return result;
673         }
674         i++;
675     }
676     debugError("Handler not found\n");
677     return false;
678 }
679
680 void
681 IsoHandlerManager::signalActivityTransmit()
682 {
683     assert(m_IsoTaskTransmit);
684     m_IsoTaskTransmit->signalActivity();
685 }
686
687 void
688 IsoHandlerManager::signalActivityReceive()
689 {
690     assert(m_IsoTaskReceive);
691     m_IsoTaskReceive->signalActivity();
692 }
693
694 bool IsoHandlerManager::registerHandler(IsoHandler *handler)
695 {
696     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
697     assert(handler);
698     handler->setVerboseLevel(getDebugLevel());
699     m_IsoHandlers.push_back(handler);
700     requestShadowMapUpdate();
701     return true;
702 }
703
704 bool IsoHandlerManager::unregisterHandler(IsoHandler *handler)
705 {
706     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
707     assert(handler);
708
709     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
710       it != m_IsoHandlers.end();
711       ++it )
712     {
713         if ( *it == handler ) {
714             m_IsoHandlers.erase(it);
715             requestShadowMapUpdate();
716             return true;
717         }
718     }
719     debugFatal("Could not find handler (%p)\n", handler);
720     return false; //not found
721 }
722
723 /**
724  * Registers an StreamProcessor with the IsoHandlerManager.
725  *
726  * If nescessary, an IsoHandler is created to handle this stream.
727  * Once an StreamProcessor is registered to the handler, it will be included
728  * in the ISO streaming cycle (i.e. receive/transmit of it will occur).
729  *
730  * @param stream the stream to register
731  * @return true if registration succeeds
732  *
733  * \todo : currently there is a one-to-one mapping
734  *        between streams and handlers, this is not ok for
735  *        multichannel receive
736  */
737 bool IsoHandlerManager::registerStream(StreamProcessor *stream)
738 {
739     debugOutput( DEBUG_LEVEL_VERBOSE, "Registering %s stream %p\n", stream->getTypeString(), stream);
740     assert(stream);
741
742     IsoHandler* h = NULL;
743
744     // make sure the stream isn't already attached to a handler
745     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
746       it != m_IsoHandlers.end();
747       ++it )
748     {
749         if((*it)->isStreamRegistered(stream)) {
750             debugError( "stream already registered!\n");
751             return false;
752         }
753     }
754
755     // clean up all handlers that aren't used
756     pruneHandlers();
757
758     // allocate a handler for this stream
759     if (stream->getType()==StreamProcessor::ePT_Receive) {
760         // setup the optimal parameters for the raw1394 ISO buffering
761         unsigned int packets_per_period = stream->getPacketsPerPeriod();
762         unsigned int max_packet_size = stream->getMaxPacketSize() + 8; // bufferfill takes another 8 bytes for headers
763         unsigned int page_size = getpagesize();
764
765         // Ensure we don't request a packet size bigger than the
766         // kernel-enforced maximum which is currently 1 page.
767         // NOTE: PP: this is not really true AFAICT
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         // the interrupt/wakeup interval prediction of raw1394 is a mess...
774         int wanted_irq_interval = (packets_per_period-1) / MINIMUM_INTERRUPTS_PER_PERIOD;
775         if(wanted_irq_interval <= 0) wanted_irq_interval=1;
776
777         // mimic kernel initialization
778         unsigned int kern_buff_stride = RAW1394_RCV_MIN_BUF_STRIDE;
779         for (; kern_buff_stride < max_packet_size; kern_buff_stride *= 2);
780         if (kern_buff_stride > page_size) kern_buff_stride = page_size;
781         // kern_buff_stride is the minimal granularity of interrupts
782         // therefore the following will result in on-average correct interrupt timing
783         int irq_interval = (wanted_irq_interval * max_packet_size) / kern_buff_stride;
784
785         // the receive buffer size doesn't matter for the latency,
786         // but it has a minimal value in order for libraw to operate correctly (300)
787         int buffers=400;
788
789         // create the actual handler
790         h = new IsoHandler(*this, IsoHandler::eHT_Receive,
791                            buffers, max_packet_size, irq_interval);
792
793         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoRecvHandler\n");
794
795         if(!h) {
796             debugFatal("Could not create IsoRecvHandler\n");
797             return false;
798         }
799
800     } else if (stream->getType()==StreamProcessor::ePT_Transmit) {
801         // setup the optimal parameters for the raw1394 ISO buffering
802 //        unsigned int packets_per_period = stream->getPacketsPerPeriod();
803         unsigned int max_packet_size = stream->getMaxPacketSize();
804 //         unsigned int page_size = getpagesize();
805
806         // Ensure we don't request a packet size bigger than the
807         // kernel-enforced maximum which is currently 1 page.
808 //         if (max_packet_size > page_size) {
809 //             debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size);
810 //             return false;
811 //         }
812         if (max_packet_size > MAX_XMIT_PACKET_SIZE) {
813             debugError("max packet size (%u) > MAX_XMIT_PACKET_SIZE (%u)\n",
814                        max_packet_size, MAX_XMIT_PACKET_SIZE);
815             return false;
816         }
817
818         // the SP specifies how many packets to ISO-buffer
819         int buffers = stream->getNbPacketsIsoXmitBuffer();
820         if (buffers > MAX_XMIT_NB_BUFFERS) {
821             debugOutput(DEBUG_LEVEL_VERBOSE,
822                         "nb buffers (%u) > MAX_XMIT_NB_BUFFERS (%u)\n",
823                         buffers, MAX_XMIT_NB_BUFFERS);
824             buffers = MAX_XMIT_NB_BUFFERS;
825         }
826         unsigned int irq_interval = buffers / MINIMUM_INTERRUPTS_PER_PERIOD;
827         if(irq_interval <= 0) irq_interval=1;
828
829         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoXmitHandler\n");
830
831         // create the actual handler
832         h = new IsoHandler(*this, IsoHandler::eHT_Transmit,
833                            buffers, max_packet_size, irq_interval);
834
835         if(!h) {
836             debugFatal("Could not create IsoXmitHandler\n");
837             return false;
838         }
839
840     } else {
841         debugFatal("Bad stream type\n");
842         return false;
843     }
844
845     h->setVerboseLevel(getDebugLevel());
846
847     // init the handler
848     if(!h->init()) {
849         debugFatal("Could not initialize receive handler\n");
850         return false;
851     }
852
853     // register the stream with the handler
854     if(!h->registerStream(stream)) {
855         debugFatal("Could not register receive stream with handler\n");
856         return false;
857     }
858
859     // register the handler with the manager
860     if(!registerHandler(h)) {
861         debugFatal("Could not register receive handler with manager\n");
862         return false;
863     }
864     debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n", stream, h);
865
866     m_StreamProcessors.push_back(stream);
867     debugOutput( DEBUG_LEVEL_VERBOSE, " %d streams, %d handlers registered\n",
868                                       m_StreamProcessors.size(), m_IsoHandlers.size());
869     return true;
870 }
871
872 bool IsoHandlerManager::unregisterStream(StreamProcessor *stream)
873 {
874     debugOutput( DEBUG_LEVEL_VERBOSE, "Unregistering %s stream %p\n", stream->getTypeString(), stream);
875     assert(stream);
876
877     // make sure the stream isn't attached to a handler anymore
878     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
879       it != m_IsoHandlers.end();
880       ++it )
881     {
882         if((*it)->isStreamRegistered(stream)) {
883             if(!(*it)->unregisterStream(stream)) {
884                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not unregister stream (%p) from handler (%p)...\n",stream,*it);
885                 return false;
886             }
887             debugOutput( DEBUG_LEVEL_VERBOSE, " unregistered stream (%p) from handler (%p)...\n",stream,*it);
888         }
889     }
890
891     // clean up all handlers that aren't used
892     pruneHandlers();
893
894     // remove the stream from the registered streams list
895     for ( StreamProcessorVectorIterator it = m_StreamProcessors.begin();
896       it != m_StreamProcessors.end();
897       ++it )
898     {
899         if ( *it == stream ) {
900             m_StreamProcessors.erase(it);
901             debugOutput( DEBUG_LEVEL_VERBOSE, " deleted stream (%p) from list...\n", *it);
902             return true;
903         }
904     }
905     return false; //not found
906 }
907
908 /**
909  * @brief unregister a handler from the manager
910  * @note called without the lock held.
911  */
912 void IsoHandlerManager::pruneHandlers() {
913     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
914     IsoHandlerVector toUnregister;
915
916     // find all handlers that are not in use
917     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
918           it != m_IsoHandlers.end();
919           ++it )
920     {
921         if(!((*it)->inUse())) {
922             debugOutput( DEBUG_LEVEL_VERBOSE, " handler (%p) not in use\n",*it);
923             toUnregister.push_back(*it);
924         }
925     }
926     // delete them
927     for ( IsoHandlerVectorIterator it = toUnregister.begin();
928           it != toUnregister.end();
929           ++it )
930     {
931         unregisterHandler(*it);
932
933         debugOutput( DEBUG_LEVEL_VERBOSE, " deleting handler (%p)\n",*it);
934
935         // Now the handler's been unregistered it won't be reused
936         // again.  Therefore it really needs to be formally deleted
937         // to free up the raw1394 handle.  Otherwise things fall
938         // apart after several xrun recoveries as the system runs
939         // out of resources to support all the disused but still
940         // allocated raw1394 handles.  At least this is the current
941         // theory as to why we end up with "memory allocation"
942         // failures after several Xrun recoveries.
943         delete *it;
944     }
945 }
946
947 bool
948 IsoHandlerManager::stopHandlerForStream(Streaming::StreamProcessor *stream) {
949     // check state
950     if(m_State != E_Running) {
951         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
952         return false;
953     }
954     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
955       it != m_IsoHandlers.end();
956       ++it )
957     {
958         if((*it)->isStreamRegistered(stream)) {
959             debugOutput( DEBUG_LEVEL_VERBOSE, " stopping handler %p for stream %p\n", *it, stream);
960             if(!(*it)->disable()) {
961                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not disable handler (%p)\n",*it);
962                 return false;
963             }
964             bool result;
965             if((*it)->getType() == IsoHandler::eHT_Transmit) {
966                 result = m_IsoTaskTransmit->requestShadowMapUpdate();
967             } else {
968                 result = m_IsoTaskReceive->requestShadowMapUpdate();
969             }
970             if(!result) {
971                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
972                 return false;
973             }
974             return true;
975         }
976     }
977     debugError("Stream %p has no attached handler\n", stream);
978     return false;
979 }
980
981 int
982 IsoHandlerManager::getPacketLatencyForStream(Streaming::StreamProcessor *stream) {
983     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
984       it != m_IsoHandlers.end();
985       ++it )
986     {
987         if((*it)->isStreamRegistered(stream)) {
988             return (*it)->getPacketLatency();
989         }
990     }
991     debugError("Stream %p has no attached handler\n", stream);
992     return 0;
993 }
994
995 void
996 IsoHandlerManager::flushHandlerForStream(Streaming::StreamProcessor *stream) {
997     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
998       it != m_IsoHandlers.end();
999       ++it )
1000     {
1001         if((*it)->isStreamRegistered(stream)) {
1002             (*it)->flush();
1003         }
1004     }
1005     debugError("Stream %p has no attached handler\n", stream);
1006     return;
1007 }
1008
1009 IsoHandler *
1010 IsoHandlerManager::getHandlerForStream(Streaming::StreamProcessor *stream) {
1011     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1012       it != m_IsoHandlers.end();
1013       ++it )
1014     {
1015         if((*it)->isStreamRegistered(stream)) {
1016             return (*it);
1017         }
1018     }
1019     debugError("Stream %p has no attached handler\n", stream);
1020     return NULL;
1021 }
1022
1023 bool
1024 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream) {
1025     return startHandlerForStream(stream, -1);
1026 }
1027
1028 bool
1029 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream, int cycle) {
1030     // check state
1031     if(m_State != E_Running) {
1032         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
1033         return false;
1034     }
1035     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1036       it != m_IsoHandlers.end();
1037       ++it )
1038     {
1039         if((*it)->isStreamRegistered(stream)) {
1040             debugOutput( DEBUG_LEVEL_VERBOSE, " starting handler %p for stream %p\n", *it, stream);
1041             if(!(*it)->enable(cycle)) {
1042                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not enable handler (%p)\n",*it);
1043                 return false;
1044             }
1045             bool result;
1046             if((*it)->getType() == IsoHandler::eHT_Transmit) {
1047                 result = m_IsoTaskTransmit->requestShadowMapUpdate();
1048             } else {
1049                 result = m_IsoTaskReceive->requestShadowMapUpdate();
1050             }
1051             if(!result) {
1052                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
1053                 return false;
1054             }
1055             return true;
1056         }
1057     }
1058     debugError("Stream %p has no attached handler\n", stream);
1059     return false;
1060 }
1061
1062 bool IsoHandlerManager::stopHandlers() {
1063     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
1064
1065     // check state
1066     if(m_State != E_Running) {
1067         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
1068         return false;
1069     }
1070
1071     bool retval=true;
1072
1073     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1074         it != m_IsoHandlers.end();
1075         ++it )
1076     {
1077         debugOutput( DEBUG_LEVEL_VERBOSE, "Stopping handler (%p)\n",*it);
1078         if(!(*it)->disable()){
1079             debugOutput( DEBUG_LEVEL_VERBOSE, " could not stop handler (%p)\n",*it);
1080             retval=false;
1081         }
1082         bool result;
1083         if((*it)->getType() == IsoHandler::eHT_Transmit) {
1084             result = m_IsoTaskTransmit->requestShadowMapUpdate();
1085         } else {
1086             result = m_IsoTaskReceive->requestShadowMapUpdate();
1087         }
1088         if(!result) {
1089             debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
1090             return false;
1091         }
1092     }
1093
1094     if (retval) {
1095         m_State=E_Prepared;
1096     } else {
1097         m_State=E_Error;
1098     }
1099     return retval;
1100 }
1101
1102 bool IsoHandlerManager::reset() {
1103     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
1104     // check state
1105     if(m_State == E_Error) {
1106         debugFatal("Resetting from error condition not yet supported...\n");
1107         return false;
1108     }
1109     // if not in an error condition, reset means stop the handlers
1110     return stopHandlers();
1111 }
1112
1113 void IsoHandlerManager::setVerboseLevel(int i) {
1114     setDebugLevel(i);
1115     // propagate the debug level
1116     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1117           it != m_IsoHandlers.end();
1118           ++it )
1119     {
1120         (*it)->setVerboseLevel(i);
1121     }
1122     if(m_IsoThreadTransmit) m_IsoThreadTransmit->setVerboseLevel(i);
1123     if(m_IsoTaskTransmit)   m_IsoTaskTransmit->setVerboseLevel(i);
1124     if(m_IsoThreadReceive)  m_IsoThreadReceive->setVerboseLevel(i);
1125     if(m_IsoTaskReceive)    m_IsoTaskReceive->setVerboseLevel(i);
1126     setDebugLevel(i);
1127     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", i );
1128 }
1129
1130 void IsoHandlerManager::dumpInfo() {
1131     #ifdef DEBUG
1132     unsigned int i=0;
1133     debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping IsoHandlerManager Stream handler information...\n");
1134     debugOutputShort( DEBUG_LEVEL_NORMAL, " State: %d\n",(int)m_State);
1135
1136     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
1137           it != m_IsoHandlers.end();
1138           ++it )
1139     {
1140         debugOutputShort( DEBUG_LEVEL_NORMAL, " IsoHandler %d (%p)\n",i++,*it);
1141         (*it)->dumpInfo();
1142     }
1143     #endif
1144 }
1145
1146 const char *
1147 IsoHandlerManager::eHSToString(enum eHandlerStates s) {
1148     switch (s) {
1149         default: return "Invalid";
1150         case E_Created: return "Created";
1151         case E_Prepared: return "Prepared";
1152         case E_Running: return "Running";
1153         case E_Error: return "Error";
1154     }
1155 }
Note: See TracBrowser for help on using the browser.