root/trunk/libffado/src/debugmodule/debugmodule.h

Revision 1535, 14.9 kB (checked in by ppalmers, 14 years ago)

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

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * Copyright (C) 2005-2008 by Daniel Wagner
3  * Copyright (C) 2005-2008 by Pieter Palmers
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 2 of the License, or
13  * (at your option) version 3 of the License.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #ifndef DEBUGMODULE_H
26 #define DEBUGMODULE_H
27
28 #include "config_debug.h"
29
30 #include "../fbtypes.h"
31 #include <assert.h>
32
33 #include <vector>
34 #include <iostream>
35 #include <semaphore.h>
36
37 #define FFADO_ASSERT(x) { \
38     if(!(x)) { \
39         m_debugModule.print( DebugModule::eDL_Fatal,        \
40                                 __FILE__,                   \
41                                 __FUNCTION__,               \
42                                 __LINE__,                   \
43                                 "Assertion failed...\n");      \
44         debugPrintBacktrace( 10 ); \
45         DebugModuleManager::instance()->flush(); \
46         assert(x); \
47     }}
48
49 typedef short debug_level_t;
50
51 #define DEBUG_LEVEL_MESSAGE        0
52 #define DEBUG_LEVEL_FATAL          1
53 #define DEBUG_LEVEL_ERROR          2
54 #define DEBUG_LEVEL_WARNING        3
55 #define DEBUG_LEVEL_NORMAL         4
56 #define DEBUG_LEVEL_INFO           5
57 #define DEBUG_LEVEL_VERBOSE        6
58 #define DEBUG_LEVEL_VERY_VERBOSE   7
59 #define DEBUG_LEVEL_ULTRA_VERBOSE  8
60
61 /* MB_NEXT() relies on the fact that MB_BUFFERS is a power of two */
62 #define MB_NEXT(index)      (((index)+1) & (DEBUG_MB_BUFFERS-1))
63 #define MB_BUFFERSIZE       DEBUG_MAX_MESSAGE_LENGTH
64
65 // no backtrace support when not debugging
66 #ifndef DEBUG
67     #undef DEBUG_BACKTRACE_SUPPORT
68     #define DEBUG_BACKTRACE_SUPPORT 0
69 #endif
70
71 // no backlog support when not debugging
72 #ifndef DEBUG
73     #undef DEBUG_BACKLOG_SUPPORT
74     #define DEBUG_BACKLOG_SUPPORT 0
75 #endif
76
77 // the backlog is a similar buffer as the message buffer
78 #define DEBUG_BACKLOG_MB_NEXT(index)  (((index)+1) & (DEBUG_BACKLOG_MB_BUFFERS-1))
79 #define DEBUG_BACKLOG_MIN_LEVEL       DEBUG_LEVEL_VERY_VERBOSE
80
81 #define debugFatal( format, args... )                               \
82                 m_debugModule.print( DebugModule::eDL_Fatal,        \
83                                      __FILE__,                      \
84                                      __FUNCTION__,                  \
85                                      __LINE__,                      \
86                                      format,                        \
87                                      ##args )
88 #define debugError( format, args... )                               \
89                 m_debugModule.print( DebugModule::eDL_Error,        \
90                                      __FILE__,                      \
91                                      __FUNCTION__,                  \
92                                      __LINE__,                      \
93                                      format,                        \
94                                      ##args )
95 #define debugWarning( format, args... )                             \
96                 m_debugModule.print( DebugModule::eDL_Warning,      \
97                                      __FILE__,                      \
98                                      __FUNCTION__,                  \
99                                      __LINE__,                      \
100                                     format,                         \
101                                     ##args )
102
103 #define debugFatalShort( format, args... )                          \
104                 m_debugModule.printShort( DebugModule::eDL_Fatal,   \
105                                      format,                        \
106                                      ##args )
107 #define debugErrorShort( format, args... )                          \
108                 m_debugModule.printShort( DebugModule::eDL_Error,   \
109                                      format,                        \
110                                      ##args )
111 #define debugWarningShort( format, args... )                        \
112                 m_debugModule.printShort( DebugModule::eDL_Warning, \
113                                      format,                        \
114                                      ##args )
115
116 // these are for messages that are also displayed when not compiled
117 // for debug
118 #ifdef DEBUG
119 #define printMessage( format, args... )                             \
120                 m_debugModule.print( DebugModule::eDL_Message,      \
121                                      __FILE__,                      \
122                                      __FUNCTION__,                  \
123                                      __LINE__,                      \
124                                     format,                         \
125                                     ##args )
126 #else
127 #define printMessage( format, args... )                             \
128                 m_debugModule.printShort( DebugModule::eDL_Message,      \
129                                     format,                         \
130                                     ##args )
131 #endif
132 #define printMessageShort( format, args... )                        \
133                 m_debugModule.printShort( DebugModule::eDL_Message, \
134                                      format,                        \
135                                      ##args )
136
137 #define DECLARE_DEBUG_MODULE static DebugModule m_debugModule
138 #define DECLARE_DEBUG_MODULE_REFERENCE DebugModule &m_debugModule
139 #define IMPL_DEBUG_MODULE( ClassName, RegisterName, Level )        \
140                 DebugModule ClassName::m_debugModule =             \
141                     DebugModule( #RegisterName, Level )
142
143 #define DECLARE_GLOBAL_DEBUG_MODULE extern DebugModule m_debugModule
144 #define IMPL_GLOBAL_DEBUG_MODULE( RegisterName, Level )            \
145                 DebugModule m_debugModule =                        \
146             DebugModule( #RegisterName, Level )
147
148 #define setDebugLevel( Level ) {                                    \
149                 m_debugModule.setLevel( Level ); \
150                 }
151
152 /*                m_debugModule.print( eDL_Normal,                        \
153                                      __FILE__,                     \
154                                      __FUNCTION__,                 \
155                                      __LINE__,                     \
156                                      "Setting debug level to %d\n",  \
157                                      Level ); \
158                 }*/
159
160 #define getDebugLevel(  )                                     \
161                 m_debugModule.getLevel( )
162
163 #define flushDebugOutput()      DebugModuleManager::instance()->flush()
164
165 #if DEBUG_BACKLOG_SUPPORT
166
167 #define debugShowBackLog() \
168     {                                                       \
169         m_debugModule.print( DebugModule::eDL_Warning,      \
170                              __FILE__,                      \
171                              __FUNCTION__,                  \
172                              __LINE__,                      \
173                              "Backlog print requested\n");  \
174         DebugModuleManager::instance()->showBackLog();      \
175     }
176 #define debugShowBackLogLines(x) \
177     {                                                       \
178         m_debugModule.print( DebugModule::eDL_Warning,      \
179                              __FILE__,                      \
180                              __FUNCTION__,                  \
181                              __LINE__,                      \
182                              "Backlog print requested\n");  \
183         DebugModuleManager::instance()->showBackLog(x);     \
184     }
185
186 #else
187 #define debugShowBackLog()
188 #define debugShowBackLogLines(x)
189
190 #endif
191
192 #ifdef DEBUG
193
194     #define debugOutput( level, format, args... )                  \
195                 m_debugModule.print( level,                        \
196                                      __FILE__,                     \
197                                      __FUNCTION__,                 \
198                                      __LINE__,                     \
199                                      format,                       \
200                                      ##args )
201
202     #define debugOutputShort( level, format, args... )             \
203                 m_debugModule.printShort( level,                   \
204                                      format,                       \
205                                      ##args )
206     #define DEBUG_NORMAL( x ) x;
207
208     #if DEBUG_EXTREME_ENABLE
209         #define debugOutputExtreme( level, format, args... )           \
210                     m_debugModule.print( level,                        \
211                                         __FILE__,                     \
212                                         __FUNCTION__,                 \
213                                         __LINE__,                     \
214                                         format,                       \
215                                         ##args )
216         #define debugOutputShortExtreme( level, format, args... )      \
217                     m_debugModule.printShort( level,                   \
218                                         format,                       \
219                                         ##args )
220         #define DEBUG_EXTREME( x ) x;
221     #else
222         #define debugOutputExtreme( level, format, args... )
223         #define debugOutputShortExtreme( level, format, args... )
224         #define DEBUG_EXTREME( x )
225     #endif
226
227 #else
228
229     #define debugOutput( level, format, args... )
230     #define debugOutputShort( level, format, args... )
231     #define DEBUG_NORMAL( x )
232
233     #define debugOutputExtreme( level, format, args... )
234     #define debugOutputShortExtreme( level, format, args... )
235     #define DEBUG_EXTREME( x )
236
237 #endif
238
239 /* Enable preemption checking for Linux Realtime Preemption kernels.
240  *
241  * This checks if any RT-safe code section does anything to cause CPU
242  * preemption.  Examples are sleep() or other system calls that block.
243  * If a problem is detected, the kernel writes a syslog entry, and
244  * sends SIGUSR2 to the client.
245  */
246
247 // #define DO_PREEMPTION_CHECKING
248
249 #include <sys/time.h>
250
251 #ifdef DO_PREEMPTION_CHECKING
252 #define CHECK_PREEMPTION(onoff) \
253     gettimeofday((struct timeval *)1, (struct timezone *)onoff)
254 #else
255 #define CHECK_PREEMPTION(onoff)
256 #endif
257
258 /*
259  * Backtrace support
260  */
261 #if DEBUG_BACKTRACE_SUPPORT
262     #define debugPrintBacktrace( _SIZE_ )                       \
263         DebugModuleManager::instance()->printBacktrace( _SIZE_ );
264     #define debugBacktraceGet( _ID_ )                       \
265         DebugModuleManager::instance()->getBacktracePtr( _ID_ );
266     #define debugGetFunctionNameFromAddr( _ADDR_, _BUFF_, _MAX_SIZE_ )              \
267         DebugModuleManager::instance()->getFunctionName( _ADDR_, _BUFF_, _MAX_SIZE_ );
268 #else
269     #define debugPrintBacktrace( _SIZE_ )
270     #define debugBacktraceGet( _ID_ )       NULL
271     #define debugGetFunctionNameFromAddr( _ADDR_, _BUFF_, _MAX_SIZE_ )
272 #endif
273
274 /*
275  * helper functions
276  */
277
278 unsigned char toAscii( unsigned char c );
279 void quadlet2char( fb_quadlet_t quadlet, unsigned char* buff );
280 void hexDump( unsigned char *data_start, unsigned int length );
281 void hexDumpQuadlets( quadlet_t *data_start, unsigned int length );
282
283 class DebugModule {
284 public:
285     enum {
286         eDL_Message      = DEBUG_LEVEL_MESSAGE,
287         eDL_Fatal        = DEBUG_LEVEL_FATAL,
288         eDL_Error        = DEBUG_LEVEL_ERROR,
289         eDL_Warning      = DEBUG_LEVEL_WARNING,
290         eDL_Normal       = DEBUG_LEVEL_NORMAL,
291         eDL_Info         = DEBUG_LEVEL_INFO,
292         eDL_Verbose      = DEBUG_LEVEL_VERBOSE,
293         eDL_VeryVerbose  = DEBUG_LEVEL_VERY_VERBOSE,
294         eDL_UltraVerbose = DEBUG_LEVEL_ULTRA_VERBOSE,
295     } EDebugLevel;
296
297     DebugModule( std::string name, debug_level_t level );
298     virtual ~DebugModule();
299
300     void printShort( debug_level_t level,
301                      const char* format,
302                      ... ) const;
303
304     void print( debug_level_t level,
305                 const char*   file,
306                 const char*   function,
307                 unsigned int  line,
308                 const char*   format,
309                 ... ) const;
310
311     bool setLevel( debug_level_t level )
312         { m_level = level; return true; }
313     debug_level_t getLevel()
314         { return m_level; }
315     std::string getName()
316         { return m_name; }
317
318 protected:
319     const char* getPreSequence( debug_level_t level ) const;
320     const char* getPostSequence( debug_level_t level ) const;
321
322 private:
323     std::string   m_name;
324     debug_level_t m_level;
325 };
326
327
328 class DebugModuleManager {
329 public:
330     friend class DebugModule;
331
332     static DebugModuleManager* instance();
333     ~DebugModuleManager();
334
335     bool setMgrDebugLevel( std::string name, debug_level_t level );
336
337     void flush();
338
339 #if DEBUG_BACKLOG_SUPPORT
340     // the backlog is a ringbuffer of all the messages
341     // that have been recorded using the debugPrint
342     // statements, regardless of the debug level.
343     // This is useful to obtain more debug info
344     // when something goes wrong without having too
345     // much output in normal operation
346     void showBackLog();
347     void showBackLog(int nblines);
348 #endif
349
350 #if DEBUG_BACKTRACE_SUPPORT
351     void printBacktrace(int len);
352     void *getBacktracePtr(int id);
353     void getFunctionName( void *, char *, int );
354 #endif
355
356 protected:
357     bool registerModule( DebugModule& debugModule );
358     bool unregisterModule( DebugModule& debugModule );
359
360     bool init();
361
362     void print(const char *msg);
363
364 #if DEBUG_BACKLOG_SUPPORT
365     void backlog_print(const char *msg);
366 #endif
367
368 private:
369     DebugModuleManager();
370
371     typedef std::vector< DebugModule* > DebugModuleVector;
372     typedef std::vector< DebugModule* >::iterator DebugModuleVectorIterator;
373
374     unsigned int mb_initialized;
375
376 #if DEBUG_USE_MESSAGE_BUFFER
377     char mb_buffers[DEBUG_MB_BUFFERS][MB_BUFFERSIZE];
378     unsigned int mb_inbuffer;
379     unsigned int mb_outbuffer;
380     unsigned int mb_overruns;
381     pthread_t mb_writer_thread;
382     pthread_mutex_t mb_write_lock;
383     pthread_mutex_t mb_flush_lock;
384     sem_t        mb_writes;
385 #endif
386
387 #if DEBUG_BACKTRACE_SUPPORT
388     pthread_mutex_t m_backtrace_lock;
389     char m_backtrace_strbuffer[MB_BUFFERSIZE];
390     void *m_backtrace_buffer[DEBUG_MAX_BACKTRACE_LENGTH];
391     void *m_backtrace_buffer_seen[DEBUG_MAX_BACKTRACE_FUNCTIONS_SEEN];
392     int m_backtrace_buffer_nb_seen;
393 #endif
394
395     static void *mb_thread_func(void *arg);
396     void mb_flush();
397
398 #if DEBUG_BACKLOG_SUPPORT
399     // the backlog
400     char bl_mb_buffers[DEBUG_BACKLOG_MB_BUFFERS][MB_BUFFERSIZE];
401     unsigned int bl_mb_inbuffer;
402     pthread_mutex_t bl_mb_write_lock;
403 #endif
404
405     static DebugModuleManager* m_instance;
406     DebugModuleVector          m_debugModules;
407 };
408
409 #endif
Note: See TracBrowser for help on using the browser.