root/trunk/libfreebob/src/debugmodule/debugmodule.cpp

Revision 360, 10.7 kB (checked in by pieterpalmers, 17 years ago)

- temporary commit to backup some work

- Started a framework to synchronize IsoHandlers? to

any generic TimeSource?. The idea is to introduce
one overall time reference, and resynchronize all
other timed events to this time source.
This will, on the long run, allow:

  • combining devices on multiple FW busses together,
    as these are not synched by hardware.
  • synchronizing to the system clock
  • synchronizing to any other time source (e.g.
    when implementing a jackd client, i.e. using
    the freebob devices as jackd clients).

- Implemented a realtime safe way to read the cycle

timer for an IsoHandler?. (+ test application)

- Implemented tests/test-sytmonitor:

Monitors 2 or more channels and reports the average
SYT timestamp difference between both.

- Messed around with SYT timestamping for AMDTP. Doesn't

work (yet).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /* debugmodule.cpp
2  * Copyright (C) 2005 by Daniel Wagner
3  *
4  * This file is part of FreeBoB.
5  *
6  * FreeBoB is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * FreeBoB is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with FreeBoB; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18  * MA 02111-1307 USA.
19  */
20
21 #include "debugmodule.h"
22
23 #include <stdarg.h>
24 #include <netinet/in.h>
25
26 #include <iostream>
27
28 using namespace std;
29
30 struct ColorEntry  {
31     const char* preSequence;
32     const char* postSequence;
33 };
34
35 ColorEntry colorTable[] = {
36     { "\033[31mFatal",   "\033[0m" },
37     { "\033[31mError",   "\033[0m" },
38     { "\033[31mWarning", "\033[0m" },
39     { "Debug",           ""        },
40 };
41
42
43 DebugModule::DebugModule( std::string name,  debug_level_t level )
44     : m_name( name )
45     , m_level( level )
46 {
47     if ( !DebugModuleManager::instance()->registerModule( *this ) ) {
48         cerr << "Could not register DebugModule (" << name
49              << ") at DebugModuleManager"
50              << endl;
51     }
52 }
53
54 DebugModule::~DebugModule()
55 {
56     cerr << "Unregistering "
57          << this->getName()
58          << " at DebugModuleManager"
59          << endl;
60     if ( !DebugModuleManager::instance()->unregisterModule( *this ) ) {
61         cerr << "Could not unregister DebugModule at DebugModuleManager"
62              << endl;
63     }
64    
65 }
66
67 void
68 DebugModule::printShort( debug_level_t level,
69                          const char* format,
70                          ... ) const
71 {
72     if ( level > m_level ) {
73         return;
74     }
75
76     va_list arg;
77
78     va_start( arg, format );
79
80     DebugModuleManager::instance()->va_print( format, arg );
81    
82     va_end( arg );
83 }
84
85 void
86 DebugModule::print( debug_level_t level,
87                     const char*   file,
88                     const char*   function,
89                     unsigned int  line,
90                     const char*   format,
91                     ... ) const
92 {
93     if ( level > m_level ) {
94         return;
95     }
96
97     va_list arg;
98     va_start( arg, format );
99     DebugModuleManager::instance()->print( "%s (%s)[%4d] %s: ", getPreSequence( level ),
100                  file,  line,  function );
101     DebugModuleManager::instance()->va_print( format, arg );
102     DebugModuleManager::instance()->print( "%s", getPostSequence( level ) );
103     va_end( arg );
104 }
105
106 const char*
107 DebugModule::getPreSequence( debug_level_t level ) const
108 {
109     if ( ( level <= eDL_Normal ) && ( level >= eDL_Fatal ) ) {
110         return colorTable[level].preSequence;
111     }
112     return colorTable[eDL_Normal].preSequence;
113 }
114
115 const char*
116 DebugModule::getPostSequence( debug_level_t level ) const
117 {
118     if ( ( level <= eDL_Normal ) && ( level >= eDL_Fatal ) ) {
119         return colorTable[level].postSequence;
120     }
121     return colorTable[eDL_Normal].postSequence;
122 }
123
124 //--------------------------------------
125
126 DebugModuleManager* DebugModuleManager::m_instance = 0;
127
128 DebugModuleManager::DebugModuleManager()
129     : mb_initialized(0)
130     , mb_inbuffer(0)
131     , mb_outbuffer(0)
132     , mb_overruns(0)
133
134 {
135
136 }
137
138 DebugModuleManager::~DebugModuleManager()
139 {
140         // cleanin up leftover modules
141     for ( DebugModuleVectorIterator it = m_debugModules.begin();
142           it != m_debugModules.end();
143           ++it )
144     {
145         fprintf(stderr,"Cleaning up leftover debug module: %s\n",(*it)->getName().c_str());
146         m_debugModules.erase( it );
147         delete *it;
148     }
149
150         if (!mb_initialized)
151                 return;
152
153         pthread_mutex_lock(&mb_write_lock);
154         mb_initialized = 0;
155         pthread_cond_signal(&mb_ready_cond);
156         pthread_mutex_unlock(&mb_write_lock);
157
158         pthread_join(mb_writer_thread, NULL);
159         mb_flush();
160
161         if (mb_overruns)
162                 fprintf(stderr, "WARNING: %d message buffer overruns!\n",
163                         mb_overruns);
164         else
165                 fprintf(stderr, "no message buffer overruns\n");
166
167         pthread_mutex_destroy(&mb_write_lock);
168         pthread_cond_destroy(&mb_ready_cond);
169
170 }
171
172 bool
173 DebugModuleManager::init()
174 {
175         if (mb_initialized)
176                 return true;
177                
178         fprintf(stderr, "DebugModuleManager init...\n");
179
180         pthread_mutex_init(&mb_write_lock, NULL);
181         pthread_cond_init(&mb_ready_cond, NULL);
182
183         mb_overruns = 0;
184         mb_initialized = 1;
185
186         if (pthread_create(&mb_writer_thread, NULL, &mb_thread_func, (void *)this) != 0)
187                 mb_initialized = 0;
188
189     return true;
190 }
191
192 DebugModuleManager*
193 DebugModuleManager::instance()
194 {
195     if ( !m_instance ) {
196         m_instance = new DebugModuleManager;
197         if ( !m_instance ) {
198             cerr << "DebugModuleManager::instance Failed to create "
199                  << "DebugModuleManager" << endl;
200         }
201         if ( !m_instance->init() ) {
202             cerr << "DebugModuleManager::instance Failed to init "
203                  << "DebugModuleManager" << endl;
204         }
205     }
206     return m_instance;
207 }
208
209 bool
210 DebugModuleManager::registerModule( DebugModule& debugModule )
211 {
212     m_debugModules.push_back( &debugModule );
213     return true;
214 }
215
216 bool
217 DebugModuleManager::unregisterModule( DebugModule& debugModule )
218 {
219     for ( DebugModuleVectorIterator it = m_debugModules.begin();
220           it != m_debugModules.end();
221           ++it )
222     {
223         if ( *it == &debugModule ) {
224             m_debugModules.erase( it );
225             return true;
226         }
227     }
228
229     cerr << "DebugModuleManager::unregisterModule: Could not unregister "
230          << "DebugModule (" << debugModule.getName() << ")" << endl;
231     return false;
232 }
233
234 bool
235 DebugModuleManager::setMgrDebugLevel( std::string name, debug_level_t level )
236 {
237     for ( DebugModuleVectorIterator it = m_debugModules.begin();
238           it != m_debugModules.end();
239           ++it )
240     {
241         if ( (*it)->getName() == name ) {
242             return (*it)->setLevel( level );
243         }
244     }
245
246     cerr << "setDebugLevel: Did not find DebugModule ("
247          << name << ")" << endl;
248     return false;
249 }
250
251
252 void
253 DebugModuleManager::mb_flush()
254 {
255         /* called WITHOUT the mb_write_lock */
256         while (mb_outbuffer != mb_inbuffer) {
257                 fputs(mb_buffers[mb_outbuffer], stderr);
258                 mb_outbuffer = MB_NEXT(mb_outbuffer);
259         }
260 }
261
262 void *
263 DebugModuleManager::mb_thread_func(void *arg)
264 {
265
266     DebugModuleManager *m=static_cast<DebugModuleManager *>(arg);
267    
268         /* The mutex is only to eliminate collisions between multiple
269          * writer threads and protect the condition variable. */
270         pthread_mutex_lock(&m->mb_write_lock);
271
272         while (m->mb_initialized) {
273                 pthread_cond_wait(&m->mb_ready_cond, &m->mb_write_lock);
274  
275                 /* releasing the mutex reduces contention */
276                 pthread_mutex_unlock(&m->mb_write_lock);
277                 m->mb_flush();
278                 pthread_mutex_lock(&m->mb_write_lock);
279         }
280
281         pthread_mutex_unlock(&m->mb_write_lock);
282
283         return NULL;
284 }
285
286 void
287 DebugModuleManager::print(const char *fmt, ...)
288 {
289         char msg[MB_BUFFERSIZE];
290         va_list ap;
291
292         /* format the message first, to reduce lock contention */
293         va_start(ap, fmt);
294         vsnprintf(msg, MB_BUFFERSIZE, fmt, ap);
295         va_end(ap);
296
297         if (!mb_initialized) {
298                 /* Unable to print message with realtime safety.
299                  * Complain and print it anyway. */
300                 fprintf(stderr, "ERROR: messagebuffer not initialized: %s",
301                         msg);
302                 return;
303         }
304         if (pthread_mutex_trylock(&mb_write_lock) == 0) {
305                 strncpy(mb_buffers[mb_inbuffer], msg, MB_BUFFERSIZE);
306                 mb_inbuffer = MB_NEXT(mb_inbuffer);
307                 pthread_cond_signal(&mb_ready_cond);
308                 pthread_mutex_unlock(&mb_write_lock);
309         } else {                        /* lock collision */
310 //              atomic_add(&mb_overruns, 1);
311                 // FIXME: atomicity
312                 mb_overruns++; // skip the atomicness for now
313         }
314 }
315
316
317 void
318 DebugModuleManager::va_print (const char *fmt, va_list ap)
319 {
320         char msg[MB_BUFFERSIZE];
321        
322         /* format the message first, to reduce lock contention */
323         vsnprintf(msg, MB_BUFFERSIZE, fmt, ap);
324
325         if (!mb_initialized) {
326                 /* Unable to print message with realtime safety.
327                  * Complain and print it anyway. */
328                 fprintf(stderr, "ERROR: messagebuffer not initialized: %s",
329                         msg);
330                 return;
331         }
332
333         if (pthread_mutex_trylock(&mb_write_lock) == 0) {
334                 strncpy(mb_buffers[mb_inbuffer], msg, MB_BUFFERSIZE);
335                 mb_inbuffer = MB_NEXT(mb_inbuffer);
336                 pthread_cond_signal(&mb_ready_cond);
337                 pthread_mutex_unlock(&mb_write_lock);
338         } else {                        /* lock collision */
339 //              atomic_add(&mb_overruns, 1);
340                 // FIXME: atomicity
341                 mb_overruns++; // skip the atomicness for now
342         }
343 }
344
345 //----------------------------------------
346
347 unsigned char
348 toAscii( unsigned char c )
349 {
350     if ( ( c > 31 ) && ( c < 126) ) {
351         return c;
352     } else {
353         return '.';
354     }
355 }
356
357 /* converts a quadlet to a uchar * buffer
358  * not implemented optimally, but clear
359  */
360 void
361 quadlet2char( quadlet_t quadlet, unsigned char* buff )
362 {
363     *(buff)   = (quadlet>>24)&0xFF;
364     *(buff+1) = (quadlet>>16)&0xFF;
365     *(buff+2) = (quadlet>> 8)&0xFF;
366     *(buff+3) = (quadlet)    &0xFF;
367 }
368
369 void
370 hexDump( unsigned char *data_start, unsigned int length )
371 {
372     unsigned int i=0;
373     unsigned int byte_pos;
374     unsigned int bytes_left;
375
376     if ( length <= 0 ) {
377         return;
378     }
379     if ( length >= 7 ) {
380         for ( i = 0; i < (length-7); i += 8 ) {
381             printf( "%04X: %02X %02X %02X %02X %02X %02X %02X %02X "
382                     "- [%c%c%c%c%c%c%c%c]\n",
383
384                     i,
385
386                     *(data_start+i+0),
387                     *(data_start+i+1),
388                     *(data_start+i+2),
389                     *(data_start+i+3),
390                     *(data_start+i+4),
391                     *(data_start+i+5),
392                     *(data_start+i+6),
393                     *(data_start+i+7),
394
395                     toAscii( *(data_start+i+0) ),
396                     toAscii( *(data_start+i+1) ),
397                     toAscii( *(data_start+i+2) ),
398                     toAscii( *(data_start+i+3) ),
399                     toAscii( *(data_start+i+4) ),
400                     toAscii( *(data_start+i+5) ),
401                     toAscii( *(data_start+i+6) ),
402                     toAscii( *(data_start+i+7) )
403                 );
404         }
405     }
406     byte_pos = i;
407     bytes_left = length - byte_pos;
408
409     printf( "%04X:" ,i );
410     for ( i = byte_pos; i < length; i += 1 ) {
411         printf( " %02X", *(data_start+i) );
412     }
413     for ( i=0; i < 8-bytes_left; i+=1 ) {
414         printf( "   " );
415     }
416
417     printf( " - [" );
418     for ( i = byte_pos; i < length; i += 1) {
419         printf( "%c", toAscii(*(data_start+i)));
420     }
421     for ( i = 0; i < 8-bytes_left; i += 1) {
422         printf( " " );
423     }
424
425     printf( "]" );
426     printf( "\n" );
427 }
428
429 void
430 hexDumpQuadlets( quadlet_t *data, unsigned int length )
431 {
432     unsigned int i=0;
433
434     if ( length <= 0 ) {
435         return;
436     }
437     for (i = 0; i< length; i += 1) {
438         printf( "%02d %04X: %08X (%08X)"
439                 "\n", i, i*4, data[i],ntohl(data[i]));
440     }
441 }
442
443
Note: See TracBrowser for help on using the browser.