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

Revision 1722, 41.2 kB (checked in by ppalmers, 14 years ago)

fix format warnings for extreme debugging

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