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

Revision 859, 11.6 kB (checked in by ppalmers, 13 years ago)

enable/disable backlog from 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-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 "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
188 #else
189
190     #define debugOutput( level, format, args... )
191     #define debugOutputShort( level, format, args... )
192
193 #endif
194
195 /* Enable preemption checking for Linux Realtime Preemption kernels.
196  *
197  * This checks if any RT-safe code section does anything to cause CPU
198  * preemption.  Examples are sleep() or other system calls that block.
199  * If a problem is detected, the kernel writes a syslog entry, and
200  * sends SIGUSR2 to the client.
201  */
202
203 // #define DO_PREEMPTION_CHECKING
204
205 #include <sys/time.h>
206
207 #ifdef DO_PREEMPTION_CHECKING
208 #define CHECK_PREEMPTION(onoff) \
209     gettimeofday((struct timeval *)1, (struct timezone *)onoff)
210 #else
211 #define CHECK_PREEMPTION(onoff)
212 #endif
213
214 unsigned char toAscii( unsigned char c );
215 void quadlet2char( fb_quadlet_t quadlet, unsigned char* buff );
216 void hexDump( unsigned char *data_start, unsigned int length );
217 void hexDumpQuadlets( quadlet_t *data_start, unsigned int length );
218
219 class DebugModule {
220 public:
221     enum {
222         eDL_Message      = DEBUG_LEVEL_MESSAGE,
223         eDL_Fatal        = DEBUG_LEVEL_FATAL,
224         eDL_Error        = DEBUG_LEVEL_ERROR,
225         eDL_Warning      = DEBUG_LEVEL_WARNING,
226         eDL_Normal       = DEBUG_LEVEL_NORMAL,
227         eDL_Info         = DEBUG_LEVEL_INFO,
228         eDL_Verbose      = DEBUG_LEVEL_VERBOSE,
229         eDL_VeryVerbose  = DEBUG_LEVEL_VERY_VERBOSE,
230         eDL_UltraVerbose = DEBUG_LEVEL_ULTRA_VERBOSE,
231     } EDebugLevel;
232
233     DebugModule( std::string name, debug_level_t level );
234     virtual ~DebugModule();
235
236     void printShort( debug_level_t level,
237                      const char* format,
238                      ... ) const;
239
240     void print( debug_level_t level,
241                 const char*   file,
242                 const char*   function,
243                 unsigned int  line,
244                 const char*   format,
245                 ... ) const;
246
247     bool setLevel( debug_level_t level )
248         { m_level = level; return true; }
249     debug_level_t getLevel()
250         { return m_level; }
251     std::string getName()
252         { return m_name; }
253
254 protected:
255     const char* getPreSequence( debug_level_t level ) const;
256     const char* getPostSequence( debug_level_t level ) const;
257
258 private:
259     std::string   m_name;
260     debug_level_t m_level;
261 };
262
263
264 class DebugModuleManager {
265 public:
266     friend class DebugModule;
267
268     static DebugModuleManager* instance();
269     ~DebugModuleManager();
270
271     bool setMgrDebugLevel( std::string name, debug_level_t level );
272
273     void flush();
274
275     // the backlog is a ringbuffer of all the messages
276     // that have been recorded using the debugPrint
277     // statements, regardless of the debug level.
278     // This is useful to obtain more debug info
279     // when something goes wrong without having too
280     // much output in normal operation
281     void showBackLog();
282     void showBackLog(int nblines);
283
284 protected:
285     bool registerModule( DebugModule& debugModule );
286     bool unregisterModule( DebugModule& debugModule );
287
288     bool init();
289
290     void print(const char *msg);
291     void backlog_print(const char *msg);
292
293 private:
294     DebugModuleManager();
295
296     typedef std::vector< DebugModule* > DebugModuleVector;
297     typedef std::vector< DebugModule* >::iterator DebugModuleVectorIterator;
298
299     char mb_buffers[MB_BUFFERS][MB_BUFFERSIZE];
300     unsigned int mb_initialized;
301     unsigned int mb_inbuffer;
302     unsigned int mb_outbuffer;
303     unsigned int mb_overruns;
304     pthread_t mb_writer_thread;
305     pthread_mutex_t mb_write_lock;
306     pthread_mutex_t mb_flush_lock;
307     pthread_cond_t mb_ready_cond;
308
309     static void *mb_thread_func(void *arg);
310     void mb_flush();
311
312 #ifdef IMPLEMENT_BACKLOG
313     // the backlog
314     char bl_mb_buffers[BACKLOG_MB_BUFFERS][MB_BUFFERSIZE];
315     unsigned int bl_mb_inbuffer;
316     pthread_mutex_t bl_mb_write_lock;
317 #endif
318
319     static DebugModuleManager* m_instance;
320     DebugModuleVector          m_debugModules;
321 };
322
323 #endif
Note: See TracBrowser for help on using the browser.