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

Revision 1568, 14.9 kB (checked in by holin, 14 years ago)

gcc 4.4 fixes (r1566, r1567, DICE) to trunk

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