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

Revision 944, 13.1 kB (checked in by arnonym, 16 years ago)

Second half of #70. printMessage is now the full version when debug is enabled and equals printMessaheShort when debug is off...

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