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

Revision 1046, 13.9 kB (checked in by ppalmers, 15 years ago)

debug message cleanup. move #defines into config.h.in.

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