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

Revision 1201, 14.4 kB (checked in by ppalmers, 15 years ago)

fix some deadlock issues on the control code (cfr #114)

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