root/branches/libffado-2.0/src/debugmodule/debugmodule.h

Revision 1567, 14.4 kB (checked in by holin, 14 years ago)

more gcc 4.4 fixes

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