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

Revision 790, 11.5 kB (checked in by ppalmers, 13 years ago)

add debugging code

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