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

Revision 866, 12.8 kB (checked in by ppalmers, 16 years ago)

- weed out some unused functions
- introduce 'debugOutputExtreme' allowing to disable debug statements in the speed-sensitive sections. This should reduce the cpu load on a 'normal' debug build significantly.

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